From 238bb38a948ddf3d782f8138b39868cb08356c91 Mon Sep 17 00:00:00 2001 From: Christian Poveda Date: Thu, 22 Feb 2018 13:53:59 -0500 Subject: [PATCH 01/68] First version --- src/libcore/cell.rs | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/libcore/cell.rs b/src/libcore/cell.rs index ec0d1b704dce..75ed562ae540 100644 --- a/src/libcore/cell.rs +++ b/src/libcore/cell.rs @@ -10,10 +10,24 @@ //! Shareable mutable containers. //! +//! Rust memory safety is based on this rule: Given an object `T`, is only possible to +//! have one of the following: +//! +//! - Having several inmutable references (`&T`) to the object (also know as Aliasing). +//! - Having one mutable reference (`&mut T`) to the object (also know as Mutability). +//! +//! This is enforced by the Rust compiler. However, there are situations where this rule is not +//! flexible enough. Sometimes is required to have multiple references to an object and yet +//! mutate it. +//! +//! Shareable mutable containers exist to permit mutability in presence of aliasing in a +//! controlled manner. Both `Cell` and `RefCell` allows to do this in a single threaded +//! way. For multiple threads is possible to use `Mutex`, `RwLock` or `AtomicXXX`. +//! //! Values of the `Cell` and `RefCell` types may be mutated through shared references (i.e. //! the common `&T` type), whereas most Rust types can only be mutated through unique (`&mut T`) //! references. We say that `Cell` and `RefCell` provide 'interior mutability', in contrast -//! with typical Rust types that exhibit 'inherited mutability'. +//! with typical Rust types that exhibit 'inherited mutability'. //! //! Cell types come in two flavors: `Cell` and `RefCell`. `Cell` implements interior //! mutability by moving values in and out of the `Cell`. To use references instead of values, From f9e049afc544e70dc595df67d878b52c098aaa9a Mon Sep 17 00:00:00 2001 From: Christian Poveda Date: Fri, 23 Feb 2018 12:57:18 -0500 Subject: [PATCH 02/68] add info about sync --- src/libcore/cell.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/libcore/cell.rs b/src/libcore/cell.rs index 75ed562ae540..1067b6ff0c11 100644 --- a/src/libcore/cell.rs +++ b/src/libcore/cell.rs @@ -22,7 +22,9 @@ //! //! Shareable mutable containers exist to permit mutability in presence of aliasing in a //! controlled manner. Both `Cell` and `RefCell` allows to do this in a single threaded -//! way. For multiple threads is possible to use `Mutex`, `RwLock` or `AtomicXXX`. +//! way, you can mutate them using an inmutable reference. However, neither `Cell` nor +//! `RefCell` are thread safe (they do not implement `Sync`), if you need to do Aliasing and +//! Mutation between multiple threads is possible to use `Mutex`, `RwLock` or `AtomicXXX`. //! //! Values of the `Cell` and `RefCell` types may be mutated through shared references (i.e. //! the common `&T` type), whereas most Rust types can only be mutated through unique (`&mut T`) From 58d1f839520b97ac06e48aeb49d814282b20056c Mon Sep 17 00:00:00 2001 From: Christian Poveda Date: Fri, 23 Feb 2018 13:00:26 -0500 Subject: [PATCH 03/68] remove redundant info --- 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 1067b6ff0c11..b3a7d20c4aa5 100644 --- a/src/libcore/cell.rs +++ b/src/libcore/cell.rs @@ -17,19 +17,19 @@ //! - Having one mutable reference (`&mut T`) to the object (also know as Mutability). //! //! This is enforced by the Rust compiler. However, there are situations where this rule is not -//! flexible enough. Sometimes is required to have multiple references to an object and yet +//! flexible enough. Sometimes is required to have multiple references to an object and yet //! mutate it. //! //! Shareable mutable containers exist to permit mutability in presence of aliasing in a //! controlled manner. Both `Cell` and `RefCell` allows to do this in a single threaded -//! way, you can mutate them using an inmutable reference. However, neither `Cell` nor -//! `RefCell` are thread safe (they do not implement `Sync`), if you need to do Aliasing and -//! Mutation between multiple threads is possible to use `Mutex`, `RwLock` or `AtomicXXX`. +//! way. However, neither `Cell` nor `RefCell` are thread safe (they do not implement +//! `Sync`), if you need to do Aliasing and Mutation between multiple threads is possible to use +//! `Mutex`, `RwLock` or `AtomicXXX`. //! //! Values of the `Cell` and `RefCell` types may be mutated through shared references (i.e. //! the common `&T` type), whereas most Rust types can only be mutated through unique (`&mut T`) //! references. We say that `Cell` and `RefCell` provide 'interior mutability', in contrast -//! with typical Rust types that exhibit 'inherited mutability'. +//! with typical Rust types that exhibit 'inherited mutability'. //! //! Cell types come in two flavors: `Cell` and `RefCell`. `Cell` implements interior //! mutability by moving values in and out of the `Cell`. To use references instead of values, From 43de01f97eeee13f9bf9f19b0b241e8368633d11 Mon Sep 17 00:00:00 2001 From: Christian Poveda Date: Fri, 23 Feb 2018 15:12:28 -0500 Subject: [PATCH 04/68] cleaned trailing whitespaces --- src/libcore/cell.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libcore/cell.rs b/src/libcore/cell.rs index b3a7d20c4aa5..6f0655f2033e 100644 --- a/src/libcore/cell.rs +++ b/src/libcore/cell.rs @@ -20,9 +20,9 @@ //! flexible enough. Sometimes is required to have multiple references to an object and yet //! mutate it. //! -//! Shareable mutable containers exist to permit mutability in presence of aliasing in a +//! Shareable mutable containers exist to permit mutability in presence of aliasing in a //! controlled manner. Both `Cell` and `RefCell` allows to do this in a single threaded -//! way. However, neither `Cell` nor `RefCell` are thread safe (they do not implement +//! way. However, neither `Cell` nor `RefCell` are thread safe (they do not implement //! `Sync`), if you need to do Aliasing and Mutation between multiple threads is possible to use //! `Mutex`, `RwLock` or `AtomicXXX`. //! From 5344b07addf342334470778964d863d99eec7430 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 24 Feb 2018 16:50:44 +0100 Subject: [PATCH 05/68] Add new warning for CStr::from_ptr --- src/libstd/ffi/c_str.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/libstd/ffi/c_str.rs b/src/libstd/ffi/c_str.rs index 2519d8304355..c88c2bc91371 100644 --- a/src/libstd/ffi/c_str.rs +++ b/src/libstd/ffi/c_str.rs @@ -875,6 +875,8 @@ impl CStr { /// `ptr`. /// * There is no guarantee that the memory pointed to by `ptr` contains a /// valid nul terminator byte at the end of the string. + /// * It is not guaranteed that the memory pointed by `ptr` won't change + /// before the `CStr` has been destroyed. /// /// > **Note**: This operation is intended to be a 0-cost cast but it is /// > currently implemented with an up-front calculation of the length of From bbd64b256320013d02734504c744cd3c0b180ebf Mon Sep 17 00:00:00 2001 From: Phlosioneer Date: Sat, 24 Feb 2018 11:37:38 -0500 Subject: [PATCH 06/68] Slight modification to the as_ref example of std::option::Option A user in a reddit thread was confused by the name of the variable "num_as_int"; they thought the example was trying to convert the string "10" as if it were binary 2 by calling str::len(). In reality, the example is simply demonstrating how to take an immutable reference to the value of an Option. The confusion comes from the coincidence that the length of the string "10" is also its binary representation, and the implication from the variable names that a conversion was occuring ("num_as_str" to "num_as_int"). This PR changes the example number to 12 instead of 10, and changes the variable name from "num_as_int" to "num_length" to better communicate what the example is doing. The reddit thread: https://www.reddit.com/r/rust/comments/7zpvev/notyetawesome_rust_what_use_cases_would_you_like/dur39xw/ --- src/libcore/option.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libcore/option.rs b/src/libcore/option.rs index b8fe28d0f0d7..96b551d8704a 100644 --- a/src/libcore/option.rs +++ b/src/libcore/option.rs @@ -233,10 +233,10 @@ impl Option { /// [`usize`]: ../../std/primitive.usize.html /// /// ``` - /// let num_as_str: Option = Some("10".to_string()); + /// let num_as_str: Option = Some("12".to_string()); /// // First, cast `Option` to `Option<&String>` with `as_ref`, /// // then consume *that* with `map`, leaving `num_as_str` on the stack. - /// let num_as_int: Option = num_as_str.as_ref().map(|n| n.len()); + /// let num_length: Option = num_as_str.as_ref().map(|n| n.len()); /// println!("still can print num_as_str: {:?}", num_as_str); /// ``` #[inline] From ce3ad263ff085ac15016430de5f4abb154427433 Mon Sep 17 00:00:00 2001 From: Christian Poveda Date: Sat, 24 Feb 2018 18:04:08 -0500 Subject: [PATCH 07/68] added link to sync containers --- src/libcore/cell.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/libcore/cell.rs b/src/libcore/cell.rs index 6f0655f2033e..91074c18d771 100644 --- a/src/libcore/cell.rs +++ b/src/libcore/cell.rs @@ -24,7 +24,8 @@ //! controlled manner. Both `Cell` and `RefCell` allows to do this in a single threaded //! way. However, neither `Cell` nor `RefCell` are thread safe (they do not implement //! `Sync`), if you need to do Aliasing and Mutation between multiple threads is possible to use -//! `Mutex`, `RwLock` or `AtomicXXX`. +//! [`Mutex`](../sync/struct.Mutex.html), [`RwLock`](../sync/struct.RwLock.html) or +//! [`atomic`](../sync/atomic/index.html) types. //! //! Values of the `Cell` and `RefCell` types may be mutated through shared references (i.e. //! the common `&T` type), whereas most Rust types can only be mutated through unique (`&mut T`) From 7ded7f764c2d590d0c3ad71b9ffbbcfaec2174fb Mon Sep 17 00:00:00 2001 From: Christian Poveda Date: Sat, 24 Feb 2018 18:06:01 -0500 Subject: [PATCH 08/68] corrected grammar errors --- src/libcore/cell.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/libcore/cell.rs b/src/libcore/cell.rs index 91074c18d771..858bdcbb7211 100644 --- a/src/libcore/cell.rs +++ b/src/libcore/cell.rs @@ -10,17 +10,17 @@ //! Shareable mutable containers. //! -//! Rust memory safety is based on this rule: Given an object `T`, is only possible to +//! Rust memory safety is based on this rule: Given an object `T`, it is only possible to //! have one of the following: //! -//! - Having several inmutable references (`&T`) to the object (also know as Aliasing). +//! - Having several immutable references (`&T`) to the object (also know as Aliasing). //! - Having one mutable reference (`&mut T`) to the object (also know as Mutability). //! //! This is enforced by the Rust compiler. However, there are situations where this rule is not -//! flexible enough. Sometimes is required to have multiple references to an object and yet +//! flexible enough. Sometimes it is required to have multiple references to an object and yet //! mutate it. //! -//! Shareable mutable containers exist to permit mutability in presence of aliasing in a +//! Shareable mutable containers exist to permit mutability in the presence of aliasing in a //! controlled manner. Both `Cell` and `RefCell` allows to do this in a single threaded //! way. However, neither `Cell` nor `RefCell` are thread safe (they do not implement //! `Sync`), if you need to do Aliasing and Mutation between multiple threads is possible to use From 397ce8a1aedd0734cbf9b7dfb36ea18fbe6a5d91 Mon Sep 17 00:00:00 2001 From: Christian Poveda Date: Sat, 24 Feb 2018 22:43:30 -0500 Subject: [PATCH 09/68] fixed links --- src/libcore/cell.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libcore/cell.rs b/src/libcore/cell.rs index 858bdcbb7211..a946aca68d1b 100644 --- a/src/libcore/cell.rs +++ b/src/libcore/cell.rs @@ -24,8 +24,8 @@ //! controlled manner. Both `Cell` and `RefCell` allows to do this in a single threaded //! way. However, neither `Cell` nor `RefCell` are thread safe (they do not implement //! `Sync`), if you need to do Aliasing and Mutation between multiple threads is possible to use -//! [`Mutex`](../sync/struct.Mutex.html), [`RwLock`](../sync/struct.RwLock.html) or -//! [`atomic`](../sync/atomic/index.html) types. +//! [`Mutex`](../../std/sync/struct.Mutex.html), [`RwLock`](../../std/sync/struct.RwLock.html) or +//! [`atomic`](../../core/sync/atomic/index.html) types. //! //! Values of the `Cell` and `RefCell` types may be mutated through shared references (i.e. //! the common `&T` type), whereas most Rust types can only be mutated through unique (`&mut T`) From e8904f935ab45a033c61e2136674a080046fd733 Mon Sep 17 00:00:00 2001 From: Phlosioneer Date: Sun, 25 Feb 2018 15:46:17 -0500 Subject: [PATCH 10/68] Change the example string to something arbitrary The choice of string is arbitrary, so all references to a number in the string were removed. The string is now the standard "Hello world!". --- src/libcore/option.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/libcore/option.rs b/src/libcore/option.rs index 96b551d8704a..5c9fe8600768 100644 --- a/src/libcore/option.rs +++ b/src/libcore/option.rs @@ -233,11 +233,12 @@ impl Option { /// [`usize`]: ../../std/primitive.usize.html /// /// ``` - /// let num_as_str: Option = Some("12".to_string()); + /// let text: Option = Some("Hello, world!".to_string()); /// // First, cast `Option` to `Option<&String>` with `as_ref`, - /// // then consume *that* with `map`, leaving `num_as_str` on the stack. - /// let num_length: Option = num_as_str.as_ref().map(|n| n.len()); - /// println!("still can print num_as_str: {:?}", num_as_str); + /// // then consume *that* with `map`, leaving `text` on the stack. + /// let text_length: Option = text.as_ref().map(|s| s.len()); + /// println!("text length: {}", text_length); + /// println!("still can print text: {:?}", text); /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] From 9091584def3b566f24f8fbeac495e6dc87178be8 Mon Sep 17 00:00:00 2001 From: Christian Poveda Date: Mon, 26 Feb 2018 11:14:40 -0500 Subject: [PATCH 11/68] some grammar corrections --- src/libcore/cell.rs | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/libcore/cell.rs b/src/libcore/cell.rs index a946aca68d1b..37f301c59092 100644 --- a/src/libcore/cell.rs +++ b/src/libcore/cell.rs @@ -13,18 +13,19 @@ //! Rust memory safety is based on this rule: Given an object `T`, it is only possible to //! have one of the following: //! -//! - Having several immutable references (`&T`) to the object (also know as Aliasing). -//! - Having one mutable reference (`&mut T`) to the object (also know as Mutability). +//! - Having several immutable references (`&T`) to the object (also known as **aliasing**). +//! - Having one mutable reference (`&mut T`) to the object (also known as **mutability**). //! //! This is enforced by the Rust compiler. However, there are situations where this rule is not //! flexible enough. Sometimes it is required to have multiple references to an object and yet //! mutate it. //! -//! Shareable mutable containers exist to permit mutability in the presence of aliasing in a -//! controlled manner. Both `Cell` and `RefCell` allows to do this in a single threaded +//! Shareable mutable containers exist to permit mutability in a controlled manner, even in the +//! presence of aliasing. Both `Cell` and `RefCell` allows to do this in a single threaded //! way. However, neither `Cell` nor `RefCell` are thread safe (they do not implement -//! `Sync`), if you need to do Aliasing and Mutation between multiple threads is possible to use -//! [`Mutex`](../../std/sync/struct.Mutex.html), [`RwLock`](../../std/sync/struct.RwLock.html) or +//! `Sync`). If you need to do aliasing and mutation between multiple threads it is possible to +//! use [`Mutex`](../../std/sync/struct.Mutex.html), +//! [`RwLock`](../../std/sync/struct.RwLock.html) or //! [`atomic`](../../core/sync/atomic/index.html) types. //! //! Values of the `Cell` and `RefCell` types may be mutated through shared references (i.e. From b7b3498ce86d025ed84b0daa9a28588190ac444a Mon Sep 17 00:00:00 2001 From: Phlosioneer Date: Mon, 26 Feb 2018 19:48:15 -0500 Subject: [PATCH 12/68] Fix doctest failure Tried to be fancy with print statements. --- src/libcore/option.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/libcore/option.rs b/src/libcore/option.rs index 5c9fe8600768..2b77ba391227 100644 --- a/src/libcore/option.rs +++ b/src/libcore/option.rs @@ -237,7 +237,6 @@ impl Option { /// // First, cast `Option` to `Option<&String>` with `as_ref`, /// // then consume *that* with `map`, leaving `text` on the stack. /// let text_length: Option = text.as_ref().map(|s| s.len()); - /// println!("text length: {}", text_length); /// println!("still can print text: {:?}", text); /// ``` #[inline] From a17a2e3f839a6c5c00ee8f00ac4c7d92e2ad634b Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Tue, 27 Feb 2018 16:03:23 -0300 Subject: [PATCH 13/68] Do not report _#nr lifetimes names in errors --- .../borrow_check/error_reporting.rs | 51 ++++++++++++++++--- src/test/ui/nll/borrowed-local-error.rs | 26 ++++++++++ src/test/ui/nll/borrowed-local-error.stderr | 17 +++++++ src/test/ui/nll/borrowed-temporary-error.rs | 26 ++++++++++ .../ui/nll/borrowed-temporary-error.stderr | 14 +++++ 5 files changed, 128 insertions(+), 6 deletions(-) create mode 100644 src/test/ui/nll/borrowed-local-error.rs create mode 100644 src/test/ui/nll/borrowed-local-error.stderr create mode 100644 src/test/ui/nll/borrowed-temporary-error.rs create mode 100644 src/test/ui/nll/borrowed-temporary-error.stderr diff --git a/src/librustc_mir/borrow_check/error_reporting.rs b/src/librustc_mir/borrow_check/error_reporting.rs index 34551e8e76f5..9d8b2b709b7d 100644 --- a/src/librustc_mir/borrow_check/error_reporting.rs +++ b/src/librustc_mir/borrow_check/error_reporting.rs @@ -497,14 +497,34 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { _proper_span: Span, _end_span: Option, ) { + debug!( + "report_unscoped_local_value_does_not_live_long_enough(\ + {:?}, {:?}, {:?}, {:?}, {:?}, {:?}\ + )", + context, + name, + scope_tree, + borrow, + drop_span, + borrow_span + ); + let mut err = self.tcx.path_does_not_live_long_enough(borrow_span, &format!("`{}`", name), Origin::Mir); err.span_label(borrow_span, "borrowed value does not live long enough"); err.span_label(drop_span, "borrowed value only lives until here"); - self.tcx.note_and_explain_region(scope_tree, &mut err, - "borrowed value must be valid for ", - borrow.region, "..."); + + if !self.tcx.sess.nll() { + self.tcx.note_and_explain_region( + scope_tree, + &mut err, + "borrowed value must be valid for ", + borrow.region, + "...", + ); + } + self.explain_why_borrow_contains_point(context, borrow, &mut err); err.emit(); } @@ -519,14 +539,33 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { proper_span: Span, _end_span: Option ) { + debug!( + "report_unscoped_temporary_value_does_not_live_long_enough(\ + {:?}, {:?}, {:?}, {:?}, {:?}\ + )", + context, + scope_tree, + borrow, + drop_span, + proper_span + ); + let mut err = self.tcx.path_does_not_live_long_enough(proper_span, "borrowed value", Origin::Mir); err.span_label(proper_span, "temporary value does not live long enough"); err.span_label(drop_span, "temporary value only lives until here"); - self.tcx.note_and_explain_region(scope_tree, &mut err, - "borrowed value must be valid for ", - borrow.region, "..."); + + if !self.tcx.sess.nll() { + self.tcx.note_and_explain_region( + scope_tree, + &mut err, + "borrowed value must be valid for ", + borrow.region, + "...", + ); + } + self.explain_why_borrow_contains_point(context, borrow, &mut err); err.emit(); } diff --git a/src/test/ui/nll/borrowed-local-error.rs b/src/test/ui/nll/borrowed-local-error.rs new file mode 100644 index 000000000000..785a38da9598 --- /dev/null +++ b/src/test/ui/nll/borrowed-local-error.rs @@ -0,0 +1,26 @@ +// Copyright 2018 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: -Znll-dump-cause + +#![feature(nll)] + +fn gimme(x: &(u32,)) -> &u32 { + &x.0 +} + +fn main() { + let x = gimme({ + let v = (22,); + &v + //~^ ERROR `v` does not live long enough [E0597] + }); + println!("{:?}", x); +} diff --git a/src/test/ui/nll/borrowed-local-error.stderr b/src/test/ui/nll/borrowed-local-error.stderr new file mode 100644 index 000000000000..3bc197855482 --- /dev/null +++ b/src/test/ui/nll/borrowed-local-error.stderr @@ -0,0 +1,17 @@ +error[E0597]: `v` does not live long enough + --> $DIR/borrowed-local-error.rs:22:9 + | +LL | let x = gimme({ + | _____________- +LL | | let v = (22,); +LL | | &v + | | ^^ borrowed value does not live long enough +LL | | //~^ ERROR `v` does not live long enough [E0597] +LL | | }); + | |_____-- borrow later used here + | | + | borrowed value only lives until here + +error: aborting due to previous error + +If you want more information on this error, try using "rustc --explain E0597" diff --git a/src/test/ui/nll/borrowed-temporary-error.rs b/src/test/ui/nll/borrowed-temporary-error.rs new file mode 100644 index 000000000000..e1a6112d173f --- /dev/null +++ b/src/test/ui/nll/borrowed-temporary-error.rs @@ -0,0 +1,26 @@ +// Copyright 2018 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: -Znll-dump-cause + +#![feature(nll)] + +fn gimme(x: &(u32,)) -> &u32 { + &x.0 +} + +fn main() { + let x = gimme({ + let v = 22; + &(v,) + //~^ ERROR borrowed value does not live long enough [E0597] + }); + println!("{:?}", x); +} diff --git a/src/test/ui/nll/borrowed-temporary-error.stderr b/src/test/ui/nll/borrowed-temporary-error.stderr new file mode 100644 index 000000000000..f5cb1dccc378 --- /dev/null +++ b/src/test/ui/nll/borrowed-temporary-error.stderr @@ -0,0 +1,14 @@ +error[E0597]: borrowed value does not live long enough + --> $DIR/borrowed-temporary-error.rs:22:10 + | +LL | &(v,) + | ^^^^ temporary value does not live long enough +LL | //~^ ERROR borrowed value does not live long enough [E0597] +LL | }); + | - temporary value only lives until here +LL | println!("{:?}", x); + | - borrow later used here + +error: aborting due to previous error + +If you want more information on this error, try using "rustc --explain E0597" From 7580826a1f600e1ce51fa16da120de8cc263712b Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Tue, 27 Feb 2018 18:10:35 -0300 Subject: [PATCH 14/68] Avoid printing overwhelming info on -Znll-dump-cause --- .../borrow_check/nll/explain_borrow/mod.rs | 1 - .../borrow_check/nll/region_infer/mod.rs | 71 +------------------ 2 files changed, 2 insertions(+), 70 deletions(-) diff --git a/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs b/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs index 948c1ac0b136..158e8c7a9929 100644 --- a/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs +++ b/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs @@ -71,7 +71,6 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { } _ => { - cause.label_diagnostic(mir, err); } } } diff --git a/src/librustc_mir/borrow_check/nll/region_infer/mod.rs b/src/librustc_mir/borrow_check/nll/region_infer/mod.rs index 33c012dfad82..d2f6d626c9eb 100644 --- a/src/librustc_mir/borrow_check/nll/region_infer/mod.rs +++ b/src/librustc_mir/borrow_check/nll/region_infer/mod.rs @@ -26,7 +26,6 @@ use rustc::ty::{self, RegionVid, Ty, TypeFoldable}; use rustc::util::common::ErrorReported; use rustc_data_structures::bitvec::BitVector; use rustc_data_structures::indexed_vec::IndexVec; -use rustc_errors::DiagnosticBuilder; use std::fmt; use std::rc::Rc; use syntax::ast; @@ -435,7 +434,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { self.check_type_tests(infcx, mir, mir_def_id, outlives_requirements.as_mut()); - self.check_universal_regions(infcx, mir, mir_def_id, outlives_requirements.as_mut()); + self.check_universal_regions(infcx, mir_def_id, outlives_requirements.as_mut()); let outlives_requirements = outlives_requirements.unwrap_or(vec![]); @@ -897,7 +896,6 @@ impl<'tcx> RegionInferenceContext<'tcx> { fn check_universal_regions<'gcx>( &self, infcx: &InferCtxt<'_, 'gcx, 'tcx>, - mir: &Mir<'tcx>, mir_def_id: DefId, mut propagated_outlives_requirements: Option<&mut Vec>>, ) { @@ -913,7 +911,6 @@ impl<'tcx> RegionInferenceContext<'tcx> { for (fr, _) in universal_definitions { self.check_universal_region( infcx, - mir, mir_def_id, fr, &mut propagated_outlives_requirements, @@ -932,7 +929,6 @@ impl<'tcx> RegionInferenceContext<'tcx> { fn check_universal_region<'gcx>( &self, infcx: &InferCtxt<'_, 'gcx, 'tcx>, - mir: &Mir<'tcx>, mir_def_id: DefId, longer_fr: RegionVid, propagated_outlives_requirements: &mut Option<&mut Vec>>, @@ -990,7 +986,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { // Note: in this case, we use the unapproximated regions // to report the error. This gives better error messages // in some cases. - self.report_error(infcx, mir, mir_def_id, longer_fr, shorter_fr, blame_span); + self.report_error(infcx, mir_def_id, longer_fr, shorter_fr, blame_span); } } @@ -1005,7 +1001,6 @@ impl<'tcx> RegionInferenceContext<'tcx> { fn report_error( &self, infcx: &InferCtxt<'_, '_, 'tcx>, - mir: &Mir<'tcx>, mir_def_id: DefId, fr: RegionVid, outlived_fr: RegionVid, @@ -1039,12 +1034,6 @@ impl<'tcx> RegionInferenceContext<'tcx> { &format!("{} does not outlive {}", fr_string, outlived_fr_string,), ); - // Find out why `fr` had to outlive `outlived_fr`... - let inferred_values = self.inferred_values.as_ref().unwrap(); - if let Some(cause) = inferred_values.cause(fr, outlived_fr) { - cause.label_diagnostic(mir, &mut diag); - } - diag.emit(); } @@ -1285,62 +1274,6 @@ impl CauseExt for Rc { } impl Cause { - pub(crate) fn label_diagnostic(&self, mir: &Mir<'_>, diag: &mut DiagnosticBuilder<'_>) { - // The cause information is pretty messy. Only dump it as an - // internal debugging aid if -Znll-dump-cause is given. - let nll_dump_cause = ty::tls::with(|tcx| tcx.sess.nll_dump_cause()); - if !nll_dump_cause { - return; - } - - let mut string = String::new(); - self.push_diagnostic_string(mir, &mut string); - diag.note(&string); - } - - fn push_diagnostic_string(&self, mir: &Mir<'_>, string: &mut String) { - match self { - Cause::LiveVar(local, location) => { - string.push_str(&format!("because `{:?}` is live at {:?}", local, location)); - } - - Cause::DropVar(local, location) => { - string.push_str(&format!( - "because `{:?}` is dropped at {:?}", - local, - location - )); - } - - Cause::LiveOther(location) => { - string.push_str(&format!( - "because of a general liveness constraint at {:?}", - location - )); - } - - Cause::UniversalRegion(region_vid) => { - string.push_str(&format!( - "because `{:?}` is universally quantified", - region_vid - )); - } - - Cause::Outlives { - original_cause, - constraint_location, - constraint_span: _, - } => { - string.push_str(&format!( - "because of an outlives relation created at `{:?}`\n", - constraint_location - )); - - original_cause.push_diagnostic_string(mir, string); - } - } - } - pub(crate) fn root_cause(&self) -> &Cause { match self { Cause::LiveVar(..) | From 02e021b6d4e1ae779dc538404a4fa0c54ed5f7ed Mon Sep 17 00:00:00 2001 From: Amanieu d'Antras Date: Thu, 7 Apr 2016 18:16:40 +0100 Subject: [PATCH 15/68] Add bitreverse intrinsic --- src/libcore/intrinsics.rs | 4 ++++ src/librustc_trans/context.rs | 6 ++++++ src/librustc_trans/intrinsic.rs | 8 ++++++-- src/librustc_typeck/check/intrinsic.rs | 3 ++- src/test/run-pass/intrinsics-integer.rs | 10 ++++++++++ 5 files changed, 28 insertions(+), 3 deletions(-) diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs index a05d67a304fa..830ebad06542 100644 --- a/src/libcore/intrinsics.rs +++ b/src/libcore/intrinsics.rs @@ -1292,6 +1292,10 @@ extern "rust-intrinsic" { /// Reverses the bytes in an integer type `T`. pub fn bswap(x: T) -> T; + /// Reverses the bits in an integer type `T`. + #[cfg(not(stage0))] + pub fn bitreverse(x: T) -> T; + /// Performs checked integer addition. /// The stabilized versions of this intrinsic are available on the integer /// primitives via the `overflowing_add` method. For example, diff --git a/src/librustc_trans/context.rs b/src/librustc_trans/context.rs index a285e5f263ab..b93e8c2ad21c 100644 --- a/src/librustc_trans/context.rs +++ b/src/librustc_trans/context.rs @@ -597,6 +597,12 @@ fn declare_intrinsic(cx: &CodegenCx, key: &str) -> Option { ifn!("llvm.bswap.i64", fn(t_i64) -> t_i64); ifn!("llvm.bswap.i128", fn(t_i128) -> t_i128); + ifn!("llvm.bitreverse.i8", fn(t_i8) -> t_i8); + ifn!("llvm.bitreverse.i16", fn(t_i16) -> t_i16); + ifn!("llvm.bitreverse.i32", fn(t_i32) -> t_i32); + ifn!("llvm.bitreverse.i64", fn(t_i64) -> t_i64); + ifn!("llvm.bitreverse.i128", fn(t_i128) -> t_i128); + ifn!("llvm.sadd.with.overflow.i8", fn(t_i8, t_i8) -> mk_struct!{t_i8, i1}); ifn!("llvm.sadd.with.overflow.i16", fn(t_i16, t_i16) -> mk_struct!{t_i16, i1}); ifn!("llvm.sadd.with.overflow.i32", fn(t_i32, t_i32) -> mk_struct!{t_i32, i1}); diff --git a/src/librustc_trans/intrinsic.rs b/src/librustc_trans/intrinsic.rs index b1f1fb52c907..3f87ce7e0479 100644 --- a/src/librustc_trans/intrinsic.rs +++ b/src/librustc_trans/intrinsic.rs @@ -287,8 +287,8 @@ pub fn trans_intrinsic_call<'a, 'tcx>(bx: &Builder<'a, 'tcx>, ], None) }, "ctlz" | "ctlz_nonzero" | "cttz" | "cttz_nonzero" | "ctpop" | "bswap" | - "add_with_overflow" | "sub_with_overflow" | "mul_with_overflow" | - "overflowing_add" | "overflowing_sub" | "overflowing_mul" | + "bitreverse" | "add_with_overflow" | "sub_with_overflow" | + "mul_with_overflow" | "overflowing_add" | "overflowing_sub" | "overflowing_mul" | "unchecked_div" | "unchecked_rem" | "unchecked_shl" | "unchecked_shr" => { let ty = arg_tys[0]; match int_type_width_signed(ty, cx) { @@ -315,6 +315,10 @@ pub fn trans_intrinsic_call<'a, 'tcx>(bx: &Builder<'a, 'tcx>, &[args[0].immediate()], None) } } + "bitreverse" => { + bx.call(cx.get_intrinsic(&format!("llvm.bitreverse.i{}", width)), + &[args[0].immediate()], None) + } "add_with_overflow" | "sub_with_overflow" | "mul_with_overflow" => { let intrinsic = format!("llvm.{}{}.with.overflow.i{}", if signed { 's' } else { 'u' }, diff --git a/src/librustc_typeck/check/intrinsic.rs b/src/librustc_typeck/check/intrinsic.rs index 23243c3ad66c..2e00040d99a7 100644 --- a/src/librustc_typeck/check/intrinsic.rs +++ b/src/librustc_typeck/check/intrinsic.rs @@ -275,7 +275,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" | "ctlz_nonzero" | "cttz" | "cttz_nonzero" | "bswap" => + "ctpop" | "ctlz" | "ctlz_nonzero" | "cttz" | "cttz_nonzero" | + "bswap" | "bitreverse" => (1, vec![param(0)], param(0)), "add_with_overflow" | "sub_with_overflow" | "mul_with_overflow" => diff --git a/src/test/run-pass/intrinsics-integer.rs b/src/test/run-pass/intrinsics-integer.rs index 4896f02da20b..6e0712f6767b 100644 --- a/src/test/run-pass/intrinsics-integer.rs +++ b/src/test/run-pass/intrinsics-integer.rs @@ -18,6 +18,7 @@ mod rusti { pub fn cttz(x: T) -> T; pub fn cttz_nonzero(x: T) -> T; pub fn bswap(x: T) -> T; + pub fn bitreverse(x: T) -> T; } } @@ -138,5 +139,14 @@ pub fn main() { assert_eq!(bswap(0x0ABBCC0Di32), 0x0DCCBB0A); assert_eq!(bswap(0x0122334455667708u64), 0x0877665544332201); assert_eq!(bswap(0x0122334455667708i64), 0x0877665544332201); + + assert_eq!(bitreverse(0x0Au8), 0x50); + assert_eq!(bitreverse(0x0Ai8), 0x50); + assert_eq!(bitreverse(0x0A0Cu16), 0x3050); + assert_eq!(bitreverse(0x0A0Ci16), 0x3050); + assert_eq!(bitreverse(0x0ABBCC0Eu32), 0x7033DD50); + assert_eq!(bitreverse(0x0ABBCC0Ei32), 0x7033DD50); + assert_eq!(bitreverse(0x0122334455667708u64), 0x10EE66AA22CC4480); + assert_eq!(bitreverse(0x0122334455667708i64), 0x10EE66AA22CC4480); } } From df8dd3fd3ef2080c01360db38de610c13db1766e Mon Sep 17 00:00:00 2001 From: Tshepang Lekhonkhobe Date: Wed, 28 Feb 2018 22:27:47 +0200 Subject: [PATCH 16/68] doc: no need for the references Also: - apply some rustfmt love - fix output of one example --- src/libcore/iter/iterator.rs | 53 +++++++++++++++--------------------- 1 file changed, 22 insertions(+), 31 deletions(-) diff --git a/src/libcore/iter/iterator.rs b/src/libcore/iter/iterator.rs index 9d8a71250f88..722e50fe0f49 100644 --- a/src/libcore/iter/iterator.rs +++ b/src/libcore/iter/iterator.rs @@ -1180,19 +1180,19 @@ pub trait Iterator { /// /// // this iterator sequence is complex. /// let sum = a.iter() - /// .cloned() - /// .filter(|&x| x % 2 == 0) - /// .fold(0, |sum, i| sum + i); + /// .cloned() + /// .filter(|x| x % 2 == 0) + /// .fold(0, |sum, i| sum + i); /// /// println!("{}", sum); /// /// // let's add some inspect() calls to investigate what's happening /// let sum = a.iter() - /// .cloned() - /// .inspect(|x| println!("about to filter: {}", x)) - /// .filter(|&x| x % 2 == 0) - /// .inspect(|x| println!("made it through filter: {}", x)) - /// .fold(0, |sum, i| sum + i); + /// .cloned() + /// .inspect(|x| println!("about to filter: {}", x)) + /// .filter(|x| x % 2 == 0) + /// .inspect(|x| println!("made it through filter: {}", x)) + /// .fold(0, |sum, i| sum + i); /// /// println!("{}", sum); /// ``` @@ -1200,6 +1200,7 @@ pub trait Iterator { /// This will print: /// /// ```text + /// 6 /// about to filter: 1 /// about to filter: 4 /// made it through filter: 4 @@ -1230,8 +1231,7 @@ pub trait Iterator { /// /// let iter = a.into_iter(); /// - /// let sum: i32 = iter.take(5) - /// .fold(0, |acc, &i| acc + i ); + /// let sum: i32 = iter.take(5).fold(0, |acc, i| acc + i ); /// /// assert_eq!(sum, 6); /// @@ -1245,9 +1245,7 @@ pub trait Iterator { /// let mut iter = a.into_iter(); /// /// // instead, we add in a .by_ref() - /// let sum: i32 = iter.by_ref() - /// .take(2) - /// .fold(0, |acc, &i| acc + i ); + /// let sum: i32 = iter.by_ref().take(2).fold(0, |acc, i| acc + i ); /// /// assert_eq!(sum, 3); /// @@ -1304,9 +1302,7 @@ pub trait Iterator { /// /// let a = [1, 2, 3]; /// - /// let doubled: VecDeque = a.iter() - /// .map(|&x| x * 2) - /// .collect(); + /// let doubled: VecDeque = a.iter().map(|&x| x * 2).collect(); /// /// assert_eq!(2, doubled[0]); /// assert_eq!(4, doubled[1]); @@ -1318,9 +1314,7 @@ pub trait Iterator { /// ``` /// let a = [1, 2, 3]; /// - /// let doubled = a.iter() - /// .map(|&x| x * 2) - /// .collect::>(); + /// let doubled = a.iter().map(|x| x * 2).collect::>(); /// /// assert_eq!(vec![2, 4, 6], doubled); /// ``` @@ -1331,9 +1325,7 @@ pub trait Iterator { /// ``` /// let a = [1, 2, 3]; /// - /// let doubled = a.iter() - /// .map(|&x| x * 2) - /// .collect::>(); + /// let doubled = a.iter().map(|x| x * 2).collect::>(); /// /// assert_eq!(vec![2, 4, 6], doubled); /// ``` @@ -1344,9 +1336,9 @@ pub trait Iterator { /// let chars = ['g', 'd', 'k', 'k', 'n']; /// /// let hello: String = chars.iter() - /// .map(|&x| x as u8) - /// .map(|x| (x + 1) as char) - /// .collect(); + /// .map(|&x| x as u8) + /// .map(|x| (x + 1) as char) + /// .collect(); /// /// assert_eq!("hello", hello); /// ``` @@ -1393,8 +1385,9 @@ pub trait Iterator { /// ``` /// let a = [1, 2, 3]; /// - /// let (even, odd): (Vec, Vec) = a.into_iter() - /// .partition(|&n| n % 2 == 0); + /// let (even, odd): (Vec, Vec) = a + /// .into_iter() + /// .partition(|&n| n % 2 == 0); /// /// assert_eq!(even, vec![2]); /// assert_eq!(odd, vec![1, 3]); @@ -1457,8 +1450,7 @@ pub trait Iterator { /// let a = [1, 2, 3]; /// /// // the checked sum of all of the elements of the array - /// let sum = a.iter() - /// .try_fold(0i8, |acc, &x| acc.checked_add(x)); + /// let sum = a.iter().try_fold(0i8, |acc, &x| acc.checked_add(x)); /// /// assert_eq!(sum, Some(6)); /// ``` @@ -1556,8 +1548,7 @@ pub trait Iterator { /// let a = [1, 2, 3]; /// /// // the sum of all of the elements of the array - /// let sum = a.iter() - /// .fold(0, |acc, &x| acc + x); + /// let sum = a.iter().fold(0, |acc, x| acc + x); /// /// assert_eq!(sum, 6); /// ``` From e822e62ee80a9108bfdb7d0952c85fab2146f569 Mon Sep 17 00:00:00 2001 From: flip1995 Date: Thu, 22 Feb 2018 15:53:22 +0100 Subject: [PATCH 17/68] Suggest type for overflowing bin/hex-literals --- src/librustc_lint/types.rs | 194 ++++++++++++++++++++++---- src/test/ui/lint/type-overflow.rs | 35 +++++ src/test/ui/lint/type-overflow.stderr | 70 ++++++++++ 3 files changed, 274 insertions(+), 25 deletions(-) create mode 100644 src/test/ui/lint/type-overflow.rs create mode 100644 src/test/ui/lint/type-overflow.stderr diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs index ef9b3d38c637..4fabb5bafbf8 100644 --- a/src/librustc_lint/types.rs +++ b/src/librustc_lint/types.rs @@ -150,11 +150,52 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeLimits { // Detect literal value out of range [min, max] inclusive // avoiding use of -min to prevent overflow/panic - if (negative && v > max + 1) || - (!negative && v > max) { - cx.span_lint(OVERFLOWING_LITERALS, - e.span, - &format!("literal out of range for {:?}", t)); + if (negative && v > max + 1) || (!negative && v > max) { + if let Some(repr_str) = get_bin_hex_repr(cx, lit) { + let bits = int_ty_bits(t, cx.sess().target.isize_ty); + let mut actually = v as i128; + if bits < 128 { + // v & 0b0..01..1, |1| = bits + let trimmed = v & ((1 << bits) - 1); + actually = if v & (1 << (bits - 1)) == 0 { + // positive + trimmed as i128 + } else { + // negative -> two's complement + (((-1 as i128 as u128) << bits) | trimmed) as i128 + }; + } + let mut err = cx.struct_span_lint( + OVERFLOWING_LITERALS, + e.span, + &format!("literal out of range for {:?}", t), + ); + err.note(&format!( + "the literal `{}` (decimal `{}`) does not fit into \ + an `{:?}` and will become `{}{:?}`.", + repr_str, v, t, actually, t + )); + let sugg_ty = get_fitting_type( + &cx.tables.node_id_to_type(e.hir_id).sty, + v, + negative, + ).map_or(String::new(), |ty| match ty { + ty::TyUint(t) => format!("Consider using `{:?}`", t), + ty::TyInt(t) => format!("Consider using `{:?}`", t), + _ => String::new(), + }); + if !sugg_ty.is_empty() { + err.help(&sugg_ty); + } + + err.emit(); + return; + } + cx.span_lint( + OVERFLOWING_LITERALS, + e.span, + &format!("literal out of range for {:?}", t), + ); return; } } @@ -180,37 +221,77 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeLimits { if let hir::ExprCast(..) = parent_expr.node { if let ty::TyChar = cx.tables.expr_ty(parent_expr).sty { let mut err = cx.struct_span_lint( - OVERFLOWING_LITERALS, - parent_expr.span, - "only u8 can be casted into char"); - err.span_suggestion(parent_expr.span, - &"use a char literal instead", - format!("'\\u{{{:X}}}'", lit_val)); + OVERFLOWING_LITERALS, + parent_expr.span, + "only u8 can be casted into char", + ); + err.span_suggestion( + parent_expr.span, + &"use a char literal instead", + format!("'\\u{{{:X}}}'", lit_val), + ); err.emit(); - return + return; } } } - cx.span_lint(OVERFLOWING_LITERALS, - e.span, - &format!("literal out of range for {:?}", t)); + if let Some(repr_str) = get_bin_hex_repr(cx, lit) { + let bits = uint_ty_bits(t, cx.sess().target.usize_ty); + // u128 cannot be greater than max -> compiler error + let actually = lit_val & ((1 << bits) - 1); + let mut err = cx.struct_span_lint( + OVERFLOWING_LITERALS, + e.span, + &format!("literal out of range for {:?}", t), + ); + err.note(&format!( + "the literal `{}` (decimal `{}`) does not fit into \ + an `{:?}` and will become `{}{:?}`.", + repr_str, lit_val, t, actually, t + )); + let sugg_ty = get_fitting_type( + &cx.tables.node_id_to_type(e.hir_id).sty, + lit_val, + false, + ).map_or( + String::new(), + |ty| { + if let ty::TyUint(t) = ty { + format!("Consider using `{:?}`", t) + } else { + String::new() + } + }, + ); + if !sugg_ty.is_empty() { + err.help(&sugg_ty); + } + + err.emit(); + return; + } + cx.span_lint( + OVERFLOWING_LITERALS, + e.span, + &format!("literal out of range for {:?}", t), + ); } } ty::TyFloat(t) => { let is_infinite = match lit.node { - ast::LitKind::Float(v, _) | - ast::LitKind::FloatUnsuffixed(v) => { - match t { - ast::FloatTy::F32 => v.as_str().parse().map(f32::is_infinite), - ast::FloatTy::F64 => v.as_str().parse().map(f64::is_infinite), - } - } + ast::LitKind::Float(v, _) | ast::LitKind::FloatUnsuffixed(v) => match t + { + ast::FloatTy::F32 => v.as_str().parse().map(f32::is_infinite), + ast::FloatTy::F64 => v.as_str().parse().map(f64::is_infinite), + }, _ => bug!(), }; if is_infinite == Ok(true) { - cx.span_lint(OVERFLOWING_LITERALS, - e.span, - &format!("literal out of range for {:?}", t)); + cx.span_lint( + OVERFLOWING_LITERALS, + e.span, + &format!("literal out of range for {:?}", t), + ); } } _ => (), @@ -338,6 +419,69 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeLimits { _ => false, } } + + fn get_bin_hex_repr(cx: &LateContext, lit: &ast::Lit) -> Option { + if let Some(src) = cx.sess().codemap().span_to_snippet(lit.span).ok() { + if let Some(firstch) = src.chars().next() { + if let Some(0) = char::to_digit(firstch, 10) { + if let Some(base) = src.chars().nth(1) { + if base == 'x' || base == 'b' { + return Some(src); + } + } + } + } + } + + None + } + + fn get_fitting_type<'a>( + t: &ty::TypeVariants, + val: u128, + negative: bool, + ) -> Option> { + use syntax::ast::IntTy::*; + use syntax::ast::UintTy::*; + macro_rules! find_fit { + ($ty:expr, $val:expr, $negative:expr, + $($type:ident => [$($utypes:expr),*] => [$($itypes:expr),*]),+) => { + { + let _neg = if negative { 1 } else { 0 }; + match $ty { + $($type => { + $(if !negative && val <= uint_ty_range($utypes).1 { + return Some(ty::TyUint($utypes)) + })* + $(if val <= int_ty_range($itypes).1 as u128 + _neg { + return Some(ty::TyInt($itypes)) + })* + None + },)* + _ => None + } + } + } + } + if let &ty::TyInt(i) = t { + return find_fit!(i, val, negative, + I8 => [U8] => [I16, I32, I64, I128], + I16 => [U16] => [I32, I64, I128], + I32 => [U32] => [I64, I128], + I64 => [U64] => [I128], + I128 => [U128] => []); + } + if let &ty::TyUint(u) = t { + return find_fit!(u, val, negative, + U8 => [U8, U16, U32, U64, U128] => [], + U16 => [U16, U32, U64, U128] => [], + U32 => [U32, U64, U128] => [], + U64 => [U64, U128] => [], + U128 => [U128] => []); + } + + None + } } } diff --git a/src/test/ui/lint/type-overflow.rs b/src/test/ui/lint/type-overflow.rs new file mode 100644 index 000000000000..e414f43b3ffd --- /dev/null +++ b/src/test/ui/lint/type-overflow.rs @@ -0,0 +1,35 @@ +// Copyright 2018 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. + +// must-compile-successfully + +#![feature(i128_type)] + +fn main() { + let error = 255i8; //~WARNING literal out of range for i8 + + let ok = 0b1000_0001; // should be ok -> i32 + let ok = 0b0111_1111i8; // should be ok -> 127i8 + + let fail = 0b1000_0001i8; //~WARNING literal out of range for i8 + + let fail = 0x8000_0000_0000_0000i64; //~WARNING literal out of range for i64 + + let fail = 0x1_FFFF_FFFFu32; //~WARNING literal out of range for u32 + + let fail: i128 = 0x8000_0000_0000_0000_0000_0000_0000_0000; + //~^ WARNING literal out of range for i128 + + let fail = 0x8FFF_FFFF_FFFF_FFFE; //~WARNING literal out of range for i32 + + let fail: isize = 0x8000_0000_0000_0000; //~WARNING literal out of range for isize + + let fail = -0b1111_1111i8; //~WARNING literal out of range for i8 +} diff --git a/src/test/ui/lint/type-overflow.stderr b/src/test/ui/lint/type-overflow.stderr new file mode 100644 index 000000000000..425f76da5cb4 --- /dev/null +++ b/src/test/ui/lint/type-overflow.stderr @@ -0,0 +1,70 @@ +warning: literal out of range for i8 + --> $DIR/type-overflow.rs:16:17 + | +16 | let error = 255i8; //~WARNING literal out of range for i8 + | ^^^^^ + | + = note: #[warn(overflowing_literals)] on by default + +warning: literal out of range for i8 + --> $DIR/type-overflow.rs:21:16 + | +21 | let fail = 0b1000_0001i8; //~WARNING literal out of range for i8 + | ^^^^^^^^^^^^^ + | + = note: the literal `0b1000_0001i8` (decimal `129`) does not fit into an `i8` and will become `-127i8`. + = help: Consider using `u8` + +warning: literal out of range for i64 + --> $DIR/type-overflow.rs:23:16 + | +23 | let fail = 0x8000_0000_0000_0000i64; //~WARNING literal out of range for i64 + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the literal `0x8000_0000_0000_0000i64` (decimal `9223372036854775808`) does not fit into an `i64` and will become `-9223372036854775808i64`. + = help: Consider using `u64` + +warning: literal out of range for u32 + --> $DIR/type-overflow.rs:25:16 + | +25 | let fail = 0x1_FFFF_FFFFu32; //~WARNING literal out of range for u32 + | ^^^^^^^^^^^^^^^^ + | + = note: the literal `0x1_FFFF_FFFFu32` (decimal `8589934591`) does not fit into an `u32` and will become `4294967295u32`. + = help: Consider using `u64` + +warning: literal out of range for i128 + --> $DIR/type-overflow.rs:27:22 + | +27 | let fail: i128 = 0x8000_0000_0000_0000_0000_0000_0000_0000; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: the literal `0x8000_0000_0000_0000_0000_0000_0000_0000` (decimal `170141183460469231731687303715884105728`) does not fit into an `i128` and will become `-170141183460469231731687303715884105728i128`. + = help: Consider using `u128` + +warning: literal out of range for i32 + --> $DIR/type-overflow.rs:30:16 + | +30 | let fail = 0x8FFF_FFFF_FFFF_FFFE; //~WARNING literal out of range for i32 + | ^^^^^^^^^^^^^^^^^^^^^ + | + = note: the literal `0x8FFF_FFFF_FFFF_FFFE` (decimal `10376293541461622782`) does not fit into an `i32` and will become `-2i32`. + = help: Consider using `i128` + +warning: literal out of range for isize + --> $DIR/type-overflow.rs:32:23 + | +32 | let fail: isize = 0x8000_0000_0000_0000; //~WARNING literal out of range for isize + | ^^^^^^^^^^^^^^^^^^^^^ + | + = note: the literal `0x8000_0000_0000_0000` (decimal `9223372036854775808`) does not fit into an `isize` and will become `-9223372036854775808isize`. + +warning: literal out of range for i8 + --> $DIR/type-overflow.rs:34:17 + | +34 | let fail = -0b1111_1111i8; //~WARNING literal out of range for i8 + | ^^^^^^^^^^^^^ + | + = note: the literal `0b1111_1111i8` (decimal `255`) does not fit into an `i8` and will become `-1i8`. + = help: Consider using `i16` + From 19c4771eeb5fc8fb18bb2e9a3f16ee474d8e67e3 Mon Sep 17 00:00:00 2001 From: flip1995 Date: Thu, 22 Feb 2018 20:25:58 +0100 Subject: [PATCH 18/68] Implementing requested changes --- src/librustc_lint/types.rs | 141 +++++++++++++++---------------------- 1 file changed, 56 insertions(+), 85 deletions(-) diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs index 4fabb5bafbf8..db9dfedc656b 100644 --- a/src/librustc_lint/types.rs +++ b/src/librustc_lint/types.rs @@ -153,18 +153,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeLimits { if (negative && v > max + 1) || (!negative && v > max) { if let Some(repr_str) = get_bin_hex_repr(cx, lit) { let bits = int_ty_bits(t, cx.sess().target.isize_ty); - let mut actually = v as i128; - if bits < 128 { - // v & 0b0..01..1, |1| = bits - let trimmed = v & ((1 << bits) - 1); - actually = if v & (1 << (bits - 1)) == 0 { - // positive - trimmed as i128 - } else { - // negative -> two's complement - (((-1 as i128 as u128) << bits) | trimmed) as i128 - }; - } + let actually = + ((v << (128 - bits)) as i128) >> (128 - bits); let mut err = cx.struct_span_lint( OVERFLOWING_LITERALS, e.span, @@ -175,15 +165,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeLimits { an `{:?}` and will become `{}{:?}`.", repr_str, v, t, actually, t )); - let sugg_ty = get_fitting_type( + let sugg_ty = get_type_suggestion( &cx.tables.node_id_to_type(e.hir_id).sty, v, negative, - ).map_or(String::new(), |ty| match ty { - ty::TyUint(t) => format!("Consider using `{:?}`", t), - ty::TyInt(t) => format!("Consider using `{:?}`", t), - _ => String::new(), - }); + ); if !sugg_ty.is_empty() { err.help(&sugg_ty); } @@ -221,24 +207,20 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeLimits { if let hir::ExprCast(..) = parent_expr.node { if let ty::TyChar = cx.tables.expr_ty(parent_expr).sty { let mut err = cx.struct_span_lint( - OVERFLOWING_LITERALS, - parent_expr.span, - "only u8 can be casted into char", - ); - err.span_suggestion( - parent_expr.span, - &"use a char literal instead", - format!("'\\u{{{:X}}}'", lit_val), - ); + OVERFLOWING_LITERALS, + parent_expr.span, + "only u8 can be casted into char"); + err.span_suggestion(parent_expr.span, + &"use a char literal instead", + format!("'\\u{{{:X}}}'", lit_val)); err.emit(); - return; + return } } } if let Some(repr_str) = get_bin_hex_repr(cx, lit) { let bits = uint_ty_bits(t, cx.sess().target.usize_ty); - // u128 cannot be greater than max -> compiler error - let actually = lit_val & ((1 << bits) - 1); + let actually = (lit_val << (128 - bits)) >> (128 - bits); let mut err = cx.struct_span_lint( OVERFLOWING_LITERALS, e.span, @@ -249,19 +231,10 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeLimits { an `{:?}` and will become `{}{:?}`.", repr_str, lit_val, t, actually, t )); - let sugg_ty = get_fitting_type( + let sugg_ty = get_type_suggestion( &cx.tables.node_id_to_type(e.hir_id).sty, lit_val, false, - ).map_or( - String::new(), - |ty| { - if let ty::TyUint(t) = ty { - format!("Consider using `{:?}`", t) - } else { - String::new() - } - }, ); if !sugg_ty.is_empty() { err.help(&sugg_ty); @@ -279,19 +252,19 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeLimits { } ty::TyFloat(t) => { let is_infinite = match lit.node { - ast::LitKind::Float(v, _) | ast::LitKind::FloatUnsuffixed(v) => match t - { - ast::FloatTy::F32 => v.as_str().parse().map(f32::is_infinite), - ast::FloatTy::F64 => v.as_str().parse().map(f64::is_infinite), - }, + ast::LitKind::Float(v, _) | + ast::LitKind::FloatUnsuffixed(v) => { + match t { + ast::FloatTy::F32 => v.as_str().parse().map(f32::is_infinite), + ast::FloatTy::F64 => v.as_str().parse().map(f64::is_infinite), + } + } _ => bug!(), }; if is_infinite == Ok(true) { - cx.span_lint( - OVERFLOWING_LITERALS, - e.span, - &format!("literal out of range for {:?}", t), - ); + cx.span_lint(OVERFLOWING_LITERALS, + e.span, + &format!("literal out of range for {:?}", t)); } } _ => (), @@ -421,26 +394,27 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeLimits { } fn get_bin_hex_repr(cx: &LateContext, lit: &ast::Lit) -> Option { - if let Some(src) = cx.sess().codemap().span_to_snippet(lit.span).ok() { - if let Some(firstch) = src.chars().next() { - if let Some(0) = char::to_digit(firstch, 10) { - if let Some(base) = src.chars().nth(1) { - if base == 'x' || base == 'b' { - return Some(src); - } - } - } + let src = cx.sess().codemap().span_to_snippet(lit.span).ok()?; + let firstch = src.chars().next()?; + + if let Some(0) = char::to_digit(firstch, 10) { + match src.chars().nth(1) { + Some('x') | Some('b') => return Some(src), + _ => return None, } } None } - fn get_fitting_type<'a>( - t: &ty::TypeVariants, - val: u128, - negative: bool, - ) -> Option> { + // This function finds the next fitting type and generates a suggestion string. + // It searches for fitting types in the following way (`X < Y`): + // - `iX`: if literal fits in `uX` => `uX`, else => `iY` + // - `-iX` => `iY` + // - `uX` => `uY` + // + // No suggestion for: `isize`, `usize`. + fn get_type_suggestion<'a>(t: &ty::TypeVariants, val: u128, negative: bool) -> String { use syntax::ast::IntTy::*; use syntax::ast::UintTy::*; macro_rules! find_fit { @@ -451,36 +425,33 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeLimits { match $ty { $($type => { $(if !negative && val <= uint_ty_range($utypes).1 { - return Some(ty::TyUint($utypes)) + return format!("Consider using `{:?}`", $utypes) })* $(if val <= int_ty_range($itypes).1 as u128 + _neg { - return Some(ty::TyInt($itypes)) + return format!("Consider using `{:?}`", $itypes) })* - None + String::new() },)* - _ => None + _ => String::new() } } } } - if let &ty::TyInt(i) = t { - return find_fit!(i, val, negative, - I8 => [U8] => [I16, I32, I64, I128], - I16 => [U16] => [I32, I64, I128], - I32 => [U32] => [I64, I128], - I64 => [U64] => [I128], - I128 => [U128] => []); + match t { + &ty::TyInt(i) => find_fit!(i, val, negative, + I8 => [U8] => [I16, I32, I64, I128], + I16 => [U16] => [I32, I64, I128], + I32 => [U32] => [I64, I128], + I64 => [U64] => [I128], + I128 => [U128] => []), + &ty::TyUint(u) => find_fit!(u, val, negative, + U8 => [U8, U16, U32, U64, U128] => [], + U16 => [U16, U32, U64, U128] => [], + U32 => [U32, U64, U128] => [], + U64 => [U64, U128] => [], + U128 => [U128] => []), + _ => String::new(), } - if let &ty::TyUint(u) = t { - return find_fit!(u, val, negative, - U8 => [U8, U16, U32, U64, U128] => [], - U16 => [U16, U32, U64, U128] => [], - U32 => [U32, U64, U128] => [], - U64 => [U64, U128] => [], - U128 => [U128] => []); - } - - None } } } From 5c706196449f679b163a8a5fbfb08d842db07e29 Mon Sep 17 00:00:00 2001 From: flip1995 Date: Sat, 24 Feb 2018 16:40:51 +0100 Subject: [PATCH 19/68] Rewrite error reporting as requested --- src/librustc_lint/types.rs | 114 ++++++++++++++++---------- src/test/ui/lint/type-overflow.stderr | 30 +++---- 2 files changed, 82 insertions(+), 62 deletions(-) diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs index db9dfedc656b..02aef271c37d 100644 --- a/src/librustc_lint/types.rs +++ b/src/librustc_lint/types.rs @@ -152,29 +152,14 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeLimits { // avoiding use of -min to prevent overflow/panic if (negative && v > max + 1) || (!negative && v > max) { if let Some(repr_str) = get_bin_hex_repr(cx, lit) { - let bits = int_ty_bits(t, cx.sess().target.isize_ty); - let actually = - ((v << (128 - bits)) as i128) >> (128 - bits); - let mut err = cx.struct_span_lint( - OVERFLOWING_LITERALS, - e.span, - &format!("literal out of range for {:?}", t), - ); - err.note(&format!( - "the literal `{}` (decimal `{}`) does not fit into \ - an `{:?}` and will become `{}{:?}`.", - repr_str, v, t, actually, t - )); - let sugg_ty = get_type_suggestion( - &cx.tables.node_id_to_type(e.hir_id).sty, + report_bin_hex_error( + cx, + e, + ty::TyInt(t), + repr_str, v, negative, ); - if !sugg_ty.is_empty() { - err.help(&sugg_ty); - } - - err.emit(); return; } cx.span_lint( @@ -219,28 +204,14 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeLimits { } } if let Some(repr_str) = get_bin_hex_repr(cx, lit) { - let bits = uint_ty_bits(t, cx.sess().target.usize_ty); - let actually = (lit_val << (128 - bits)) >> (128 - bits); - let mut err = cx.struct_span_lint( - OVERFLOWING_LITERALS, - e.span, - &format!("literal out of range for {:?}", t), - ); - err.note(&format!( - "the literal `{}` (decimal `{}`) does not fit into \ - an `{:?}` and will become `{}{:?}`.", - repr_str, lit_val, t, actually, t - )); - let sugg_ty = get_type_suggestion( - &cx.tables.node_id_to_type(e.hir_id).sty, + report_bin_hex_error( + cx, + e, + ty::TyUint(t), + repr_str, lit_val, false, ); - if !sugg_ty.is_empty() { - err.help(&sugg_ty); - } - - err.emit(); return; } cx.span_lint( @@ -414,7 +385,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeLimits { // - `uX` => `uY` // // No suggestion for: `isize`, `usize`. - fn get_type_suggestion<'a>(t: &ty::TypeVariants, val: u128, negative: bool) -> String { + fn get_type_suggestion<'a>( + t: &ty::TypeVariants, + val: u128, + negative: bool, + ) -> Option { use syntax::ast::IntTy::*; use syntax::ast::UintTy::*; macro_rules! find_fit { @@ -425,14 +400,14 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeLimits { match $ty { $($type => { $(if !negative && val <= uint_ty_range($utypes).1 { - return format!("Consider using `{:?}`", $utypes) + return Some(format!("{:?}", $utypes)) })* $(if val <= int_ty_range($itypes).1 as u128 + _neg { - return format!("Consider using `{:?}`", $itypes) + return Some(format!("{:?}", $itypes)) })* - String::new() + None },)* - _ => String::new() + _ => None } } } @@ -450,9 +425,58 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeLimits { U32 => [U32, U64, U128] => [], U64 => [U64, U128] => [], U128 => [U128] => []), - _ => String::new(), + _ => None, } } + + fn report_bin_hex_error( + cx: &LateContext, + expr: &hir::Expr, + ty: ty::TypeVariants, + repr_str: String, + val: u128, + negative: bool, + ) { + let (t, actually) = match ty { + ty::TyInt(t) => { + let bits = int_ty_bits(t, cx.sess().target.isize_ty); + let actually = (val << (128 - bits)) as i128 >> (128 - bits); + (format!("{:?}", t), actually.to_string()) + } + ty::TyUint(t) => { + let bits = uint_ty_bits(t, cx.sess().target.usize_ty); + let actually = (val << (128 - bits)) >> (128 - bits); + (format!("{:?}", t), actually.to_string()) + } + _ => bug!(), + }; + let mut err = cx.struct_span_lint( + OVERFLOWING_LITERALS, + expr.span, + &format!("literal out of range for {}", t), + ); + err.note(&format!( + "the literal `{}` (decimal `{}`) does not fit into \ + an `{}` and will become `{}{}`", + repr_str, val, t, actually, t + )); + if let Some(sugg_ty) = + get_type_suggestion(&cx.tables.node_id_to_type(expr.hir_id).sty, val, negative) + { + if let Some(pos) = repr_str.chars().position(|c| c == 'i' || c == 'u') { + let (sans_suffix, _) = repr_str.split_at(pos); + err.span_suggestion( + expr.span, + &format!("consider using `{}` instead", sugg_ty), + format!("{}{}", sans_suffix, sugg_ty), + ); + } else { + err.help(&format!("consider using `{}` instead", sugg_ty)); + } + } + + err.emit(); + } } } diff --git a/src/test/ui/lint/type-overflow.stderr b/src/test/ui/lint/type-overflow.stderr index 425f76da5cb4..89718c7696a8 100644 --- a/src/test/ui/lint/type-overflow.stderr +++ b/src/test/ui/lint/type-overflow.stderr @@ -10,28 +10,25 @@ warning: literal out of range for i8 --> $DIR/type-overflow.rs:21:16 | 21 | let fail = 0b1000_0001i8; //~WARNING literal out of range for i8 - | ^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^ help: consider using `u8` instead: `0b1000_0001u8` | - = note: the literal `0b1000_0001i8` (decimal `129`) does not fit into an `i8` and will become `-127i8`. - = help: Consider using `u8` + = note: the literal `0b1000_0001i8` (decimal `129`) does not fit into an `i8` and will become `-127i8` warning: literal out of range for i64 --> $DIR/type-overflow.rs:23:16 | 23 | let fail = 0x8000_0000_0000_0000i64; //~WARNING literal out of range for i64 - | ^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `u64` instead: `0x8000_0000_0000_0000u64` | - = note: the literal `0x8000_0000_0000_0000i64` (decimal `9223372036854775808`) does not fit into an `i64` and will become `-9223372036854775808i64`. - = help: Consider using `u64` + = note: the literal `0x8000_0000_0000_0000i64` (decimal `9223372036854775808`) does not fit into an `i64` and will become `-9223372036854775808i64` warning: literal out of range for u32 --> $DIR/type-overflow.rs:25:16 | 25 | let fail = 0x1_FFFF_FFFFu32; //~WARNING literal out of range for u32 - | ^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ help: consider using `u64` instead: `0x1_FFFF_FFFFu64` | - = note: the literal `0x1_FFFF_FFFFu32` (decimal `8589934591`) does not fit into an `u32` and will become `4294967295u32`. - = help: Consider using `u64` + = note: the literal `0x1_FFFF_FFFFu32` (decimal `8589934591`) does not fit into an `u32` and will become `4294967295u32` warning: literal out of range for i128 --> $DIR/type-overflow.rs:27:22 @@ -39,8 +36,8 @@ warning: literal out of range for i128 27 | let fail: i128 = 0x8000_0000_0000_0000_0000_0000_0000_0000; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: the literal `0x8000_0000_0000_0000_0000_0000_0000_0000` (decimal `170141183460469231731687303715884105728`) does not fit into an `i128` and will become `-170141183460469231731687303715884105728i128`. - = help: Consider using `u128` + = note: the literal `0x8000_0000_0000_0000_0000_0000_0000_0000` (decimal `170141183460469231731687303715884105728`) does not fit into an `i128` and will become `-170141183460469231731687303715884105728i128` + = help: consider using `u128` instead warning: literal out of range for i32 --> $DIR/type-overflow.rs:30:16 @@ -48,8 +45,8 @@ warning: literal out of range for i32 30 | let fail = 0x8FFF_FFFF_FFFF_FFFE; //~WARNING literal out of range for i32 | ^^^^^^^^^^^^^^^^^^^^^ | - = note: the literal `0x8FFF_FFFF_FFFF_FFFE` (decimal `10376293541461622782`) does not fit into an `i32` and will become `-2i32`. - = help: Consider using `i128` + = note: the literal `0x8FFF_FFFF_FFFF_FFFE` (decimal `10376293541461622782`) does not fit into an `i32` and will become `-2i32` + = help: consider using `i128` instead warning: literal out of range for isize --> $DIR/type-overflow.rs:32:23 @@ -57,14 +54,13 @@ warning: literal out of range for isize 32 | let fail: isize = 0x8000_0000_0000_0000; //~WARNING literal out of range for isize | ^^^^^^^^^^^^^^^^^^^^^ | - = note: the literal `0x8000_0000_0000_0000` (decimal `9223372036854775808`) does not fit into an `isize` and will become `-9223372036854775808isize`. + = note: the literal `0x8000_0000_0000_0000` (decimal `9223372036854775808`) does not fit into an `isize` and will become `-9223372036854775808isize` warning: literal out of range for i8 --> $DIR/type-overflow.rs:34:17 | 34 | let fail = -0b1111_1111i8; //~WARNING literal out of range for i8 - | ^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^ help: consider using `i16` instead: `0b1111_1111i16` | - = note: the literal `0b1111_1111i8` (decimal `255`) does not fit into an `i8` and will become `-1i8`. - = help: Consider using `i16` + = note: the literal `0b1111_1111i8` (decimal `255`) does not fit into an `i8` and will become `-1i8` From f45f760f624b34a7fa70fe925303808d4713641a Mon Sep 17 00:00:00 2001 From: flip1995 Date: Thu, 1 Mar 2018 01:49:36 +0100 Subject: [PATCH 20/68] Adapt stderr of UI test to PR #48449 --- src/test/ui/lint/type-overflow.stderr | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/test/ui/lint/type-overflow.stderr b/src/test/ui/lint/type-overflow.stderr index 89718c7696a8..4ede25b9d03e 100644 --- a/src/test/ui/lint/type-overflow.stderr +++ b/src/test/ui/lint/type-overflow.stderr @@ -1,7 +1,7 @@ warning: literal out of range for i8 --> $DIR/type-overflow.rs:16:17 | -16 | let error = 255i8; //~WARNING literal out of range for i8 +LL | let error = 255i8; //~WARNING literal out of range for i8 | ^^^^^ | = note: #[warn(overflowing_literals)] on by default @@ -9,7 +9,7 @@ warning: literal out of range for i8 warning: literal out of range for i8 --> $DIR/type-overflow.rs:21:16 | -21 | let fail = 0b1000_0001i8; //~WARNING literal out of range for i8 +LL | let fail = 0b1000_0001i8; //~WARNING literal out of range for i8 | ^^^^^^^^^^^^^ help: consider using `u8` instead: `0b1000_0001u8` | = note: the literal `0b1000_0001i8` (decimal `129`) does not fit into an `i8` and will become `-127i8` @@ -17,7 +17,7 @@ warning: literal out of range for i8 warning: literal out of range for i64 --> $DIR/type-overflow.rs:23:16 | -23 | let fail = 0x8000_0000_0000_0000i64; //~WARNING literal out of range for i64 +LL | let fail = 0x8000_0000_0000_0000i64; //~WARNING literal out of range for i64 | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `u64` instead: `0x8000_0000_0000_0000u64` | = note: the literal `0x8000_0000_0000_0000i64` (decimal `9223372036854775808`) does not fit into an `i64` and will become `-9223372036854775808i64` @@ -25,7 +25,7 @@ warning: literal out of range for i64 warning: literal out of range for u32 --> $DIR/type-overflow.rs:25:16 | -25 | let fail = 0x1_FFFF_FFFFu32; //~WARNING literal out of range for u32 +LL | let fail = 0x1_FFFF_FFFFu32; //~WARNING literal out of range for u32 | ^^^^^^^^^^^^^^^^ help: consider using `u64` instead: `0x1_FFFF_FFFFu64` | = note: the literal `0x1_FFFF_FFFFu32` (decimal `8589934591`) does not fit into an `u32` and will become `4294967295u32` @@ -33,7 +33,7 @@ warning: literal out of range for u32 warning: literal out of range for i128 --> $DIR/type-overflow.rs:27:22 | -27 | let fail: i128 = 0x8000_0000_0000_0000_0000_0000_0000_0000; +LL | let fail: i128 = 0x8000_0000_0000_0000_0000_0000_0000_0000; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: the literal `0x8000_0000_0000_0000_0000_0000_0000_0000` (decimal `170141183460469231731687303715884105728`) does not fit into an `i128` and will become `-170141183460469231731687303715884105728i128` @@ -42,7 +42,7 @@ warning: literal out of range for i128 warning: literal out of range for i32 --> $DIR/type-overflow.rs:30:16 | -30 | let fail = 0x8FFF_FFFF_FFFF_FFFE; //~WARNING literal out of range for i32 +LL | let fail = 0x8FFF_FFFF_FFFF_FFFE; //~WARNING literal out of range for i32 | ^^^^^^^^^^^^^^^^^^^^^ | = note: the literal `0x8FFF_FFFF_FFFF_FFFE` (decimal `10376293541461622782`) does not fit into an `i32` and will become `-2i32` @@ -51,7 +51,7 @@ warning: literal out of range for i32 warning: literal out of range for isize --> $DIR/type-overflow.rs:32:23 | -32 | let fail: isize = 0x8000_0000_0000_0000; //~WARNING literal out of range for isize +LL | let fail: isize = 0x8000_0000_0000_0000; //~WARNING literal out of range for isize | ^^^^^^^^^^^^^^^^^^^^^ | = note: the literal `0x8000_0000_0000_0000` (decimal `9223372036854775808`) does not fit into an `isize` and will become `-9223372036854775808isize` @@ -59,7 +59,7 @@ warning: literal out of range for isize warning: literal out of range for i8 --> $DIR/type-overflow.rs:34:17 | -34 | let fail = -0b1111_1111i8; //~WARNING literal out of range for i8 +LL | let fail = -0b1111_1111i8; //~WARNING literal out of range for i8 | ^^^^^^^^^^^^^ help: consider using `i16` instead: `0b1111_1111i16` | = note: the literal `0b1111_1111i8` (decimal `255`) does not fit into an `i8` and will become `-1i8` From f7693c06338c825d0d49eb1373e2039416b38389 Mon Sep 17 00:00:00 2001 From: Lukas Lueg Date: Wed, 21 Feb 2018 16:12:23 +0100 Subject: [PATCH 21/68] Fix spelling s/casted/cast/ --- src/libcore/char.rs | 4 ++-- src/librustc_lint/types.rs | 2 +- src/libsyntax/parse/parser.rs | 2 +- src/test/run-pass/extern-types-pointer-cast.rs | 2 +- src/test/ui/cast_char.rs | 4 ++-- src/test/ui/cast_char.stderr | 4 ++-- src/test/ui/issue-22644.stderr | 16 ++++++++-------- src/test/ui/issue-42954.stderr | 2 +- 8 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/libcore/char.rs b/src/libcore/char.rs index 7215bd2a4768..55d4b590f913 100644 --- a/src/libcore/char.rs +++ b/src/libcore/char.rs @@ -79,7 +79,7 @@ pub const MAX: char = '\u{10ffff}'; /// Converts a `u32` to a `char`. /// -/// Note that all [`char`]s are valid [`u32`]s, and can be casted to one with +/// Note that all [`char`]s are valid [`u32`]s, and can be cast to one with /// [`as`]: /// /// ``` @@ -131,7 +131,7 @@ pub fn from_u32(i: u32) -> Option { /// Converts a `u32` to a `char`, ignoring validity. /// -/// Note that all [`char`]s are valid [`u32`]s, and can be casted to one with +/// Note that all [`char`]s are valid [`u32`]s, and can be cast to one with /// [`as`]: /// /// ``` diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs index f734f3182a93..2207bbd1ca05 100644 --- a/src/librustc_lint/types.rs +++ b/src/librustc_lint/types.rs @@ -184,7 +184,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeLimits { let mut err = cx.struct_span_lint( OVERFLOWING_LITERALS, parent_expr.span, - "only u8 can be casted into char"); + "only u8 can be cast into char"); err.span_suggestion(parent_expr.span, &"use a char literal instead", format!("'\\u{{{:X}}}'", lit_val)); diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 7915109ce3af..fdeed5391f77 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -3094,7 +3094,7 @@ impl<'a> Parser<'a> { let expr_str = self.sess.codemap().span_to_snippet(expr.span) .unwrap_or(pprust::expr_to_string(&expr)); err.span_suggestion(expr.span, - &format!("try {} the casted value", op_verb), + &format!("try {} the cast value", op_verb), format!("({})", expr_str)); err.emit(); diff --git a/src/test/run-pass/extern-types-pointer-cast.rs b/src/test/run-pass/extern-types-pointer-cast.rs index 628a570665a3..0dede8eb70de 100644 --- a/src/test/run-pass/extern-types-pointer-cast.rs +++ b/src/test/run-pass/extern-types-pointer-cast.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// Test that pointers to extern types can be casted from/to usize, +// Test that pointers to extern types can be cast from/to usize, // despite being !Sized. #![feature(extern_types)] diff --git a/src/test/ui/cast_char.rs b/src/test/ui/cast_char.rs index cd8ade5e51a1..4dfa5037bc55 100644 --- a/src/test/ui/cast_char.rs +++ b/src/test/ui/cast_char.rs @@ -12,9 +12,9 @@ fn main() { const XYZ: char = 0x1F888 as char; - //~^ ERROR only u8 can be casted into char + //~^ ERROR only u8 can be cast into char const XY: char = 129160 as char; - //~^ ERROR only u8 can be casted into char + //~^ ERROR only u8 can be cast into char const ZYX: char = '\u{01F888}'; println!("{}", XYZ); } diff --git a/src/test/ui/cast_char.stderr b/src/test/ui/cast_char.stderr index e42a38dace9d..5da763992e35 100644 --- a/src/test/ui/cast_char.stderr +++ b/src/test/ui/cast_char.stderr @@ -1,4 +1,4 @@ -error: only u8 can be casted into char +error: only u8 can be cast into char --> $DIR/cast_char.rs:14:23 | 14 | const XYZ: char = 0x1F888 as char; @@ -10,7 +10,7 @@ note: lint level defined here 11 | #![deny(overflowing_literals)] | ^^^^^^^^^^^^^^^^^^^^ -error: only u8 can be casted into char +error: only u8 can be cast into char --> $DIR/cast_char.rs:16:22 | 16 | const XY: char = 129160 as char; diff --git a/src/test/ui/issue-22644.stderr b/src/test/ui/issue-22644.stderr index 91107fbe3561..60ad222c7ab1 100644 --- a/src/test/ui/issue-22644.stderr +++ b/src/test/ui/issue-22644.stderr @@ -5,7 +5,7 @@ error: `<` is interpreted as a start of generic arguments for `usize`, not a com | ---------- ^ --------- interpreted as generic arguments | | | | | not interpreted as comparison - | help: try comparing the casted value: `(a as usize)` + | help: try comparing the cast value: `(a as usize)` error: `<` is interpreted as a start of generic arguments for `usize`, not a comparison --> $DIR/issue-22644.rs:17:33 @@ -14,7 +14,7 @@ error: `<` is interpreted as a start of generic arguments for `usize`, not a com | ---------- ^ -------------------- interpreted as generic arguments | | | | | not interpreted as comparison - | help: try comparing the casted value: `(a as usize)` + | help: try comparing the cast value: `(a as usize)` error: `<` is interpreted as a start of generic arguments for `usize`, not a comparison --> $DIR/issue-22644.rs:19:31 @@ -23,7 +23,7 @@ error: `<` is interpreted as a start of generic arguments for `usize`, not a com | ---------- ^ - interpreted as generic arguments | | | | | not interpreted as comparison - | help: try comparing the casted value: `(a as usize)` + | help: try comparing the cast value: `(a as usize)` error: `<` is interpreted as a start of generic arguments for `usize`, not a comparison --> $DIR/issue-22644.rs:21:31 @@ -32,7 +32,7 @@ error: `<` is interpreted as a start of generic arguments for `usize`, not a com | -------- ^ -------------------- interpreted as generic arguments | | | | | not interpreted as comparison - | help: try comparing the casted value: `(a: usize)` + | help: try comparing the cast value: `(a: usize)` error: `<` is interpreted as a start of generic arguments for `usize`, not a comparison --> $DIR/issue-22644.rs:23:29 @@ -41,7 +41,7 @@ error: `<` is interpreted as a start of generic arguments for `usize`, not a com | -------- ^ - interpreted as generic arguments | | | | | not interpreted as comparison - | help: try comparing the casted value: `(a: usize)` + | help: try comparing the cast value: `(a: usize)` error: `<` is interpreted as a start of generic arguments for `usize`, not a comparison --> $DIR/issue-22644.rs:28:20 @@ -50,7 +50,7 @@ error: `<` is interpreted as a start of generic arguments for `usize`, not a com | ^ not interpreted as comparison 29 | 4); | - interpreted as generic arguments -help: try comparing the casted value +help: try comparing the cast value | 25 | println!("{}", (a 26 | as @@ -64,7 +64,7 @@ error: `<` is interpreted as a start of generic arguments for `usize`, not a com | ^ not interpreted as comparison 38 | 5); | - interpreted as generic arguments -help: try comparing the casted value +help: try comparing the cast value | 30 | println!("{}", (a 31 | @@ -81,7 +81,7 @@ error: `<` is interpreted as a start of generic arguments for `usize`, not a shi | ---------- ^^ --------- interpreted as generic arguments | | | | | not interpreted as shift - | help: try shifting the casted value: `(a as usize)` + | help: try shifting the cast value: `(a as usize)` error: expected type, found `4` --> $DIR/issue-22644.rs:42:28 diff --git a/src/test/ui/issue-42954.stderr b/src/test/ui/issue-42954.stderr index d0fc410c474a..205fa82274a6 100644 --- a/src/test/ui/issue-42954.stderr +++ b/src/test/ui/issue-42954.stderr @@ -5,7 +5,7 @@ error: `<` is interpreted as a start of generic arguments for `u32`, not a compa | --------- ^ - interpreted as generic arguments | | | | | not interpreted as comparison - | help: try comparing the casted value: `($i as u32)` + | help: try comparing the cast value: `($i as u32)` ... 19 | is_plainly_printable!(c); | ------------------------- in this macro invocation From 834e39289d46783193b9ce43f6725f4ed8c64519 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Wed, 28 Feb 2018 15:52:06 -0300 Subject: [PATCH 22/68] Refactor note_and_explain_region to call note_and_explain_free_region --- src/librustc/infer/error_reporting/mod.rs | 178 +++++++++++----------- 1 file changed, 92 insertions(+), 86 deletions(-) diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index 700d06acf11a..cd506fabb55b 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -87,42 +87,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { prefix: &str, region: ty::Region<'tcx>, suffix: &str) { - fn item_scope_tag(item: &hir::Item) -> &'static str { - match item.node { - hir::ItemImpl(..) => "impl", - hir::ItemStruct(..) => "struct", - hir::ItemUnion(..) => "union", - hir::ItemEnum(..) => "enum", - hir::ItemTrait(..) => "trait", - hir::ItemFn(..) => "function body", - _ => "item" - } - } - - fn trait_item_scope_tag(item: &hir::TraitItem) -> &'static str { - match item.node { - hir::TraitItemKind::Method(..) => "method body", - hir::TraitItemKind::Const(..) | - hir::TraitItemKind::Type(..) => "associated item" - } - } - - fn impl_item_scope_tag(item: &hir::ImplItem) -> &'static str { - match item.node { - hir::ImplItemKind::Method(..) => "method body", - hir::ImplItemKind::Const(..) | - hir::ImplItemKind::Type(_) => "associated item" - } - } - - fn explain_span<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, - heading: &str, span: Span) - -> (String, Option) { - let lo = tcx.sess.codemap().lookup_char_pos_adj(span.lo()); - (format!("the {} at {}:{}", heading, lo.line, lo.col.to_usize() + 1), - Some(span)) - } - let (description, span) = match *region { ty::ReScope(scope) => { let new_string; @@ -143,9 +107,9 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { _ => "expression", }, Some(hir_map::NodeStmt(_)) => "statement", - Some(hir_map::NodeItem(it)) => item_scope_tag(&it), - Some(hir_map::NodeTraitItem(it)) => trait_item_scope_tag(&it), - Some(hir_map::NodeImplItem(it)) => impl_item_scope_tag(&it), + Some(hir_map::NodeItem(it)) => Self::item_scope_tag(&it), + Some(hir_map::NodeTraitItem(it)) => Self::trait_item_scope_tag(&it), + Some(hir_map::NodeImplItem(it)) => Self::impl_item_scope_tag(&it), Some(_) | None => { err.span_note(span, &unknown_scope()); return; @@ -169,57 +133,12 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { &new_string[..] } }; - explain_span(self, scope_decorated_tag, span) + self.explain_span(scope_decorated_tag, span) } ty::ReEarlyBound(_) | ty::ReFree(_) => { - let scope = region.free_region_binding_scope(self); - let node = self.hir.as_local_node_id(scope) - .unwrap_or(DUMMY_NODE_ID); - let unknown; - let tag = match self.hir.find(node) { - Some(hir_map::NodeBlock(_)) | - Some(hir_map::NodeExpr(_)) => "body", - Some(hir_map::NodeItem(it)) => item_scope_tag(&it), - Some(hir_map::NodeTraitItem(it)) => trait_item_scope_tag(&it), - Some(hir_map::NodeImplItem(it)) => impl_item_scope_tag(&it), - - // this really should not happen, but it does: - // FIXME(#27942) - Some(_) => { - unknown = format!("unexpected node ({}) for scope {:?}. \ - Please report a bug.", - self.hir.node_to_string(node), scope); - &unknown - } - None => { - unknown = format!("unknown node for scope {:?}. \ - Please report a bug.", scope); - &unknown - } - }; - let (prefix, span) = match *region { - ty::ReEarlyBound(ref br) => { - (format!("the lifetime {} as defined on", br.name), - self.sess.codemap().def_span(self.hir.span(node))) - } - ty::ReFree(ref fr) => { - match fr.bound_region { - ty::BrAnon(idx) => { - (format!("the anonymous lifetime #{} defined on", idx + 1), - self.hir.span(node)) - } - ty::BrFresh(_) => ("an anonymous lifetime defined on".to_owned(), - self.hir.span(node)), - _ => (format!("the lifetime {} as defined on", fr.bound_region), - self.sess.codemap().def_span(self.hir.span(node))), - } - } - _ => bug!() - }; - let (msg, opt_span) = explain_span(self, tag, span); - (format!("{} {}", prefix, msg), opt_span) + self.msg_span_from_free_region(region) } ty::ReStatic => ("the static lifetime".to_owned(), None), @@ -253,6 +172,93 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { err.note(&message); } } + + fn msg_span_from_free_region(self, + region: ty::Region<'tcx>) + -> (String, Option) { + let scope = region.free_region_binding_scope(self); + let node = self.hir.as_local_node_id(scope) + .unwrap_or(DUMMY_NODE_ID); + let unknown; + let tag = match self.hir.find(node) { + Some(hir_map::NodeBlock(_)) | + Some(hir_map::NodeExpr(_)) => "body", + Some(hir_map::NodeItem(it)) => Self::item_scope_tag(&it), + Some(hir_map::NodeTraitItem(it)) => Self::trait_item_scope_tag(&it), + Some(hir_map::NodeImplItem(it)) => Self::impl_item_scope_tag(&it), + + // this really should not happen, but it does: + // FIXME(#27942) + Some(_) => { + unknown = format!("unexpected node ({}) for scope {:?}. \ + Please report a bug.", + self.hir.node_to_string(node), scope); + &unknown + } + None => { + unknown = format!("unknown node for scope {:?}. \ + Please report a bug.", scope); + &unknown + } + }; + let (prefix, span) = match *region { + ty::ReEarlyBound(ref br) => { + (format!("the lifetime {} as defined on", br.name), + self.sess.codemap().def_span(self.hir.span(node))) + } + ty::ReFree(ref fr) => { + match fr.bound_region { + ty::BrAnon(idx) => { + (format!("the anonymous lifetime #{} defined on", idx + 1), + self.hir.span(node)) + } + ty::BrFresh(_) => ("an anonymous lifetime defined on".to_owned(), + self.hir.span(node)), + _ => (format!("the lifetime {} as defined on", fr.bound_region), + self.sess.codemap().def_span(self.hir.span(node))), + } + } + _ => bug!() + }; + let (msg, opt_span) = self.explain_span(tag, span); + (format!("{} {}", prefix, msg), opt_span) + } + + fn item_scope_tag(item: &hir::Item) -> &'static str { + match item.node { + hir::ItemImpl(..) => "impl", + hir::ItemStruct(..) => "struct", + hir::ItemUnion(..) => "union", + hir::ItemEnum(..) => "enum", + hir::ItemTrait(..) => "trait", + hir::ItemFn(..) => "function body", + _ => "item" + } + } + + fn trait_item_scope_tag(item: &hir::TraitItem) -> &'static str { + match item.node { + hir::TraitItemKind::Method(..) => "method body", + hir::TraitItemKind::Const(..) | + hir::TraitItemKind::Type(..) => "associated item" + } + } + + fn impl_item_scope_tag(item: &hir::ImplItem) -> &'static str { + match item.node { + hir::ImplItemKind::Method(..) => "method body", + hir::ImplItemKind::Const(..) | + hir::ImplItemKind::Type(_) => "associated item" + } + } + + fn explain_span(self, + heading: &str, span: Span) + -> (String, Option) { + let lo = self.sess.codemap().lookup_char_pos_adj(span.lo()); + (format!("the {} at {}:{}", heading, lo.line, lo.col.to_usize() + 1), + Some(span)) + } } impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { From ff7dca50a47d03764c74cac6d803e17c9d9f2a7b Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Thu, 1 Mar 2018 11:56:43 -0300 Subject: [PATCH 23/68] Make explain borrow work for Universal lifetimes --- src/librustc/infer/error_reporting/mod.rs | 33 +++++++++++++++---- .../borrow_check/error_reporting.rs | 4 +-- .../borrow_check/nll/explain_borrow/mod.rs | 14 +++++++- .../borrow_check/nll/region_infer/mod.rs | 2 +- src/test/ui/nll/borrowed-universal-error-2.rs | 22 +++++++++++++ .../ui/nll/borrowed-universal-error-2.stderr | 18 ++++++++++ src/test/ui/nll/borrowed-universal-error.rs | 26 +++++++++++++++ .../ui/nll/borrowed-universal-error.stderr | 18 ++++++++++ src/test/ui/nll/capture-ref-in-struct.stderr | 2 -- .../escape-argument.stderr | 2 -- .../escape-upvar-nested.stderr | 2 -- .../escape-upvar-ref.stderr | 2 -- ...er-to-static-comparing-against-free.stderr | 2 -- .../ui/nll/return-ref-mut-issue-46557.stderr | 2 -- 14 files changed, 127 insertions(+), 22 deletions(-) create mode 100644 src/test/ui/nll/borrowed-universal-error-2.rs create mode 100644 src/test/ui/nll/borrowed-universal-error-2.stderr create mode 100644 src/test/ui/nll/borrowed-universal-error.rs create mode 100644 src/test/ui/nll/borrowed-universal-error.stderr diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index cd506fabb55b..b51ddf719cbf 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -165,12 +165,19 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { ); } }; - let message = format!("{}{}{}", prefix, description, suffix); - if let Some(span) = span { - err.span_note(span, &message); - } else { - err.note(&message); - } + + TyCtxt::emit_msg_span(err, prefix, description, span, suffix); + } + + pub fn note_and_explain_free_region(self, + err: &mut DiagnosticBuilder, + prefix: &str, + region: ty::Region<'tcx>, + suffix: &str) { + let (description, span) = self.msg_span_from_free_region(region); + + + TyCtxt::emit_msg_span(err, prefix, description, span, suffix); } fn msg_span_from_free_region(self, @@ -224,6 +231,20 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { (format!("{} {}", prefix, msg), opt_span) } + fn emit_msg_span(err: &mut DiagnosticBuilder, + prefix: &str, + description: String, + span: Option, + suffix: &str) { + let message = format!("{}{}{}", prefix, description, suffix); + + if let Some(span) = span { + err.span_note(span, &message); + } else { + err.note(&message); + } + } + fn item_scope_tag(item: &hir::Item) -> &'static str { match item.node { hir::ItemImpl(..) => "impl", diff --git a/src/librustc_mir/borrow_check/error_reporting.rs b/src/librustc_mir/borrow_check/error_reporting.rs index 9d8b2b709b7d..667450c3f352 100644 --- a/src/librustc_mir/borrow_check/error_reporting.rs +++ b/src/librustc_mir/borrow_check/error_reporting.rs @@ -233,7 +233,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { context: Context, (place, span): (&Place<'tcx>, Span), gen_borrow_kind: BorrowKind, - issued_borrow: &BorrowData, + issued_borrow: &BorrowData<'tcx>, end_issued_loan_span: Option, ) { let issued_span = self.retrieve_borrow_span(issued_borrow); @@ -574,7 +574,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { &mut self, context: Context, (place, span): (&Place<'tcx>, Span), - loan: &BorrowData, + loan: &BorrowData<'tcx>, ) { let mut err = self.tcx.cannot_assign_to_borrowed( span, diff --git a/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs b/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs index 158e8c7a9929..c93c1848e25f 100644 --- a/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs +++ b/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs @@ -21,7 +21,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { pub(in borrow_check) fn explain_why_borrow_contains_point( &self, context: Context, - borrow: &BorrowData<'_>, + borrow: &BorrowData<'tcx>, err: &mut DiagnosticBuilder<'_>, ) { if let Some(regioncx) = &self.nonlexical_regioncx { @@ -70,6 +70,18 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { } } + Cause::UniversalRegion(region_vid) => { + if let Some(region) = regioncx.to_error_region(region_vid) { + + self.tcx.note_and_explain_free_region( + err, + "borrowed value must be valid for ", + region, + "...", + ); + } + } + _ => { } } diff --git a/src/librustc_mir/borrow_check/nll/region_infer/mod.rs b/src/librustc_mir/borrow_check/nll/region_infer/mod.rs index d2f6d626c9eb..e0a8877a6ab1 100644 --- a/src/librustc_mir/borrow_check/nll/region_infer/mod.rs +++ b/src/librustc_mir/borrow_check/nll/region_infer/mod.rs @@ -588,7 +588,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { /// existentially bound, then we check its inferred value and try /// to find a good name from that. Returns `None` if we can't find /// one (e.g., this is just some random part of the CFG). - fn to_error_region(&self, r: RegionVid) -> Option> { + pub fn to_error_region(&self, r: RegionVid) -> Option> { if self.universal_regions.is_universal_region(r) { return self.definitions[r].external_name; } else { diff --git a/src/test/ui/nll/borrowed-universal-error-2.rs b/src/test/ui/nll/borrowed-universal-error-2.rs new file mode 100644 index 000000000000..da03a9fc39b6 --- /dev/null +++ b/src/test/ui/nll/borrowed-universal-error-2.rs @@ -0,0 +1,22 @@ +// Copyright 2018 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: -Znll-dump-cause + +#![feature(nll)] +#![allow(warnings)] + +fn foo<'a>(x: &'a (u32,)) -> &'a u32 { + let v = 22; + &v + //~^ ERROR `v` does not live long enough [E0597] +} + +fn main() {} diff --git a/src/test/ui/nll/borrowed-universal-error-2.stderr b/src/test/ui/nll/borrowed-universal-error-2.stderr new file mode 100644 index 000000000000..ff999a71e0f9 --- /dev/null +++ b/src/test/ui/nll/borrowed-universal-error-2.stderr @@ -0,0 +1,18 @@ +error[E0597]: `v` does not live long enough + --> $DIR/borrowed-universal-error-2.rs:18:5 + | +LL | &v + | ^^ borrowed value does not live long enough +LL | //~^ ERROR `v` does not live long enough [E0597] +LL | } + | - borrowed value only lives until here + | +note: borrowed value must be valid for the lifetime 'a as defined on the function body at 16:1... + --> $DIR/borrowed-universal-error-2.rs:16:1 + | +LL | fn foo<'a>(x: &'a (u32,)) -> &'a u32 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +If you want more information on this error, try using "rustc --explain E0597" diff --git a/src/test/ui/nll/borrowed-universal-error.rs b/src/test/ui/nll/borrowed-universal-error.rs new file mode 100644 index 000000000000..fdc4c29071ee --- /dev/null +++ b/src/test/ui/nll/borrowed-universal-error.rs @@ -0,0 +1,26 @@ +// Copyright 2018 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: -Znll-dump-cause + +#![feature(nll)] +#![allow(warnings)] + +fn gimme(x: &(u32,)) -> &u32 { + &x.0 +} + +fn foo<'a>(x: &'a (u32,)) -> &'a u32 { + let v = 22; + gimme(&(v,)) + //~^ ERROR borrowed value does not live long enough [E0597] +} + +fn main() {} diff --git a/src/test/ui/nll/borrowed-universal-error.stderr b/src/test/ui/nll/borrowed-universal-error.stderr new file mode 100644 index 000000000000..4a3d0c6d959f --- /dev/null +++ b/src/test/ui/nll/borrowed-universal-error.stderr @@ -0,0 +1,18 @@ +error[E0597]: borrowed value does not live long enough + --> $DIR/borrowed-universal-error.rs:22:12 + | +LL | gimme(&(v,)) + | ^^^^ temporary value does not live long enough +LL | //~^ ERROR borrowed value does not live long enough [E0597] +LL | } + | - temporary value only lives until here + | +note: borrowed value must be valid for the lifetime 'a as defined on the function body at 20:1... + --> $DIR/borrowed-universal-error.rs:20:1 + | +LL | fn foo<'a>(x: &'a (u32,)) -> &'a u32 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + +If you want more information on this error, try using "rustc --explain E0597" diff --git a/src/test/ui/nll/capture-ref-in-struct.stderr b/src/test/ui/nll/capture-ref-in-struct.stderr index 316a918e4ee9..1c545906893a 100644 --- a/src/test/ui/nll/capture-ref-in-struct.stderr +++ b/src/test/ui/nll/capture-ref-in-struct.stderr @@ -9,8 +9,6 @@ LL | } LL | LL | deref(p); | - borrow later used here - | - = note: borrowed value must be valid for lifetime '_#5r... error: aborting due to previous error diff --git a/src/test/ui/nll/closure-requirements/escape-argument.stderr b/src/test/ui/nll/closure-requirements/escape-argument.stderr index 93a7bab3386d..18ffdc583497 100644 --- a/src/test/ui/nll/closure-requirements/escape-argument.stderr +++ b/src/test/ui/nll/closure-requirements/escape-argument.stderr @@ -34,8 +34,6 @@ LL | } LL | LL | deref(p); | - borrow later used here - | - = note: borrowed value must be valid for lifetime '_#6r... error: aborting due to previous error diff --git a/src/test/ui/nll/closure-requirements/escape-upvar-nested.stderr b/src/test/ui/nll/closure-requirements/escape-upvar-nested.stderr index b6c1d808ff5b..7b2b2f748726 100644 --- a/src/test/ui/nll/closure-requirements/escape-upvar-nested.stderr +++ b/src/test/ui/nll/closure-requirements/escape-upvar-nested.stderr @@ -61,8 +61,6 @@ LL | } LL | LL | deref(p); | - borrow later used here - | - = note: borrowed value must be valid for lifetime '_#4r... error: aborting due to previous error diff --git a/src/test/ui/nll/closure-requirements/escape-upvar-ref.stderr b/src/test/ui/nll/closure-requirements/escape-upvar-ref.stderr index 3cb6524f3b48..0a45603a42cd 100644 --- a/src/test/ui/nll/closure-requirements/escape-upvar-ref.stderr +++ b/src/test/ui/nll/closure-requirements/escape-upvar-ref.stderr @@ -38,8 +38,6 @@ LL | } LL | LL | deref(p); | - borrow later used here - | - = note: borrowed value must be valid for lifetime '_#4r... error: aborting due to previous error diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr index eb4d264bf827..21ed421fe96c 100644 --- a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr +++ b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr @@ -78,8 +78,6 @@ LL | let cell = Cell::new(&a); ... LL | } | - borrowed value only lives until here - | - = note: borrowed value must be valid for lifetime '_#2r... error: aborting due to 2 previous errors diff --git a/src/test/ui/nll/return-ref-mut-issue-46557.stderr b/src/test/ui/nll/return-ref-mut-issue-46557.stderr index f7e85e4277ba..c77e0772ce96 100644 --- a/src/test/ui/nll/return-ref-mut-issue-46557.stderr +++ b/src/test/ui/nll/return-ref-mut-issue-46557.stderr @@ -6,8 +6,6 @@ LL | let ref mut x = 1234543; //~ ERROR borrowed value does not live long en LL | x LL | } | - temporary value only lives until here - | - = note: borrowed value must be valid for lifetime '_#2r... error: aborting due to previous error From 99c42dccfa7d00b6f488bcd61a5cf141d2112acf Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Thu, 1 Mar 2018 16:43:03 -0300 Subject: [PATCH 24/68] rustfmt over error_reporting, explain_borrow and region_infer mods --- src/librustc/infer/error_reporting/mod.rs | 738 ++++++++++-------- .../borrow_check/error_reporting.rs | 171 ++-- .../borrow_check/nll/explain_borrow/mod.rs | 4 +- .../borrow_check/nll/region_infer/mod.rs | 54 +- 4 files changed, 513 insertions(+), 454 deletions(-) diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index b51ddf719cbf..37a84361aea2 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -56,7 +56,7 @@ //! time of error detection. use infer; -use super::{InferCtxt, TypeTrace, SubregionOrigin, RegionVariableOrigin, ValuePairs}; +use super::{InferCtxt, RegionVariableOrigin, SubregionOrigin, TypeTrace, ValuePairs}; use super::region_constraints::GenericKind; use super::lexical_region_resolve::RegionResolutionError; @@ -81,18 +81,22 @@ mod need_type_info; pub mod nice_region_error; impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { - pub fn note_and_explain_region(self, - region_scope_tree: ®ion::ScopeTree, - err: &mut DiagnosticBuilder, - prefix: &str, - region: ty::Region<'tcx>, - suffix: &str) { + pub fn note_and_explain_region( + self, + region_scope_tree: ®ion::ScopeTree, + err: &mut DiagnosticBuilder, + prefix: &str, + region: ty::Region<'tcx>, + suffix: &str, + ) { let (description, span) = match *region { ty::ReScope(scope) => { let new_string; let unknown_scope = || { - format!("{}unknown scope: {:?}{}. Please report a bug.", - prefix, scope, suffix) + format!( + "{}unknown scope: {:?}{}. Please report a bug.", + prefix, scope, suffix + ) }; let span = scope.span(self, region_scope_tree); let tag = match self.hir.find(scope.node_id(self, region_scope_tree)) { @@ -101,8 +105,8 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { hir::ExprCall(..) => "call", hir::ExprMethodCall(..) => "method call", hir::ExprMatch(.., hir::MatchSource::IfLetDesugar { .. }) => "if let", - hir::ExprMatch(.., hir::MatchSource::WhileLetDesugar) => "while let", - hir::ExprMatch(.., hir::MatchSource::ForLoopDesugar) => "for", + hir::ExprMatch(.., hir::MatchSource::WhileLetDesugar) => "while let", + hir::ExprMatch(.., hir::MatchSource::ForLoopDesugar) => "for", hir::ExprMatch(..) => "match", _ => "expression", }, @@ -117,29 +121,24 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { }; let scope_decorated_tag = match scope.data() { region::ScopeData::Node(_) => tag, - region::ScopeData::CallSite(_) => { - "scope of call-site for function" - } - region::ScopeData::Arguments(_) => { - "scope of function body" - } + region::ScopeData::CallSite(_) => "scope of call-site for function", + region::ScopeData::Arguments(_) => "scope of function body", region::ScopeData::Destruction(_) => { new_string = format!("destruction scope surrounding {}", tag); &new_string[..] } region::ScopeData::Remainder(r) => { - new_string = format!("block suffix following statement {}", - r.first_statement_index.index()); + new_string = format!( + "block suffix following statement {}", + r.first_statement_index.index() + ); &new_string[..] } }; self.explain_span(scope_decorated_tag, span) } - ty::ReEarlyBound(_) | - ty::ReFree(_) => { - self.msg_span_from_free_region(region) - } + ty::ReEarlyBound(_) | ty::ReFree(_) => self.msg_span_from_free_region(region), ty::ReStatic => ("the static lifetime".to_owned(), None), @@ -150,46 +149,37 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { // // We shouldn't really be having unification failures with ReVar // and ReLateBound though. - ty::ReSkolemized(..) | - ty::ReVar(_) | - ty::ReLateBound(..) | - ty::ReErased => { + ty::ReSkolemized(..) | ty::ReVar(_) | ty::ReLateBound(..) | ty::ReErased => { (format!("lifetime {:?}", region), None) } // We shouldn't encounter an error message with ReClosureBound. ty::ReClosureBound(..) => { - bug!( - "encountered unexpected ReClosureBound: {:?}", - region, - ); + bug!("encountered unexpected ReClosureBound: {:?}", region,); } }; TyCtxt::emit_msg_span(err, prefix, description, span, suffix); } - pub fn note_and_explain_free_region(self, - err: &mut DiagnosticBuilder, - prefix: &str, - region: ty::Region<'tcx>, - suffix: &str) { + pub fn note_and_explain_free_region( + self, + err: &mut DiagnosticBuilder, + prefix: &str, + region: ty::Region<'tcx>, + suffix: &str, + ) { let (description, span) = self.msg_span_from_free_region(region); - TyCtxt::emit_msg_span(err, prefix, description, span, suffix); } - fn msg_span_from_free_region(self, - region: ty::Region<'tcx>) - -> (String, Option) { + fn msg_span_from_free_region(self, region: ty::Region<'tcx>) -> (String, Option) { let scope = region.free_region_binding_scope(self); - let node = self.hir.as_local_node_id(scope) - .unwrap_or(DUMMY_NODE_ID); + let node = self.hir.as_local_node_id(scope).unwrap_or(DUMMY_NODE_ID); let unknown; let tag = match self.hir.find(node) { - Some(hir_map::NodeBlock(_)) | - Some(hir_map::NodeExpr(_)) => "body", + Some(hir_map::NodeBlock(_)) | Some(hir_map::NodeExpr(_)) => "body", Some(hir_map::NodeItem(it)) => Self::item_scope_tag(&it), Some(hir_map::NodeTraitItem(it)) => Self::trait_item_scope_tag(&it), Some(hir_map::NodeImplItem(it)) => Self::impl_item_scope_tag(&it), @@ -197,45 +187,55 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { // this really should not happen, but it does: // FIXME(#27942) Some(_) => { - unknown = format!("unexpected node ({}) for scope {:?}. \ - Please report a bug.", - self.hir.node_to_string(node), scope); + unknown = format!( + "unexpected node ({}) for scope {:?}. \ + Please report a bug.", + self.hir.node_to_string(node), + scope + ); &unknown } None => { - unknown = format!("unknown node for scope {:?}. \ - Please report a bug.", scope); + unknown = format!( + "unknown node for scope {:?}. \ + Please report a bug.", + scope + ); &unknown } }; let (prefix, span) = match *region { - ty::ReEarlyBound(ref br) => { - (format!("the lifetime {} as defined on", br.name), - self.sess.codemap().def_span(self.hir.span(node))) - } - ty::ReFree(ref fr) => { - match fr.bound_region { - ty::BrAnon(idx) => { - (format!("the anonymous lifetime #{} defined on", idx + 1), - self.hir.span(node)) - } - ty::BrFresh(_) => ("an anonymous lifetime defined on".to_owned(), - self.hir.span(node)), - _ => (format!("the lifetime {} as defined on", fr.bound_region), - self.sess.codemap().def_span(self.hir.span(node))), - } - } - _ => bug!() + ty::ReEarlyBound(ref br) => ( + format!("the lifetime {} as defined on", br.name), + self.sess.codemap().def_span(self.hir.span(node)), + ), + ty::ReFree(ref fr) => match fr.bound_region { + ty::BrAnon(idx) => ( + format!("the anonymous lifetime #{} defined on", idx + 1), + self.hir.span(node), + ), + ty::BrFresh(_) => ( + "an anonymous lifetime defined on".to_owned(), + self.hir.span(node), + ), + _ => ( + format!("the lifetime {} as defined on", fr.bound_region), + self.sess.codemap().def_span(self.hir.span(node)), + ), + }, + _ => bug!(), }; let (msg, opt_span) = self.explain_span(tag, span); (format!("{} {}", prefix, msg), opt_span) } - fn emit_msg_span(err: &mut DiagnosticBuilder, - prefix: &str, - description: String, - span: Option, - suffix: &str) { + fn emit_msg_span( + err: &mut DiagnosticBuilder, + prefix: &str, + description: String, + span: Option, + suffix: &str, + ) { let message = format!("{}{}{}", prefix, description, suffix); if let Some(span) = span { @@ -253,40 +253,40 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { hir::ItemEnum(..) => "enum", hir::ItemTrait(..) => "trait", hir::ItemFn(..) => "function body", - _ => "item" + _ => "item", } } fn trait_item_scope_tag(item: &hir::TraitItem) -> &'static str { match item.node { hir::TraitItemKind::Method(..) => "method body", - hir::TraitItemKind::Const(..) | - hir::TraitItemKind::Type(..) => "associated item" + hir::TraitItemKind::Const(..) | hir::TraitItemKind::Type(..) => "associated item", } } fn impl_item_scope_tag(item: &hir::ImplItem) -> &'static str { match item.node { hir::ImplItemKind::Method(..) => "method body", - hir::ImplItemKind::Const(..) | - hir::ImplItemKind::Type(_) => "associated item" + hir::ImplItemKind::Const(..) | hir::ImplItemKind::Type(_) => "associated item", } } - fn explain_span(self, - heading: &str, span: Span) - -> (String, Option) { + fn explain_span(self, heading: &str, span: Span) -> (String, Option) { let lo = self.sess.codemap().lookup_char_pos_adj(span.lo()); - (format!("the {} at {}:{}", heading, lo.line, lo.col.to_usize() + 1), - Some(span)) + ( + format!("the {} at {}:{}", heading, lo.line, lo.col.to_usize() + 1), + Some(span), + ) } } impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { - pub fn report_region_errors(&self, - region_scope_tree: ®ion::ScopeTree, - errors: &Vec>, - will_later_be_reported_by_nll: bool) { + pub fn report_region_errors( + &self, + region_scope_tree: ®ion::ScopeTree, + errors: &Vec>, + will_later_be_reported_by_nll: bool, + ) { debug!("report_region_errors(): {} errors to start", errors.len()); if will_later_be_reported_by_nll && self.tcx.sess.nll() { @@ -300,17 +300,17 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { // But with -Znll, it's nice to have some note for later. for error in errors { match *error { - RegionResolutionError::ConcreteFailure(ref origin, ..) | - RegionResolutionError::GenericBoundFailure(ref origin, ..) => { - self.tcx.sess.span_warn( - origin.span(), - "not reporting region error due to -Znll"); + RegionResolutionError::ConcreteFailure(ref origin, ..) + | RegionResolutionError::GenericBoundFailure(ref origin, ..) => { + self.tcx + .sess + .span_warn(origin.span(), "not reporting region error due to -Znll"); } RegionResolutionError::SubSupConflict(ref rvo, ..) => { - self.tcx.sess.span_warn( - rvo.span(), - "not reporting region error due to -Znll"); + self.tcx + .sess + .span_warn(rvo.span(), "not reporting region error due to -Znll"); } } } @@ -322,7 +322,10 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { // together into a `ProcessedErrors` group: let errors = self.process_errors(errors); - debug!("report_region_errors: {} errors after preprocessing", errors.len()); + debug!( + "report_region_errors: {} errors after preprocessing", + errors.len() + ); for error in errors { debug!("report_region_errors: error = {:?}", error); @@ -337,7 +340,8 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { // the error. If all of these fails, we fall back to a rather // general bit of code that displays the error information RegionResolutionError::ConcreteFailure(origin, sub, sup) => { - self.report_concrete_failure(region_scope_tree, origin, sub, sup).emit(); + self.report_concrete_failure(region_scope_tree, origin, sub, sup) + .emit(); } RegionResolutionError::GenericBoundFailure(origin, param_ty, sub) => { @@ -350,17 +354,21 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { ); } - RegionResolutionError::SubSupConflict(var_origin, - sub_origin, - sub_r, - sup_origin, - sup_r) => { - self.report_sub_sup_conflict(region_scope_tree, - var_origin, - sub_origin, - sub_r, - sup_origin, - sup_r); + RegionResolutionError::SubSupConflict( + var_origin, + sub_origin, + sub_r, + sup_origin, + sup_r, + ) => { + self.report_sub_sup_conflict( + region_scope_tree, + var_origin, + sub_origin, + sub_r, + sup_origin, + sup_r, + ); } } } @@ -377,8 +385,10 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { // The method also attempts to weed out messages that seem like // duplicates that will be unhelpful to the end-user. But // obviously it never weeds out ALL errors. - fn process_errors(&self, errors: &Vec>) - -> Vec> { + fn process_errors( + &self, + errors: &Vec>, + ) -> Vec> { debug!("process_errors()"); // We want to avoid reporting generic-bound failures if we can @@ -395,15 +405,18 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { let is_bound_failure = |e: &RegionResolutionError<'tcx>| match *e { RegionResolutionError::GenericBoundFailure(..) => true, - RegionResolutionError::ConcreteFailure(..) | - RegionResolutionError::SubSupConflict(..) => false, + RegionResolutionError::ConcreteFailure(..) + | RegionResolutionError::SubSupConflict(..) => false, }; - let mut errors = if errors.iter().all(|e| is_bound_failure(e)) { errors.clone() } else { - errors.iter().filter(|&e| !is_bound_failure(e)).cloned().collect() + errors + .iter() + .filter(|&e| !is_bound_failure(e)) + .cloned() + .collect() }; // sort the errors by span, for better error message stability. @@ -416,10 +429,12 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { } /// Adds a note if the types come from similarly named crates - fn check_and_note_conflicting_crates(&self, - err: &mut DiagnosticBuilder, - terr: &TypeError<'tcx>, - sp: Span) { + fn check_and_note_conflicting_crates( + &self, + err: &mut DiagnosticBuilder, + terr: &TypeError<'tcx>, + sp: Span, + ) { let report_path_match = |err: &mut DiagnosticBuilder, did1: DefId, did2: DefId| { // Only external crates, if either is from a local // module we could have false positives @@ -430,12 +445,16 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { let found_abs_path = self.tcx.absolute_item_path_str(did2); // We compare strings because DefPath can be different // for imported and non-imported crates - if exp_path == found_path - || exp_abs_path == found_abs_path { + if exp_path == found_path || exp_abs_path == found_abs_path { let crate_name = self.tcx.crate_name(did1.krate); - err.span_note(sp, &format!("Perhaps two different versions \ - of crate `{}` are being used?", - crate_name)); + err.span_note( + sp, + &format!( + "Perhaps two different versions \ + of crate `{}` are being used?", + crate_name + ), + ); } } }; @@ -446,24 +465,21 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { match (&exp_found.expected.sty, &exp_found.found.sty) { (&ty::TyAdt(exp_adt, _), &ty::TyAdt(found_adt, _)) => { report_path_match(err, exp_adt.did, found_adt.did); - }, - _ => () + } + _ => (), } - }, + } TypeError::Traits(ref exp_found) => { report_path_match(err, exp_found.expected, exp_found.found); - }, - _ => () // FIXME(#22750) handle traits and stuff + } + _ => (), // FIXME(#22750) handle traits and stuff } } - fn note_error_origin(&self, - err: &mut DiagnosticBuilder<'tcx>, - cause: &ObligationCause<'tcx>) - { + fn note_error_origin(&self, err: &mut DiagnosticBuilder<'tcx>, cause: &ObligationCause<'tcx>) { match cause.code { ObligationCauseCode::MatchExpressionArm { arm_span, source } => match source { - hir::MatchSource::IfLetDesugar {..} => { + hir::MatchSource::IfLetDesugar { .. } => { let msg = "`if let` arm with an incompatible type"; if self.tcx.sess.codemap().is_multiline(arm_span) { err.span_note(arm_span, msg); @@ -480,7 +496,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { } } }, - _ => () + _ => (), } } @@ -497,13 +513,15 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { /// Bar /// -------- this type is the same as a type argument in the other type, not highlighted /// ``` - fn highlight_outer(&self, - value: &mut DiagnosticStyledString, - other_value: &mut DiagnosticStyledString, - name: String, - sub: &ty::subst::Substs<'tcx>, - pos: usize, - other_ty: &Ty<'tcx>) { + fn highlight_outer( + &self, + value: &mut DiagnosticStyledString, + other_value: &mut DiagnosticStyledString, + name: String, + sub: &ty::subst::Substs<'tcx>, + pos: usize, + other_ty: &Ty<'tcx>, + ) { // `value` and `other_value` hold two incomplete type representation for display. // `name` is the path of both types being compared. `sub` value.push_highlighted(name); @@ -513,14 +531,17 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { } // Output the lifetimes fot the first type - let lifetimes = sub.regions().map(|lifetime| { - let s = format!("{}", lifetime); - if s.is_empty() { - "'_".to_string() - } else { - s - } - }).collect::>().join(", "); + let lifetimes = sub.regions() + .map(|lifetime| { + let s = format!("{}", lifetime); + if s.is_empty() { + "'_".to_string() + } else { + s + } + }) + .collect::>() + .join(", "); if !lifetimes.is_empty() { if sub.regions().count() < len { value.push_normal(lifetimes + &", "); @@ -570,13 +591,15 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { /// Bar /// -------- this type is the same as a type argument in the other type, not highlighted /// ``` - fn cmp_type_arg(&self, - mut t1_out: &mut DiagnosticStyledString, - mut t2_out: &mut DiagnosticStyledString, - path: String, - sub: &ty::subst::Substs<'tcx>, - other_path: String, - other_ty: &Ty<'tcx>) -> Option<()> { + fn cmp_type_arg( + &self, + mut t1_out: &mut DiagnosticStyledString, + mut t2_out: &mut DiagnosticStyledString, + path: String, + sub: &ty::subst::Substs<'tcx>, + other_path: String, + other_ty: &Ty<'tcx>, + ) -> Option<()> { for (i, ta) in sub.types().enumerate() { if &ta == other_ty { self.highlight_outer(&mut t1_out, &mut t2_out, path, sub, i, &other_ty); @@ -594,11 +617,13 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { } /// Add a `,` to the type representation only if it is appropriate. - fn push_comma(&self, - value: &mut DiagnosticStyledString, - other_value: &mut DiagnosticStyledString, - len: usize, - pos: usize) { + fn push_comma( + &self, + value: &mut DiagnosticStyledString, + other_value: &mut DiagnosticStyledString, + len: usize, + pos: usize, + ) { if len > 0 && pos != len - 1 { value.push_normal(", "); other_value.push_normal(", "); @@ -607,39 +632,39 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { /// Compare two given types, eliding parts that are the same between them and highlighting /// relevant differences, and return two representation of those types for highlighted printing. - fn cmp(&self, t1: Ty<'tcx>, t2: Ty<'tcx>) - -> (DiagnosticStyledString, DiagnosticStyledString) - { + fn cmp(&self, t1: Ty<'tcx>, t2: Ty<'tcx>) -> (DiagnosticStyledString, DiagnosticStyledString) { fn equals<'tcx>(a: &Ty<'tcx>, b: &Ty<'tcx>) -> bool { match (&a.sty, &b.sty) { (a, b) if *a == *b => true, - (&ty::TyInt(_), &ty::TyInfer(ty::InferTy::IntVar(_))) | - (&ty::TyInfer(ty::InferTy::IntVar(_)), &ty::TyInt(_)) | - (&ty::TyInfer(ty::InferTy::IntVar(_)), &ty::TyInfer(ty::InferTy::IntVar(_))) | - (&ty::TyFloat(_), &ty::TyInfer(ty::InferTy::FloatVar(_))) | - (&ty::TyInfer(ty::InferTy::FloatVar(_)), &ty::TyFloat(_)) | - (&ty::TyInfer(ty::InferTy::FloatVar(_)), - &ty::TyInfer(ty::InferTy::FloatVar(_))) => true, + (&ty::TyInt(_), &ty::TyInfer(ty::InferTy::IntVar(_))) + | (&ty::TyInfer(ty::InferTy::IntVar(_)), &ty::TyInt(_)) + | (&ty::TyInfer(ty::InferTy::IntVar(_)), &ty::TyInfer(ty::InferTy::IntVar(_))) + | (&ty::TyFloat(_), &ty::TyInfer(ty::InferTy::FloatVar(_))) + | (&ty::TyInfer(ty::InferTy::FloatVar(_)), &ty::TyFloat(_)) + | ( + &ty::TyInfer(ty::InferTy::FloatVar(_)), + &ty::TyInfer(ty::InferTy::FloatVar(_)), + ) => true, _ => false, } } - fn push_ty_ref<'tcx>(r: &ty::Region<'tcx>, - tnm: &ty::TypeAndMut<'tcx>, - s: &mut DiagnosticStyledString) { + fn push_ty_ref<'tcx>( + r: &ty::Region<'tcx>, + tnm: &ty::TypeAndMut<'tcx>, + s: &mut DiagnosticStyledString, + ) { let r = &format!("{}", r); - s.push_highlighted(format!("&{}{}{}", - r, - if r == "" { - "" - } else { - " " - }, - if tnm.mutbl == hir::MutMutable { - "mut " - } else { - "" - })); + s.push_highlighted(format!( + "&{}{}{}", + r, + if r == "" { "" } else { " " }, + if tnm.mutbl == hir::MutMutable { + "mut " + } else { + "" + } + )); s.push_normal(format!("{}", tnm.ty)); } @@ -732,12 +757,15 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { // Foo // ------- this type argument is exactly the same as the other type // Bar - if self.cmp_type_arg(&mut values.0, - &mut values.1, - path1.clone(), - sub1, - path2.clone(), - &t2).is_some() { + if self.cmp_type_arg( + &mut values.0, + &mut values.1, + path1.clone(), + sub1, + path2.clone(), + &t2, + ).is_some() + { return values; } // Check for case: @@ -745,19 +773,18 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { // Bar // Foo> // ------- this type argument is exactly the same as the other type - if self.cmp_type_arg(&mut values.1, - &mut values.0, - path2, - sub2, - path1, - &t1).is_some() { + if self.cmp_type_arg(&mut values.1, &mut values.0, path2, sub2, path1, &t1) + .is_some() + { return values; } // We couldn't find anything in common, highlight everything. // let x: Bar = y::>(); - (DiagnosticStyledString::highlighted(format!("{}", t1)), - DiagnosticStyledString::highlighted(format!("{}", t2))) + ( + DiagnosticStyledString::highlighted(format!("{}", t1)), + DiagnosticStyledString::highlighted(format!("{}", t2)), + ) } } @@ -786,28 +813,36 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { _ => { if t1 == t2 { // The two types are the same, elide and don't highlight. - (DiagnosticStyledString::normal("_"), DiagnosticStyledString::normal("_")) + ( + DiagnosticStyledString::normal("_"), + DiagnosticStyledString::normal("_"), + ) } else { // We couldn't find anything in common, highlight everything. - (DiagnosticStyledString::highlighted(format!("{}", t1)), - DiagnosticStyledString::highlighted(format!("{}", t2))) + ( + DiagnosticStyledString::highlighted(format!("{}", t1)), + DiagnosticStyledString::highlighted(format!("{}", t2)), + ) } } } } - pub fn note_type_err(&self, - diag: &mut DiagnosticBuilder<'tcx>, - cause: &ObligationCause<'tcx>, - secondary_span: Option<(Span, String)>, - mut values: Option>, - terr: &TypeError<'tcx>) - { + pub fn note_type_err( + &self, + diag: &mut DiagnosticBuilder<'tcx>, + cause: &ObligationCause<'tcx>, + secondary_span: Option<(Span, String)>, + mut values: Option>, + terr: &TypeError<'tcx>, + ) { // For some types of errors, expected-found does not make // sense, so just ignore the values we were given. match terr { - TypeError::CyclicTy(_) => { values = None; } - _ => { } + TypeError::CyclicTy(_) => { + values = None; + } + _ => {} } let (expected_found, exp_found, is_simple_error) = match values { @@ -815,8 +850,8 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { Some(values) => { let (is_simple_error, exp_found) = match values { ValuePairs::Types(exp_found) => { - let is_simple_err = exp_found.expected.is_primitive() - && exp_found.found.is_primitive(); + let is_simple_err = + exp_found.expected.is_primitive() && exp_found.found.is_primitive(); (is_simple_err, Some(exp_found)) } @@ -827,7 +862,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { None => { // Derived error. Cancel the emitter. self.tcx.sess.diagnostic().cancel(diag); - return + return; } }; (vals, exp_found, is_simple_error) @@ -845,9 +880,12 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { match (terr, is_simple_error, expected == found) { (&TypeError::Sorts(ref values), false, true) => { diag.note_expected_found_extra( - &"type", expected, found, + &"type", + expected, + found, &format!(" ({})", values.expected.sort_string(self.tcx)), - &format!(" ({})", values.found.sort_string(self.tcx))); + &format!(" ({})", values.found.sort_string(self.tcx)), + ); } (_, false, _) => { if let Some(exp_found) = exp_found { @@ -855,12 +893,12 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { TypeVariants::TyFnDef(def, _) => { (Some(def), Some(self.tcx.fn_sig(def).output())) } - _ => (None, None) + _ => (None, None), }; let exp_is_struct = match exp_found.expected.sty { TypeVariants::TyAdt(def, _) => def.is_struct(), - _ => false + _ => false, }; if let (Some(def_id), Some(ret_ty)) = (def_id, ret_ty) { @@ -888,14 +926,15 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { self.note_error_origin(diag, &cause); } - pub fn report_and_explain_type_error(&self, - trace: TypeTrace<'tcx>, - terr: &TypeError<'tcx>) - -> DiagnosticBuilder<'tcx> - { - debug!("report_and_explain_type_error(trace={:?}, terr={:?})", - trace, - terr); + pub fn report_and_explain_type_error( + &self, + trace: TypeTrace<'tcx>, + terr: &TypeError<'tcx>, + ) -> DiagnosticBuilder<'tcx> { + debug!( + "report_and_explain_type_error(trace={:?}, terr={:?})", + trace, terr + ); let span = trace.cause.span(&self.tcx); let failure_code = trace.cause.as_failure_code(terr); @@ -917,9 +956,10 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { diag } - fn values_str(&self, values: &ValuePairs<'tcx>) - -> Option<(DiagnosticStyledString, DiagnosticStyledString)> - { + fn values_str( + &self, + values: &ValuePairs<'tcx>, + ) -> Option<(DiagnosticStyledString, DiagnosticStyledString)> { match *values { infer::Types(ref exp_found) => self.expected_found_str_ty(exp_found), infer::TraitRefs(ref exp_found) => self.expected_found_str(exp_found), @@ -927,9 +967,10 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { } } - fn expected_found_str_ty(&self, - exp_found: &ty::error::ExpectedFound>) - -> Option<(DiagnosticStyledString, DiagnosticStyledString)> { + fn expected_found_str_ty( + &self, + exp_found: &ty::error::ExpectedFound>, + ) -> Option<(DiagnosticStyledString, DiagnosticStyledString)> { let exp_found = self.resolve_type_vars_if_possible(exp_found); if exp_found.references_error() { return None; @@ -941,25 +982,27 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { /// Returns a string of the form "expected `{}`, found `{}`". fn expected_found_str>( &self, - exp_found: &ty::error::ExpectedFound) - -> Option<(DiagnosticStyledString, DiagnosticStyledString)> - { + exp_found: &ty::error::ExpectedFound, + ) -> Option<(DiagnosticStyledString, DiagnosticStyledString)> { let exp_found = self.resolve_type_vars_if_possible(exp_found); if exp_found.references_error() { return None; } - Some((DiagnosticStyledString::highlighted(format!("{}", exp_found.expected)), - DiagnosticStyledString::highlighted(format!("{}", exp_found.found)))) + Some(( + DiagnosticStyledString::highlighted(format!("{}", exp_found.expected)), + DiagnosticStyledString::highlighted(format!("{}", exp_found.found)), + )) } - pub fn report_generic_bound_failure(&self, - region_scope_tree: ®ion::ScopeTree, - span: Span, - origin: Option>, - bound_kind: GenericKind<'tcx>, - sub: Region<'tcx>) - { + pub fn report_generic_bound_failure( + &self, + region_scope_tree: ®ion::ScopeTree, + span: Span, + origin: Option>, + bound_kind: GenericKind<'tcx>, + sub: Region<'tcx>, + ) { // Attempt to obtain the span of the parameter so we can // suggest adding an explicit lifetime bound to it. let type_param_span = match (self.in_progress_tables, bound_kind) { @@ -985,8 +1028,10 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { // `sp` only covers `T`, change it so that it covers // `T:` when appropriate let sp = if has_lifetimes { - sp.to(self.tcx.sess.codemap().next_point( - self.tcx.sess.codemap().next_point(sp))) + sp.to(self.tcx + .sess + .codemap() + .next_point(self.tcx.sess.codemap().next_point(sp))) } else { sp }; @@ -1001,37 +1046,39 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { }; let labeled_user_string = match bound_kind { - GenericKind::Param(ref p) => - format!("the parameter type `{}`", p), - GenericKind::Projection(ref p) => - format!("the associated type `{}`", p), + GenericKind::Param(ref p) => format!("the parameter type `{}`", p), + GenericKind::Projection(ref p) => format!("the associated type `{}`", p), }; if let Some(SubregionOrigin::CompareImplMethodObligation { - span, item_name, impl_item_def_id, trait_item_def_id, - }) = origin { - self.report_extra_impl_obligation(span, - item_name, - impl_item_def_id, - trait_item_def_id, - &format!("`{}: {}`", bound_kind, sub)) - .emit(); + span, + item_name, + impl_item_def_id, + trait_item_def_id, + }) = origin + { + self.report_extra_impl_obligation( + span, + item_name, + impl_item_def_id, + trait_item_def_id, + &format!("`{}: {}`", bound_kind, sub), + ).emit(); return; } - fn binding_suggestion<'tcx, S: fmt::Display>(err: &mut DiagnosticBuilder<'tcx>, - type_param_span: Option<(Span, bool)>, - bound_kind: GenericKind<'tcx>, - sub: S) { - let consider = &format!("consider adding an explicit lifetime bound `{}: {}`...", - bound_kind, - sub); + fn binding_suggestion<'tcx, S: fmt::Display>( + err: &mut DiagnosticBuilder<'tcx>, + type_param_span: Option<(Span, bool)>, + bound_kind: GenericKind<'tcx>, + sub: S, + ) { + let consider = &format!( + "consider adding an explicit lifetime bound `{}: {}`...", + bound_kind, sub + ); if let Some((sp, has_lifetimes)) = type_param_span { - let tail = if has_lifetimes { - " + " - } else { - "" - }; + let tail = if has_lifetimes { " + " } else { "" }; let suggestion = format!("{}: {}{}", bound_kind, sub, tail); err.span_suggestion_short(sp, consider, suggestion); } else { @@ -1040,44 +1087,56 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { } let mut err = match *sub { - ty::ReEarlyBound(_) | - ty::ReFree(ty::FreeRegion {bound_region: ty::BrNamed(..), ..}) => { + ty::ReEarlyBound(_) + | ty::ReFree(ty::FreeRegion { + bound_region: ty::BrNamed(..), + .. + }) => { // Does the required lifetime have a nice name we can print? - let mut err = struct_span_err!(self.tcx.sess, - span, - E0309, - "{} may not live long enough", - labeled_user_string); + let mut err = struct_span_err!( + self.tcx.sess, + span, + E0309, + "{} may not live long enough", + labeled_user_string + ); binding_suggestion(&mut err, type_param_span, bound_kind, sub); err } ty::ReStatic => { // Does the required lifetime have a nice name we can print? - let mut err = struct_span_err!(self.tcx.sess, - span, - E0310, - "{} may not live long enough", - labeled_user_string); + let mut err = struct_span_err!( + self.tcx.sess, + span, + E0310, + "{} may not live long enough", + labeled_user_string + ); binding_suggestion(&mut err, type_param_span, bound_kind, "'static"); err } _ => { // If not, be less specific. - let mut err = struct_span_err!(self.tcx.sess, - span, - E0311, - "{} may not live long enough", - labeled_user_string); - err.help(&format!("consider adding an explicit lifetime bound for `{}`", - bound_kind)); + let mut err = struct_span_err!( + self.tcx.sess, + span, + E0311, + "{} may not live long enough", + labeled_user_string + ); + err.help(&format!( + "consider adding an explicit lifetime bound for `{}`", + bound_kind + )); self.tcx.note_and_explain_region( region_scope_tree, &mut err, &format!("{} must be valid for ", labeled_user_string), sub, - "..."); + "...", + ); err } }; @@ -1088,26 +1147,31 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { err.emit(); } - fn report_sub_sup_conflict(&self, - region_scope_tree: ®ion::ScopeTree, - var_origin: RegionVariableOrigin, - sub_origin: SubregionOrigin<'tcx>, - sub_region: Region<'tcx>, - sup_origin: SubregionOrigin<'tcx>, - sup_region: Region<'tcx>) { - + fn report_sub_sup_conflict( + &self, + region_scope_tree: ®ion::ScopeTree, + var_origin: RegionVariableOrigin, + sub_origin: SubregionOrigin<'tcx>, + sub_region: Region<'tcx>, + sup_origin: SubregionOrigin<'tcx>, + sup_region: Region<'tcx>, + ) { let mut err = self.report_inference_failure(var_origin); - self.tcx.note_and_explain_region(region_scope_tree, &mut err, + self.tcx.note_and_explain_region( + region_scope_tree, + &mut err, "first, the lifetime cannot outlive ", sup_region, - "..."); + "...", + ); match (&sup_origin, &sub_origin) { (&infer::Subtype(ref sup_trace), &infer::Subtype(ref sub_trace)) => { - if let (Some((sup_expected, sup_found)), - Some((sub_expected, sub_found))) = (self.values_str(&sup_trace.values), - self.values_str(&sub_trace.values)) { + if let (Some((sup_expected, sup_found)), Some((sub_expected, sub_found))) = ( + self.values_str(&sup_trace.values), + self.values_str(&sub_trace.values), + ) { if sub_expected == sup_expected && sub_found == sup_found { self.tcx.note_and_explain_region( region_scope_tree, @@ -1116,10 +1180,12 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { sub_region, "...", ); - err.note(&format!("...so that the {}:\nexpected {}\n found {}", - sup_trace.cause.as_requirement_str(), - sup_expected.content(), - sup_found.content())); + err.note(&format!( + "...so that the {}:\nexpected {}\n found {}", + sup_trace.cause.as_requirement_str(), + sup_expected.content(), + sup_found.content() + )); err.emit(); return; } @@ -1130,10 +1196,13 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { self.note_region_origin(&mut err, &sup_origin); - self.tcx.note_and_explain_region(region_scope_tree, &mut err, + self.tcx.note_and_explain_region( + region_scope_tree, + &mut err, "but, the lifetime must be valid for ", sub_region, - "..."); + "...", + ); self.note_region_origin(&mut err, &sub_origin); err.emit(); @@ -1141,9 +1210,10 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { } impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { - fn report_inference_failure(&self, - var_origin: RegionVariableOrigin) - -> DiagnosticBuilder<'tcx> { + fn report_inference_failure( + &self, + var_origin: RegionVariableOrigin, + ) -> DiagnosticBuilder<'tcx> { let br_string = |br: ty::BoundRegion| { let mut s = br.to_string(); if !s.is_empty() { @@ -1158,23 +1228,19 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { infer::Autoref(_) => " for autoref".to_string(), infer::Coercion(_) => " for automatic coercion".to_string(), infer::LateBoundRegion(_, br, infer::FnCall) => { - format!(" for lifetime parameter {}in function call", - br_string(br)) + format!(" for lifetime parameter {}in function call", br_string(br)) } infer::LateBoundRegion(_, br, infer::HigherRankedType) => { format!(" for lifetime parameter {}in generic type", br_string(br)) } - infer::LateBoundRegion(_, br, infer::AssocTypeProjection(def_id)) => { - format!(" for lifetime parameter {}in trait containing associated type `{}`", - br_string(br), self.tcx.associated_item(def_id).name) - } - infer::EarlyBoundRegion(_, name) => { - format!(" for lifetime parameter `{}`", - name) - } + infer::LateBoundRegion(_, br, infer::AssocTypeProjection(def_id)) => format!( + " for lifetime parameter {}in trait containing associated type `{}`", + br_string(br), + self.tcx.associated_item(def_id).name + ), + infer::EarlyBoundRegion(_, name) => format!(" for lifetime parameter `{}`", name), infer::BoundRegionInCoherence(name) => { - format!(" for lifetime parameter `{}` in coherence check", - name) + format!(" for lifetime parameter `{}` in coherence check", name) } infer::UpvarRegion(ref upvar_id, _) => { let var_node_id = self.tcx.hir.hir_to_node_id(upvar_id.var_id); @@ -1184,10 +1250,14 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { infer::NLL(..) => bug!("NLL variable found in lexical phase"), }; - struct_span_err!(self.tcx.sess, var_origin.span(), E0495, - "cannot infer an appropriate lifetime{} \ - due to conflicting requirements", - var_description) + struct_span_err!( + self.tcx.sess, + var_origin.span(), + E0495, + "cannot infer an appropriate lifetime{} \ + due to conflicting requirements", + var_description + ) } } @@ -1205,7 +1275,7 @@ impl<'tcx> ObligationCause<'tcx> { match self.code { CompareImplMethodObligation { .. } => Error0308("method not compatible with trait"), MatchExpressionArm { source, .. } => Error0308(match source { - hir::MatchSource::IfLetDesugar{..} => "`if let` arms have incompatible types", + hir::MatchSource::IfLetDesugar { .. } => "`if let` arms have incompatible types", _ => "match arms have incompatible types", }), IfExpression => Error0308("if and else have incompatible types"), @@ -1220,11 +1290,11 @@ impl<'tcx> ObligationCause<'tcx> { // say, also take a look at the error code, maybe we can // tailor to that. _ => match terr { - TypeError::CyclicTy(ty) if ty.is_closure() || ty.is_generator() => - Error0644("closure/generator type that references itself"), - _ => - Error0308("mismatched types"), - } + TypeError::CyclicTy(ty) if ty.is_closure() || ty.is_generator() => { + Error0644("closure/generator type that references itself") + } + _ => Error0308("mismatched types"), + }, } } @@ -1234,7 +1304,7 @@ impl<'tcx> ObligationCause<'tcx> { CompareImplMethodObligation { .. } => "method type is compatible with trait", ExprAssignable => "expression is assignable", MatchExpressionArm { source, .. } => match source { - hir::MatchSource::IfLetDesugar{..} => "`if let` arms have compatible types", + hir::MatchSource::IfLetDesugar { .. } => "`if let` arms have compatible types", _ => "match arms have compatible types", }, IfExpression => "if and else have compatible types", diff --git a/src/librustc_mir/borrow_check/error_reporting.rs b/src/librustc_mir/borrow_check/error_reporting.rs index 667450c3f352..eed2a2284ea1 100644 --- a/src/librustc_mir/borrow_check/error_reporting.rs +++ b/src/librustc_mir/borrow_check/error_reporting.rs @@ -17,7 +17,7 @@ use rustc_data_structures::indexed_vec::Idx; use std::rc::Rc; -use super::{MirBorrowckCtxt, Context}; +use super::{Context, MirBorrowckCtxt}; use super::{InitializationRequiringAction, PrefixSet}; use dataflow::{ActiveBorrows, BorrowData, FlowAtLocation, MovingOutStatements}; use dataflow::move_paths::MovePathIndex; @@ -97,7 +97,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { } else { true } - }, + } _ => true, }; @@ -107,9 +107,11 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { None => "value".to_owned(), }; - err.note(&format!("move occurs because {} has type `{}`, \ - which does not implement the `Copy` trait", - note_msg, ty)); + err.note(&format!( + "move occurs because {} has type `{}`, \ + which does not implement the `Copy` trait", + note_msg, ty + )); } } @@ -155,7 +157,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { span, &self.describe_place(place).unwrap_or("_".to_owned()), self.retrieve_borrow_span(borrow), - &self.describe_place(&borrow.borrowed_place).unwrap_or("_".to_owned()), + &self.describe_place(&borrow.borrowed_place) + .unwrap_or("_".to_owned()), Origin::Mir, ); @@ -176,8 +179,14 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { use rustc::hir::ExprClosure; use rustc::mir::AggregateKind; - let local = match self.mir[location.block].statements.get(location.statement_index) { - Some(&Statement { kind: StatementKind::Assign(Place::Local(local), _), .. }) => local, + let local = match self.mir[location.block] + .statements + .get(location.statement_index) + { + Some(&Statement { + kind: StatementKind::Assign(Place::Local(local), _), + .. + }) => local, _ => return None, }; @@ -203,8 +212,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { .with_freevars(node_id, |freevars| { for (v, place) in freevars.iter().zip(places) { match *place { - Operand::Copy(Place::Local(l)) | - Operand::Move(Place::Local(l)) if local == l => + Operand::Copy(Place::Local(l)) + | Operand::Move(Place::Local(l)) if local == l => { debug!( "find_closure_span: found captured local {:?}", @@ -256,8 +265,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { "immutable", "mutable", ) { - (BorrowKind::Shared, lft, _, BorrowKind::Mut { .. }, _, rgt) | - (BorrowKind::Mut { .. }, _, lft, BorrowKind::Shared, rgt, _) => self.tcx + (BorrowKind::Shared, lft, _, BorrowKind::Mut { .. }, _, rgt) + | (BorrowKind::Mut { .. }, _, lft, BorrowKind::Shared, rgt, _) => self.tcx .cannot_reborrow_already_borrowed( span, &desc_place, @@ -356,11 +365,13 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { context: Context, borrow: &BorrowData<'tcx>, drop_span: Span, - borrows: &ActiveBorrows<'cx, 'gcx, 'tcx> + borrows: &ActiveBorrows<'cx, 'gcx, 'tcx>, ) { let end_span = borrows.opt_region_end_span(&borrow.region); let scope_tree = borrows.0.scope_tree(); - let root_place = self.prefixes(&borrow.borrowed_place, PrefixSet::All).last().unwrap(); + let root_place = self.prefixes(&borrow.borrowed_place, PrefixSet::All) + .last() + .unwrap(); let borrow_span = self.mir.source_info(borrow.location).span; let proper_span = match *root_place { @@ -368,13 +379,18 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { _ => drop_span, }; - if self.access_place_error_reported.contains(&(root_place.clone(), borrow_span)) { - debug!("suppressing access_place error when borrow doesn't live long enough for {:?}", - borrow_span); + if self.access_place_error_reported + .contains(&(root_place.clone(), borrow_span)) + { + debug!( + "suppressing access_place error when borrow doesn't live long enough for {:?}", + borrow_span + ); return; } - self.access_place_error_reported.insert((root_place.clone(), borrow_span)); + self.access_place_error_reported + .insert((root_place.clone(), borrow_span)); match (borrow.region, &self.describe_place(&borrow.borrowed_place)) { (RegionKind::ReScope(_), Some(name)) => { @@ -386,9 +402,9 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { drop_span, borrow_span, proper_span, - end_span + end_span, ); - }, + } (RegionKind::ReScope(_), None) => { self.report_scoped_temporary_value_does_not_live_long_enough( context, @@ -397,14 +413,14 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { drop_span, borrow_span, proper_span, - end_span + end_span, ); - }, - (RegionKind::ReEarlyBound(_), Some(name)) | - (RegionKind::ReFree(_), Some(name)) | - (RegionKind::ReStatic, Some(name)) | - (RegionKind::ReEmpty, Some(name)) | - (RegionKind::ReVar(_), Some(name)) => { + } + (RegionKind::ReEarlyBound(_), Some(name)) + | (RegionKind::ReFree(_), Some(name)) + | (RegionKind::ReStatic, Some(name)) + | (RegionKind::ReEmpty, Some(name)) + | (RegionKind::ReVar(_), Some(name)) => { self.report_unscoped_local_value_does_not_live_long_enough( context, name, @@ -415,12 +431,12 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { proper_span, end_span, ); - }, - (RegionKind::ReEarlyBound(_), None) | - (RegionKind::ReFree(_), None) | - (RegionKind::ReStatic, None) | - (RegionKind::ReEmpty, None) | - (RegionKind::ReVar(_), None) => { + } + (RegionKind::ReEarlyBound(_), None) + | (RegionKind::ReFree(_), None) + | (RegionKind::ReStatic, None) + | (RegionKind::ReEmpty, None) + | (RegionKind::ReVar(_), None) => { self.report_unscoped_temporary_value_does_not_live_long_enough( context, &scope_tree, @@ -430,13 +446,13 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { proper_span, end_span, ); - }, - (RegionKind::ReLateBound(_, _), _) | - (RegionKind::ReSkolemized(_, _), _) | - (RegionKind::ReClosureBound(_), _) | - (RegionKind::ReErased, _) => { + } + (RegionKind::ReLateBound(_, _), _) + | (RegionKind::ReSkolemized(_, _), _) + | (RegionKind::ReClosureBound(_), _) + | (RegionKind::ReErased, _) => { span_bug!(drop_span, "region does not make sense in this context"); - }, + } } } @@ -451,11 +467,16 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { _proper_span: Span, end_span: Option, ) { - let mut err = self.tcx.path_does_not_live_long_enough(borrow_span, - &format!("`{}`", name), - Origin::Mir); + let mut err = self.tcx.path_does_not_live_long_enough( + borrow_span, + &format!("`{}`", name), + Origin::Mir, + ); err.span_label(borrow_span, "borrowed value does not live long enough"); - err.span_label(drop_span, format!("`{}` dropped here while still borrowed", name)); + err.span_label( + drop_span, + format!("`{}` dropped here while still borrowed", name), + ); if let Some(end) = end_span { err.span_label(end, "borrowed value needs to live until here"); } @@ -473,11 +494,14 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { proper_span: Span, end_span: Option, ) { - let mut err = self.tcx.path_does_not_live_long_enough(proper_span, - "borrowed value", - Origin::Mir); + let mut err = + self.tcx + .path_does_not_live_long_enough(proper_span, "borrowed value", Origin::Mir); err.span_label(proper_span, "temporary value does not live long enough"); - err.span_label(drop_span, "temporary value dropped here while still borrowed"); + err.span_label( + drop_span, + "temporary value dropped here while still borrowed", + ); err.note("consider using a `let` binding to increase its lifetime"); if let Some(end) = end_span { err.span_label(end, "temporary value needs to live until here"); @@ -499,19 +523,16 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { ) { debug!( "report_unscoped_local_value_does_not_live_long_enough(\ - {:?}, {:?}, {:?}, {:?}, {:?}, {:?}\ - )", - context, - name, - scope_tree, - borrow, - drop_span, - borrow_span + {:?}, {:?}, {:?}, {:?}, {:?}, {:?}\ + )", + context, name, scope_tree, borrow, drop_span, borrow_span ); - let mut err = self.tcx.path_does_not_live_long_enough(borrow_span, - &format!("`{}`", name), - Origin::Mir); + let mut err = self.tcx.path_does_not_live_long_enough( + borrow_span, + &format!("`{}`", name), + Origin::Mir, + ); err.span_label(borrow_span, "borrowed value does not live long enough"); err.span_label(drop_span, "borrowed value only lives until here"); @@ -537,22 +558,18 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { drop_span: Span, _borrow_span: Span, proper_span: Span, - _end_span: Option + _end_span: Option, ) { debug!( "report_unscoped_temporary_value_does_not_live_long_enough(\ - {:?}, {:?}, {:?}, {:?}, {:?}\ - )", - context, - scope_tree, - borrow, - drop_span, - proper_span + {:?}, {:?}, {:?}, {:?}, {:?}\ + )", + context, scope_tree, borrow, drop_span, proper_span ); - let mut err = self.tcx.path_does_not_live_long_enough(proper_span, - "borrowed value", - Origin::Mir); + let mut err = + self.tcx + .path_does_not_live_long_enough(proper_span, "borrowed value", Origin::Mir); err.span_label(proper_span, "temporary value does not live long enough"); err.span_label(drop_span, "temporary value only lives until here"); @@ -746,9 +763,9 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { ProjectionElem::Field(_, field_type) => { self.describe_field_from_ty(&field_type, field) } - ProjectionElem::Index(..) | - ProjectionElem::ConstantIndex { .. } | - ProjectionElem::Subslice { .. } => { + ProjectionElem::Index(..) + | ProjectionElem::ConstantIndex { .. } + | ProjectionElem::Subslice { .. } => { format!("{}", self.describe_field(&proj.base, field)) } }, @@ -805,13 +822,11 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { Place::Local(local) => { let local = &self.mir.local_decls[*local]; Some(local.ty) - }, + } Place::Static(ref st) => Some(st.ty), - Place::Projection(ref proj) => { - match proj.elem { - ProjectionElem::Field(_, ty) => Some(ty), - _ => None, - } + Place::Projection(ref proj) => match proj.elem { + ProjectionElem::Field(_, ty) => Some(ty), + _ => None, }, } } diff --git a/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs b/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs index c93c1848e25f..40826d3044d3 100644 --- a/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs +++ b/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs @@ -72,7 +72,6 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { Cause::UniversalRegion(region_vid) => { if let Some(region) = regioncx.to_error_region(region_vid) { - self.tcx.note_and_explain_free_region( err, "borrowed value must be valid for ", @@ -82,8 +81,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { } } - _ => { - } + _ => {} } } } diff --git a/src/librustc_mir/borrow_check/nll/region_infer/mod.rs b/src/librustc_mir/borrow_check/nll/region_infer/mod.rs index e0a8877a6ab1..3ffb4370359b 100644 --- a/src/librustc_mir/borrow_check/nll/region_infer/mod.rs +++ b/src/librustc_mir/borrow_check/nll/region_infer/mod.rs @@ -573,10 +573,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { // an error that multiple bounds are required. tcx.sess.span_err( type_test.span, - &format!( - "`{}` does not live long enough", - type_test.generic_kind, - ), + &format!("`{}` does not live long enough", type_test.generic_kind,), ); } } @@ -593,8 +590,8 @@ impl<'tcx> RegionInferenceContext<'tcx> { return self.definitions[r].external_name; } else { let inferred_values = self.inferred_values - .as_ref() - .expect("region values not yet inferred"); + .as_ref() + .expect("region values not yet inferred"); let upper_bound = self.universal_upper_bound(r); if inferred_values.contains(r, upper_bound) { self.to_error_region(upper_bound) @@ -806,9 +803,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { ) -> bool { debug!( "eval_region_test(point={:?}, lower_bound={:?}, test={:?})", - point, - lower_bound, - test + point, lower_bound, test ); match test { @@ -840,9 +835,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { ) -> bool { debug!( "eval_outlives({:?}: {:?} @ {:?})", - sup_region, - sub_region, - point + sup_region, sub_region, point ); // Roughly speaking, do a DFS of all region elements reachable @@ -947,8 +940,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { debug!( "check_universal_region: fr={:?} does not outlive shorter_fr={:?}", - longer_fr, - shorter_fr, + longer_fr, shorter_fr, ); let blame_span = self.blame_span(longer_fr, shorter_fr); @@ -1123,10 +1115,7 @@ impl fmt::Debug for Constraint { write!( formatter, "({:?}: {:?} @ {:?}) due to {:?}", - self.sup, - self.sub, - self.point, - self.span + self.sup, self.sub, self.point, self.span ) } } @@ -1176,9 +1165,7 @@ impl<'gcx, 'tcx> ClosureRegionRequirementsExt<'gcx, 'tcx> for ClosureRegionRequi debug!( "apply_requirements(location={:?}, closure_def_id={:?}, closure_substs={:?})", - location, - closure_def_id, - closure_substs + location, closure_def_id, closure_substs ); // Get Tu. @@ -1206,9 +1193,7 @@ impl<'gcx, 'tcx> ClosureRegionRequirementsExt<'gcx, 'tcx> for ClosureRegionRequi "apply_requirements: region={:?} \ outlived_region={:?} \ outlives_requirement={:?}", - region, - outlived_region, - outlives_requirement, + region, outlived_region, outlives_requirement, ); infcx.sub_regions(origin, outlived_region, region); } @@ -1219,9 +1204,7 @@ impl<'gcx, 'tcx> ClosureRegionRequirementsExt<'gcx, 'tcx> for ClosureRegionRequi "apply_requirements: ty={:?} \ outlived_region={:?} \ outlives_requirement={:?}", - ty, - outlived_region, - outlives_requirement, + ty, outlived_region, outlives_requirement, ); infcx.register_region_obligation( body_id, @@ -1276,19 +1259,12 @@ impl CauseExt for Rc { impl Cause { pub(crate) fn root_cause(&self) -> &Cause { match self { - Cause::LiveVar(..) | - Cause::DropVar(..) | - Cause::LiveOther(..) | - Cause::UniversalRegion(..) => { - self - } + Cause::LiveVar(..) + | Cause::DropVar(..) + | Cause::LiveOther(..) + | Cause::UniversalRegion(..) => self, - Cause::Outlives { - original_cause, - .. - } => { - original_cause.root_cause() - } + Cause::Outlives { original_cause, .. } => original_cause.root_cause(), } } } From 08504fbb0b05abdd9543f08102b0d6275dde210c Mon Sep 17 00:00:00 2001 From: Shotaro Yamada Date: Fri, 2 Mar 2018 13:50:59 +0900 Subject: [PATCH 25/68] Optimize str::repeat --- src/liballoc/lib.rs | 1 + src/liballoc/str.rs | 37 ++++++++++++++++++++++++++++++++++--- 2 files changed, 35 insertions(+), 3 deletions(-) diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs index d250cfe1880f..cb43d5bee78c 100644 --- a/src/liballoc/lib.rs +++ b/src/liballoc/lib.rs @@ -124,6 +124,7 @@ #![feature(allocator_internals)] #![feature(on_unimplemented)] #![feature(exact_chunks)] +#![feature(pointer_methods)] #![cfg_attr(not(test), feature(fused, fn_traits, placement_new_protocol, swap_with_slice, i128))] #![cfg_attr(test, feature(test, box_heap))] diff --git a/src/liballoc/str.rs b/src/liballoc/str.rs index a00e3d17dd00..08ba4a180ed5 100644 --- a/src/liballoc/str.rs +++ b/src/liballoc/str.rs @@ -43,6 +43,7 @@ use core::str as core_str; use core::str::pattern::Pattern; use core::str::pattern::{Searcher, ReverseSearcher, DoubleEndedSearcher}; use core::mem; +use core::ptr; use core::iter::FusedIterator; use std_unicode::str::{UnicodeStr, Utf16Encoder}; @@ -2066,9 +2067,39 @@ impl str { /// ``` #[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 + if n == 0 { + return String::new(); + } + + // n = 2^j + k (2^j > k) + + // 2^j: + let mut s = Vec::with_capacity(self.len() * n); + s.extend(self.as_bytes()); + let mut m = n >> 1; + while m > 0 { + let len = s.len(); + unsafe { + ptr::copy_nonoverlapping(s.as_ptr(), (s.as_mut_ptr() as *mut u8).add(len), len); + s.set_len(len * 2); + } + m >>= 1; + } + + // k: + let res_len = n * self.len(); + if res_len > s.len() { + unsafe { + ptr::copy_nonoverlapping( + s.as_ptr(), + (s.as_mut_ptr() as *mut u8).add(s.len()), + res_len - s.len(), + ); + s.set_len(res_len); + } + } + + unsafe { String::from_utf8_unchecked(s) } } /// Checks if all characters in this string are within the ASCII range. From 15ecf0694811cf9ab3273c14a97f6f05b22a9b5b Mon Sep 17 00:00:00 2001 From: flip1995 Date: Fri, 2 Mar 2018 13:33:06 +0100 Subject: [PATCH 26/68] Remove isize test --- src/test/ui/lint/type-overflow.rs | 2 -- src/test/ui/lint/type-overflow.stderr | 10 +--------- 2 files changed, 1 insertion(+), 11 deletions(-) diff --git a/src/test/ui/lint/type-overflow.rs b/src/test/ui/lint/type-overflow.rs index e414f43b3ffd..495989587e58 100644 --- a/src/test/ui/lint/type-overflow.rs +++ b/src/test/ui/lint/type-overflow.rs @@ -29,7 +29,5 @@ fn main() { let fail = 0x8FFF_FFFF_FFFF_FFFE; //~WARNING literal out of range for i32 - let fail: isize = 0x8000_0000_0000_0000; //~WARNING literal out of range for isize - let fail = -0b1111_1111i8; //~WARNING literal out of range for i8 } diff --git a/src/test/ui/lint/type-overflow.stderr b/src/test/ui/lint/type-overflow.stderr index 4ede25b9d03e..d3fcb1335e20 100644 --- a/src/test/ui/lint/type-overflow.stderr +++ b/src/test/ui/lint/type-overflow.stderr @@ -48,16 +48,8 @@ LL | let fail = 0x8FFF_FFFF_FFFF_FFFE; //~WARNING literal out of range for i = note: the literal `0x8FFF_FFFF_FFFF_FFFE` (decimal `10376293541461622782`) does not fit into an `i32` and will become `-2i32` = help: consider using `i128` instead -warning: literal out of range for isize - --> $DIR/type-overflow.rs:32:23 - | -LL | let fail: isize = 0x8000_0000_0000_0000; //~WARNING literal out of range for isize - | ^^^^^^^^^^^^^^^^^^^^^ - | - = note: the literal `0x8000_0000_0000_0000` (decimal `9223372036854775808`) does not fit into an `isize` and will become `-9223372036854775808isize` - warning: literal out of range for i8 - --> $DIR/type-overflow.rs:34:17 + --> $DIR/type-overflow.rs:32:17 | LL | let fail = -0b1111_1111i8; //~WARNING literal out of range for i8 | ^^^^^^^^^^^^^ help: consider using `i16` instead: `0b1111_1111i16` From bc651cac8d671aee9be876b71d0fa86f94f56b0f Mon Sep 17 00:00:00 2001 From: Ulrik Sverdrup Date: Mon, 15 Jan 2018 19:59:10 +0100 Subject: [PATCH 27/68] core: Stabilize FusedIterator FusedIterator is a marker trait that promises that the implementing iterator continues to return `None` from `.next()` once it has returned `None` once (and/or `.next_back()`, if implemented). The effects of FusedIterator are already widely available through `.fuse()`, but with stable `FusedIterator`, stable Rust users can implement this trait for their iterators when appropriate. --- src/liballoc/binary_heap.rs | 6 ++--- src/liballoc/boxed.rs | 2 +- src/liballoc/btree/map.rs | 16 ++++++------ src/liballoc/btree/set.rs | 14 +++++----- src/liballoc/lib.rs | 3 +-- src/liballoc/linked_list.rs | 6 ++--- src/liballoc/str.rs | 2 +- src/liballoc/string.rs | 2 +- src/liballoc/vec.rs | 4 +-- src/liballoc/vec_deque.rs | 8 +++--- src/libcore/char.rs | 8 +++--- src/libcore/iter/mod.rs | 42 +++++++++++++++--------------- src/libcore/iter/range.rs | 6 ++--- src/libcore/iter/sources.rs | 6 ++--- src/libcore/iter/traits.rs | 4 +-- src/libcore/option.rs | 6 ++--- src/libcore/result.rs | 6 ++--- src/libcore/slice/mod.rs | 24 ++++++++--------- src/libcore/str/mod.rs | 14 +++++----- src/libstd/ascii.rs | 2 +- src/libstd/collections/hash/map.rs | 14 +++++----- src/libstd/collections/hash/set.rs | 14 +++++----- src/libstd/lib.rs | 1 - src/libstd/path.rs | 4 +-- src/libstd_unicode/char.rs | 4 +-- src/libstd_unicode/lib.rs | 1 - src/libstd_unicode/u_str.rs | 4 +-- src/test/run-pass/issue-36053.rs | 1 - 28 files changed, 110 insertions(+), 114 deletions(-) diff --git a/src/liballoc/binary_heap.rs b/src/liballoc/binary_heap.rs index 3041f85cd4c3..a5694a90dbc9 100644 --- a/src/liballoc/binary_heap.rs +++ b/src/liballoc/binary_heap.rs @@ -964,7 +964,7 @@ impl<'a, T> ExactSizeIterator for Iter<'a, T> { } } -#[unstable(feature = "fused", issue = "35602")] +#[stable(feature = "fused", since = "1.25.0")] impl<'a, T> FusedIterator for Iter<'a, T> {} /// An owning iterator over the elements of a `BinaryHeap`. @@ -1019,7 +1019,7 @@ impl ExactSizeIterator for IntoIter { } } -#[unstable(feature = "fused", issue = "35602")] +#[stable(feature = "fused", since = "1.25.0")] impl FusedIterator for IntoIter {} /// A draining iterator over the elements of a `BinaryHeap`. @@ -1065,7 +1065,7 @@ impl<'a, T: 'a> ExactSizeIterator for Drain<'a, T> { } } -#[unstable(feature = "fused", issue = "35602")] +#[stable(feature = "fused", since = "1.25.0")] impl<'a, T: 'a> FusedIterator for Drain<'a, T> {} #[stable(feature = "binary_heap_extras_15", since = "1.5.0")] diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index 75a59de337ce..6b000b6fa91b 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -722,7 +722,7 @@ impl ExactSizeIterator for Box { } } -#[unstable(feature = "fused", issue = "35602")] +#[stable(feature = "fused", since = "1.25.0")] impl FusedIterator for Box {} diff --git a/src/liballoc/btree/map.rs b/src/liballoc/btree/map.rs index 618ef81fdd98..7b7a6374db9b 100644 --- a/src/liballoc/btree/map.rs +++ b/src/liballoc/btree/map.rs @@ -1156,7 +1156,7 @@ impl<'a, K: 'a, V: 'a> Iterator for Iter<'a, K, V> { } } -#[unstable(feature = "fused", issue = "35602")] +#[stable(feature = "fused", since = "1.25.0")] impl<'a, K, V> FusedIterator for Iter<'a, K, V> {} #[stable(feature = "rust1", since = "1.0.0")] @@ -1235,7 +1235,7 @@ impl<'a, K: 'a, V: 'a> ExactSizeIterator for IterMut<'a, K, V> { } } -#[unstable(feature = "fused", issue = "35602")] +#[stable(feature = "fused", since = "1.25.0")] impl<'a, K, V> FusedIterator for IterMut<'a, K, V> {} #[stable(feature = "rust1", since = "1.0.0")] @@ -1365,7 +1365,7 @@ impl ExactSizeIterator for IntoIter { } } -#[unstable(feature = "fused", issue = "35602")] +#[stable(feature = "fused", since = "1.25.0")] impl FusedIterator for IntoIter {} #[stable(feature = "rust1", since = "1.0.0")] @@ -1395,7 +1395,7 @@ impl<'a, K, V> ExactSizeIterator for Keys<'a, K, V> { } } -#[unstable(feature = "fused", issue = "35602")] +#[stable(feature = "fused", since = "1.25.0")] impl<'a, K, V> FusedIterator for Keys<'a, K, V> {} #[stable(feature = "rust1", since = "1.0.0")] @@ -1432,7 +1432,7 @@ impl<'a, K, V> ExactSizeIterator for Values<'a, K, V> { } } -#[unstable(feature = "fused", issue = "35602")] +#[stable(feature = "fused", since = "1.25.0")] impl<'a, K, V> FusedIterator for Values<'a, K, V> {} #[stable(feature = "rust1", since = "1.0.0")] @@ -1482,7 +1482,7 @@ impl<'a, K, V> ExactSizeIterator for ValuesMut<'a, K, V> { } } -#[unstable(feature = "fused", issue = "35602")] +#[stable(feature = "fused", since = "1.25.0")] impl<'a, K, V> FusedIterator for ValuesMut<'a, K, V> {} @@ -1561,7 +1561,7 @@ impl<'a, K, V> Range<'a, K, V> { } } -#[unstable(feature = "fused", issue = "35602")] +#[stable(feature = "fused", since = "1.25.0")] impl<'a, K, V> FusedIterator for Range<'a, K, V> {} #[stable(feature = "btree_range", since = "1.17.0")] @@ -1630,7 +1630,7 @@ impl<'a, K, V> DoubleEndedIterator for RangeMut<'a, K, V> { } } -#[unstable(feature = "fused", issue = "35602")] +#[stable(feature = "fused", since = "1.25.0")] impl<'a, K, V> FusedIterator for RangeMut<'a, K, V> {} impl<'a, K, V> RangeMut<'a, K, V> { diff --git a/src/liballoc/btree/set.rs b/src/liballoc/btree/set.rs index 327eaaf46513..34cb7a08ed70 100644 --- a/src/liballoc/btree/set.rs +++ b/src/liballoc/btree/set.rs @@ -946,7 +946,7 @@ impl<'a, T> ExactSizeIterator for Iter<'a, T> { fn len(&self) -> usize { self.iter.len() } } -#[unstable(feature = "fused", issue = "35602")] +#[stable(feature = "fused", since = "1.25.0")] impl<'a, T> FusedIterator for Iter<'a, T> {} #[stable(feature = "rust1", since = "1.0.0")] @@ -971,7 +971,7 @@ impl ExactSizeIterator for IntoIter { fn len(&self) -> usize { self.iter.len() } } -#[unstable(feature = "fused", issue = "35602")] +#[stable(feature = "fused", since = "1.25.0")] impl FusedIterator for IntoIter {} #[stable(feature = "btree_range", since = "1.17.0")] @@ -997,7 +997,7 @@ impl<'a, T> DoubleEndedIterator for Range<'a, T> { } } -#[unstable(feature = "fused", issue = "35602")] +#[stable(feature = "fused", since = "1.25.0")] impl<'a, T> FusedIterator for Range<'a, T> {} /// Compare `x` and `y`, but return `short` if x is None and `long` if y is None @@ -1044,7 +1044,7 @@ impl<'a, T: Ord> Iterator for Difference<'a, T> { } } -#[unstable(feature = "fused", issue = "35602")] +#[stable(feature = "fused", since = "1.25.0")] impl<'a, T: Ord> FusedIterator for Difference<'a, T> {} #[stable(feature = "rust1", since = "1.0.0")] @@ -1078,7 +1078,7 @@ impl<'a, T: Ord> Iterator for SymmetricDifference<'a, T> { } } -#[unstable(feature = "fused", issue = "35602")] +#[stable(feature = "fused", since = "1.25.0")] impl<'a, T: Ord> FusedIterator for SymmetricDifference<'a, T> {} #[stable(feature = "rust1", since = "1.0.0")] @@ -1116,7 +1116,7 @@ impl<'a, T: Ord> Iterator for Intersection<'a, T> { } } -#[unstable(feature = "fused", issue = "35602")] +#[stable(feature = "fused", since = "1.25.0")] impl<'a, T: Ord> FusedIterator for Intersection<'a, T> {} #[stable(feature = "rust1", since = "1.0.0")] @@ -1150,5 +1150,5 @@ impl<'a, T: Ord> Iterator for Union<'a, T> { } } -#[unstable(feature = "fused", issue = "35602")] +#[stable(feature = "fused", since = "1.25.0")] impl<'a, T: Ord> FusedIterator for Union<'a, T> {} diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs index d250cfe1880f..2212b62dfd8f 100644 --- a/src/liballoc/lib.rs +++ b/src/liballoc/lib.rs @@ -96,7 +96,6 @@ #![feature(fmt_internals)] #![feature(from_ref)] #![feature(fundamental)] -#![feature(fused)] #![feature(generic_param_attrs)] #![feature(i128_type)] #![feature(inclusive_range)] @@ -125,7 +124,7 @@ #![feature(on_unimplemented)] #![feature(exact_chunks)] -#![cfg_attr(not(test), feature(fused, fn_traits, placement_new_protocol, swap_with_slice, i128))] +#![cfg_attr(not(test), feature(fn_traits, placement_new_protocol, swap_with_slice, i128))] #![cfg_attr(test, feature(test, box_heap))] // Allow testing this library diff --git a/src/liballoc/linked_list.rs b/src/liballoc/linked_list.rs index ec579e3fd68d..87939fddfc81 100644 --- a/src/liballoc/linked_list.rs +++ b/src/liballoc/linked_list.rs @@ -897,7 +897,7 @@ impl<'a, T> DoubleEndedIterator for Iter<'a, T> { #[stable(feature = "rust1", since = "1.0.0")] impl<'a, T> ExactSizeIterator for Iter<'a, T> {} -#[unstable(feature = "fused", issue = "35602")] +#[stable(feature = "fused", since = "1.25.0")] impl<'a, T> FusedIterator for Iter<'a, T> {} #[stable(feature = "rust1", since = "1.0.0")] @@ -946,7 +946,7 @@ impl<'a, T> DoubleEndedIterator for IterMut<'a, T> { #[stable(feature = "rust1", since = "1.0.0")] impl<'a, T> ExactSizeIterator for IterMut<'a, T> {} -#[unstable(feature = "fused", issue = "35602")] +#[stable(feature = "fused", since = "1.25.0")] impl<'a, T> FusedIterator for IterMut<'a, T> {} impl<'a, T> IterMut<'a, T> { @@ -1117,7 +1117,7 @@ impl DoubleEndedIterator for IntoIter { #[stable(feature = "rust1", since = "1.0.0")] impl ExactSizeIterator for IntoIter {} -#[unstable(feature = "fused", issue = "35602")] +#[stable(feature = "fused", since = "1.25.0")] impl FusedIterator for IntoIter {} #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/liballoc/str.rs b/src/liballoc/str.rs index a00e3d17dd00..1a431bb26942 100644 --- a/src/liballoc/str.rs +++ b/src/liballoc/str.rs @@ -171,7 +171,7 @@ impl<'a> Iterator for EncodeUtf16<'a> { } } -#[unstable(feature = "fused", issue = "35602")] +#[stable(feature = "fused", since = "1.25.0")] impl<'a> FusedIterator for EncodeUtf16<'a> {} #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/liballoc/string.rs b/src/liballoc/string.rs index 409d2ab287e7..1fcabd8a4278 100644 --- a/src/liballoc/string.rs +++ b/src/liballoc/string.rs @@ -2254,5 +2254,5 @@ impl<'a> DoubleEndedIterator for Drain<'a> { } } -#[unstable(feature = "fused", issue = "35602")] +#[stable(feature = "fused", since = "1.25.0")] impl<'a> FusedIterator for Drain<'a> {} diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs index 3c9b6b94b440..03c9750fb392 100644 --- a/src/liballoc/vec.rs +++ b/src/liballoc/vec.rs @@ -2389,7 +2389,7 @@ impl ExactSizeIterator for IntoIter { } } -#[unstable(feature = "fused", issue = "35602")] +#[stable(feature = "fused", since = "1.25.0")] impl FusedIterator for IntoIter {} #[unstable(feature = "trusted_len", issue = "37572")] @@ -2495,7 +2495,7 @@ impl<'a, T> ExactSizeIterator for Drain<'a, T> { } } -#[unstable(feature = "fused", issue = "35602")] +#[stable(feature = "fused", since = "1.25.0")] impl<'a, T> FusedIterator for Drain<'a, T> {} /// A place for insertion at the back of a `Vec`. diff --git a/src/liballoc/vec_deque.rs b/src/liballoc/vec_deque.rs index 8b686365e692..3d7549abe6ff 100644 --- a/src/liballoc/vec_deque.rs +++ b/src/liballoc/vec_deque.rs @@ -1991,7 +1991,7 @@ impl<'a, T> ExactSizeIterator for Iter<'a, T> { } } -#[unstable(feature = "fused", issue = "35602")] +#[stable(feature = "fused", since = "1.25.0")] impl<'a, T> FusedIterator for Iter<'a, T> {} @@ -2084,7 +2084,7 @@ impl<'a, T> ExactSizeIterator for IterMut<'a, T> { } } -#[unstable(feature = "fused", issue = "35602")] +#[stable(feature = "fused", since = "1.25.0")] impl<'a, T> FusedIterator for IterMut<'a, T> {} /// An owning iterator over the elements of a `VecDeque`. @@ -2140,7 +2140,7 @@ impl ExactSizeIterator for IntoIter { } } -#[unstable(feature = "fused", issue = "35602")] +#[stable(feature = "fused", since = "1.25.0")] impl FusedIterator for IntoIter {} /// A draining iterator over the elements of a `VecDeque`. @@ -2247,7 +2247,7 @@ impl<'a, T: 'a> DoubleEndedIterator for Drain<'a, T> { #[stable(feature = "drain", since = "1.6.0")] impl<'a, T: 'a> ExactSizeIterator for Drain<'a, T> {} -#[unstable(feature = "fused", issue = "35602")] +#[stable(feature = "fused", since = "1.25.0")] impl<'a, T: 'a> FusedIterator for Drain<'a, T> {} #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libcore/char.rs b/src/libcore/char.rs index 7215bd2a4768..3ff31a7a9281 100644 --- a/src/libcore/char.rs +++ b/src/libcore/char.rs @@ -643,7 +643,7 @@ impl ExactSizeIterator for EscapeUnicode { } } -#[unstable(feature = "fused", issue = "35602")] +#[stable(feature = "fused", since = "1.25.0")] impl FusedIterator for EscapeUnicode {} #[stable(feature = "char_struct_display", since = "1.16.0")] @@ -756,7 +756,7 @@ impl ExactSizeIterator for EscapeDefault { } } -#[unstable(feature = "fused", issue = "35602")] +#[stable(feature = "fused", since = "1.25.0")] impl FusedIterator for EscapeDefault {} #[stable(feature = "char_struct_display", since = "1.16.0")] @@ -790,7 +790,7 @@ impl Iterator for EscapeDebug { #[stable(feature = "char_escape_debug", since = "1.20.0")] impl ExactSizeIterator for EscapeDebug { } -#[unstable(feature = "fused", issue = "35602")] +#[stable(feature = "fused", since = "1.25.0")] impl FusedIterator for EscapeDebug {} #[stable(feature = "char_escape_debug", since = "1.20.0")] @@ -904,5 +904,5 @@ impl> Iterator for DecodeUtf8 { } } -#[unstable(feature = "fused", issue = "35602")] +#[stable(feature = "fused", since = "1.25.0")] impl> FusedIterator for DecodeUtf8 {} diff --git a/src/libcore/iter/mod.rs b/src/libcore/iter/mod.rs index 257d7d6caaaf..9a8f7fc4e6ab 100644 --- a/src/libcore/iter/mod.rs +++ b/src/libcore/iter/mod.rs @@ -344,7 +344,7 @@ pub use self::sources::{Once, once}; pub use self::traits::{FromIterator, IntoIterator, DoubleEndedIterator, Extend}; #[stable(feature = "rust1", since = "1.0.0")] pub use self::traits::{ExactSizeIterator, Sum, Product}; -#[unstable(feature = "fused", issue = "35602")] +#[stable(feature = "fused", since = "1.25.0")] pub use self::traits::FusedIterator; #[unstable(feature = "trusted_len", issue = "37572")] pub use self::traits::TrustedLen; @@ -506,7 +506,7 @@ impl ExactSizeIterator for Rev } } -#[unstable(feature = "fused", issue = "35602")] +#[stable(feature = "fused", since = "1.25.0")] impl FusedIterator for Rev where I: FusedIterator + DoubleEndedIterator {} @@ -589,7 +589,7 @@ impl<'a, I, T: 'a> ExactSizeIterator for Cloned } } -#[unstable(feature = "fused", issue = "35602")] +#[stable(feature = "fused", since = "1.25.0")] impl<'a, I, T: 'a> FusedIterator for Cloned where I: FusedIterator, T: Clone {} @@ -662,7 +662,7 @@ impl Iterator for Cycle where I: Clone + Iterator { } } -#[unstable(feature = "fused", issue = "35602")] +#[stable(feature = "fused", since = "1.25.0")] impl FusedIterator for Cycle where I: Clone + Iterator {} /// An iterator for stepping iterators by a custom amount. @@ -1002,7 +1002,7 @@ impl DoubleEndedIterator for Chain where } // Note: *both* must be fused to handle double-ended iterators. -#[unstable(feature = "fused", issue = "35602")] +#[stable(feature = "fused", since = "1.25.0")] impl FusedIterator for Chain where A: FusedIterator, B: FusedIterator, @@ -1262,7 +1262,7 @@ unsafe impl TrustedRandomAccess for Zip } } -#[unstable(feature = "fused", issue = "35602")] +#[stable(feature = "fused", since = "1.25.0")] impl FusedIterator for Zip where A: FusedIterator, B: FusedIterator, {} @@ -1404,7 +1404,7 @@ impl ExactSizeIterator for Map } } -#[unstable(feature = "fused", issue = "35602")] +#[stable(feature = "fused", since = "1.25.0")] impl FusedIterator for Map where F: FnMut(I::Item) -> B {} @@ -1553,7 +1553,7 @@ impl DoubleEndedIterator for Filter } } -#[unstable(feature = "fused", issue = "35602")] +#[stable(feature = "fused", since = "1.25.0")] impl FusedIterator for Filter where P: FnMut(&I::Item) -> bool {} @@ -1663,7 +1663,7 @@ impl DoubleEndedIterator for FilterMap } } -#[unstable(feature = "fused", issue = "35602")] +#[stable(feature = "fused", since = "1.25.0")] impl FusedIterator for FilterMap where F: FnMut(I::Item) -> Option {} @@ -1818,7 +1818,7 @@ unsafe impl TrustedRandomAccess for Enumerate } } -#[unstable(feature = "fused", issue = "35602")] +#[stable(feature = "fused", since = "1.25.0")] impl FusedIterator for Enumerate where I: FusedIterator {} #[unstable(feature = "trusted_len", issue = "37572")] @@ -1938,7 +1938,7 @@ impl Iterator for Peekable { #[stable(feature = "rust1", since = "1.0.0")] impl ExactSizeIterator for Peekable {} -#[unstable(feature = "fused", issue = "35602")] +#[stable(feature = "fused", since = "1.25.0")] impl FusedIterator for Peekable {} impl Peekable { @@ -2072,7 +2072,7 @@ impl Iterator for SkipWhile } } -#[unstable(feature = "fused", issue = "35602")] +#[stable(feature = "fused", since = "1.25.0")] impl FusedIterator for SkipWhile where I: FusedIterator, P: FnMut(&I::Item) -> bool {} @@ -2151,7 +2151,7 @@ impl Iterator for TakeWhile } } -#[unstable(feature = "fused", issue = "35602")] +#[stable(feature = "fused", since = "1.25.0")] impl FusedIterator for TakeWhile where I: FusedIterator, P: FnMut(&I::Item) -> bool {} @@ -2290,7 +2290,7 @@ impl DoubleEndedIterator for Skip where I: DoubleEndedIterator + ExactSize } } -#[unstable(feature = "fused", issue = "35602")] +#[stable(feature = "fused", since = "1.25.0")] impl FusedIterator for Skip where I: FusedIterator {} /// An iterator that only iterates over the first `n` iterations of `iter`. @@ -2371,7 +2371,7 @@ impl Iterator for Take where I: Iterator{ #[stable(feature = "rust1", since = "1.0.0")] impl ExactSizeIterator for Take where I: ExactSizeIterator {} -#[unstable(feature = "fused", issue = "35602")] +#[stable(feature = "fused", since = "1.25.0")] impl FusedIterator for Take where I: FusedIterator {} #[unstable(feature = "trusted_len", issue = "37572")] @@ -2517,7 +2517,7 @@ impl DoubleEndedIterator for FlatMap } } -#[unstable(feature = "fused", issue = "35602")] +#[stable(feature = "fused", since = "1.25.0")] impl FusedIterator for FlatMap where I: FusedIterator, U: IntoIterator, F: FnMut(I::Item) -> U {} @@ -2605,7 +2605,7 @@ impl DoubleEndedIterator for Flatten } } -#[unstable(feature = "fused", issue = "35602")] +#[stable(feature = "fused", since = "1.25.0")] impl FusedIterator for Flatten where I: FusedIterator, U: Iterator, I::Item: IntoIterator {} @@ -2765,7 +2765,7 @@ pub struct Fuse { done: bool } -#[unstable(feature = "fused", issue = "35602")] +#[stable(feature = "fused", since = "1.25.0")] impl FusedIterator for Fuse where I: Iterator {} #[stable(feature = "rust1", since = "1.0.0")] @@ -2896,7 +2896,7 @@ unsafe impl TrustedRandomAccess for Fuse } } -#[unstable(feature = "fused", issue = "35602")] +#[stable(feature = "fused", since = "1.25.0")] impl Iterator for Fuse where I: FusedIterator { #[inline] fn next(&mut self) -> Option<::Item> { @@ -2938,7 +2938,7 @@ impl Iterator for Fuse where I: FusedIterator { } } -#[unstable(feature = "fused", reason = "recently added", issue = "35602")] +#[stable(feature = "fused", since = "1.25.0")] impl DoubleEndedIterator for Fuse where I: DoubleEndedIterator + FusedIterator { @@ -3082,6 +3082,6 @@ impl ExactSizeIterator for Inspect } } -#[unstable(feature = "fused", issue = "35602")] +#[stable(feature = "fused", since = "1.25.0")] impl FusedIterator for Inspect where F: FnMut(&I::Item) {} diff --git a/src/libcore/iter/range.rs b/src/libcore/iter/range.rs index 65b38c94dda3..7f3b227e8b73 100644 --- a/src/libcore/iter/range.rs +++ b/src/libcore/iter/range.rs @@ -295,7 +295,7 @@ impl DoubleEndedIterator for ops::Range { } } -#[unstable(feature = "fused", issue = "35602")] +#[stable(feature = "fused", since = "1.25.0")] impl FusedIterator for ops::Range {} #[stable(feature = "rust1", since = "1.0.0")] @@ -322,7 +322,7 @@ impl Iterator for ops::RangeFrom { } } -#[unstable(feature = "fused", issue = "35602")] +#[stable(feature = "fused", since = "1.25.0")] impl FusedIterator for ops::RangeFrom {} #[unstable(feature = "trusted_len", issue = "37572")] @@ -463,5 +463,5 @@ impl DoubleEndedIterator for ops::RangeInclusive { } } -#[unstable(feature = "fused", issue = "35602")] +#[stable(feature = "fused", since = "1.25.0")] impl FusedIterator for ops::RangeInclusive {} diff --git a/src/libcore/iter/sources.rs b/src/libcore/iter/sources.rs index dfd42f3e7330..149dff83bc0e 100644 --- a/src/libcore/iter/sources.rs +++ b/src/libcore/iter/sources.rs @@ -41,7 +41,7 @@ impl DoubleEndedIterator for Repeat { fn next_back(&mut self) -> Option { Some(self.element.clone()) } } -#[unstable(feature = "fused", issue = "35602")] +#[stable(feature = "fused", since = "1.25.0")] impl FusedIterator for Repeat {} #[unstable(feature = "trusted_len", issue = "37572")] @@ -259,7 +259,7 @@ impl ExactSizeIterator for Empty { #[unstable(feature = "trusted_len", issue = "37572")] unsafe impl TrustedLen for Empty {} -#[unstable(feature = "fused", issue = "35602")] +#[stable(feature = "fused", since = "1.25.0")] impl FusedIterator for Empty {} // not #[derive] because that adds a Clone bound on T, @@ -340,7 +340,7 @@ impl ExactSizeIterator for Once { #[unstable(feature = "trusted_len", issue = "37572")] unsafe impl TrustedLen for Once {} -#[unstable(feature = "fused", issue = "35602")] +#[stable(feature = "fused", since = "1.25.0")] impl FusedIterator for Once {} /// Creates an iterator that yields an element exactly once. diff --git a/src/libcore/iter/traits.rs b/src/libcore/iter/traits.rs index 860742d9eab6..a86f4e74706e 100644 --- a/src/libcore/iter/traits.rs +++ b/src/libcore/iter/traits.rs @@ -959,10 +959,10 @@ impl Product> for Result /// [`None`]: ../../std/option/enum.Option.html#variant.None /// [`Iterator::fuse`]: ../../std/iter/trait.Iterator.html#method.fuse /// [`Fuse`]: ../../std/iter/struct.Fuse.html -#[unstable(feature = "fused", issue = "35602")] +#[stable(feature = "fused", since = "1.25.0")] pub trait FusedIterator: Iterator {} -#[unstable(feature = "fused", issue = "35602")] +#[stable(feature = "fused", since = "1.25.0")] impl<'a, I: FusedIterator + ?Sized> FusedIterator for &'a mut I {} /// An iterator that reports an accurate length using size_hint. diff --git a/src/libcore/option.rs b/src/libcore/option.rs index b8fe28d0f0d7..99c1d7d9b361 100644 --- a/src/libcore/option.rs +++ b/src/libcore/option.rs @@ -1051,7 +1051,7 @@ impl<'a, A> DoubleEndedIterator for Iter<'a, A> { #[stable(feature = "rust1", since = "1.0.0")] impl<'a, A> ExactSizeIterator for Iter<'a, A> {} -#[unstable(feature = "fused", issue = "35602")] +#[stable(feature = "fused", since = "1.25.0")] impl<'a, A> FusedIterator for Iter<'a, A> {} #[unstable(feature = "trusted_len", issue = "37572")] @@ -1096,7 +1096,7 @@ impl<'a, A> DoubleEndedIterator for IterMut<'a, A> { #[stable(feature = "rust1", since = "1.0.0")] impl<'a, A> ExactSizeIterator for IterMut<'a, A> {} -#[unstable(feature = "fused", issue = "35602")] +#[stable(feature = "fused", since = "1.25.0")] impl<'a, A> FusedIterator for IterMut<'a, A> {} #[unstable(feature = "trusted_len", issue = "37572")] unsafe impl<'a, A> TrustedLen for IterMut<'a, A> {} @@ -1133,7 +1133,7 @@ impl DoubleEndedIterator for IntoIter { #[stable(feature = "rust1", since = "1.0.0")] impl ExactSizeIterator for IntoIter {} -#[unstable(feature = "fused", issue = "35602")] +#[stable(feature = "fused", since = "1.25.0")] impl FusedIterator for IntoIter {} #[unstable(feature = "trusted_len", issue = "37572")] diff --git a/src/libcore/result.rs b/src/libcore/result.rs index 3801db94e15d..5131fc837ef2 100644 --- a/src/libcore/result.rs +++ b/src/libcore/result.rs @@ -1038,7 +1038,7 @@ impl<'a, T> DoubleEndedIterator for Iter<'a, T> { #[stable(feature = "rust1", since = "1.0.0")] impl<'a, T> ExactSizeIterator for Iter<'a, T> {} -#[unstable(feature = "fused", issue = "35602")] +#[stable(feature = "fused", since = "1.25.0")] impl<'a, T> FusedIterator for Iter<'a, T> {} #[unstable(feature = "trusted_len", issue = "37572")] @@ -1082,7 +1082,7 @@ impl<'a, T> DoubleEndedIterator for IterMut<'a, T> { #[stable(feature = "rust1", since = "1.0.0")] impl<'a, T> ExactSizeIterator for IterMut<'a, T> {} -#[unstable(feature = "fused", issue = "35602")] +#[stable(feature = "fused", since = "1.25.0")] impl<'a, T> FusedIterator for IterMut<'a, T> {} #[unstable(feature = "trusted_len", issue = "37572")] @@ -1125,7 +1125,7 @@ impl DoubleEndedIterator for IntoIter { #[stable(feature = "rust1", since = "1.0.0")] impl ExactSizeIterator for IntoIter {} -#[unstable(feature = "fused", issue = "35602")] +#[stable(feature = "fused", since = "1.25.0")] impl FusedIterator for IntoIter {} #[unstable(feature = "trusted_len", issue = "37572")] diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs index a43ed65907f8..02207f1738f1 100644 --- a/src/libcore/slice/mod.rs +++ b/src/libcore/slice/mod.rs @@ -1461,7 +1461,7 @@ impl<'a, T> ExactSizeIterator for Iter<'a, T> { } } -#[unstable(feature = "fused", issue = "35602")] +#[stable(feature = "fused", since = "1.25.0")] impl<'a, T> FusedIterator for Iter<'a, T> {} #[unstable(feature = "trusted_len", issue = "37572")] @@ -1589,7 +1589,7 @@ impl<'a, T> ExactSizeIterator for IterMut<'a, T> { } } -#[unstable(feature = "fused", issue = "35602")] +#[stable(feature = "fused", since = "1.25.0")] impl<'a, T> FusedIterator for IterMut<'a, T> {} #[unstable(feature = "trusted_len", issue = "37572")] @@ -1737,7 +1737,7 @@ impl<'a, T, P> SplitIter for Split<'a, T, P> where P: FnMut(&T) -> bool { } } -#[unstable(feature = "fused", issue = "35602")] +#[stable(feature = "fused", since = "1.25.0")] impl<'a, T, P> FusedIterator for Split<'a, T, P> where P: FnMut(&T) -> bool {} /// An iterator over the subslices of the vector which are separated @@ -1835,7 +1835,7 @@ impl<'a, T, P> DoubleEndedIterator for SplitMut<'a, T, P> where } } -#[unstable(feature = "fused", issue = "35602")] +#[stable(feature = "fused", since = "1.25.0")] impl<'a, T, P> FusedIterator for SplitMut<'a, T, P> where P: FnMut(&T) -> bool {} /// An iterator over subslices separated by elements that match a predicate @@ -1892,7 +1892,7 @@ impl<'a, T, P> SplitIter for RSplit<'a, T, P> where P: FnMut(&T) -> bool { } } -//#[unstable(feature = "fused", issue = "35602")] +//#[stable(feature = "fused", since = "1.25.0")] #[unstable(feature = "slice_rsplit", issue = "41020")] impl<'a, T, P> FusedIterator for RSplit<'a, T, P> where P: FnMut(&T) -> bool {} @@ -1951,7 +1951,7 @@ impl<'a, T, P> DoubleEndedIterator for RSplitMut<'a, T, P> where } } -//#[unstable(feature = "fused", issue = "35602")] +//#[stable(feature = "fused", since = "1.25.0")] #[unstable(feature = "slice_rsplit", issue = "41020")] impl<'a, T, P> FusedIterator for RSplitMut<'a, T, P> where P: FnMut(&T) -> bool {} @@ -2088,7 +2088,7 @@ macro_rules! forward_iterator { } } - #[unstable(feature = "fused", issue = "35602")] + #[stable(feature = "fused", since = "1.25.0")] impl<'a, $elem, P> FusedIterator for $name<'a, $elem, P> where P: FnMut(&T) -> bool {} } @@ -2194,7 +2194,7 @@ impl<'a, T> DoubleEndedIterator for Windows<'a, T> { #[stable(feature = "rust1", since = "1.0.0")] impl<'a, T> ExactSizeIterator for Windows<'a, T> {} -#[unstable(feature = "fused", issue = "35602")] +#[stable(feature = "fused", since = "1.25.0")] impl<'a, T> FusedIterator for Windows<'a, T> {} #[doc(hidden)] @@ -2313,7 +2313,7 @@ impl<'a, T> DoubleEndedIterator for Chunks<'a, T> { #[stable(feature = "rust1", since = "1.0.0")] impl<'a, T> ExactSizeIterator for Chunks<'a, T> {} -#[unstable(feature = "fused", issue = "35602")] +#[stable(feature = "fused", since = "1.25.0")] impl<'a, T> FusedIterator for Chunks<'a, T> {} #[doc(hidden)] @@ -2429,7 +2429,7 @@ impl<'a, T> DoubleEndedIterator for ChunksMut<'a, T> { #[stable(feature = "rust1", since = "1.0.0")] impl<'a, T> ExactSizeIterator for ChunksMut<'a, T> {} -#[unstable(feature = "fused", issue = "35602")] +#[stable(feature = "fused", since = "1.25.0")] impl<'a, T> FusedIterator for ChunksMut<'a, T> {} #[doc(hidden)] @@ -2539,7 +2539,7 @@ impl<'a, T> ExactSizeIterator for ExactChunks<'a, T> { } } -#[unstable(feature = "fused", issue = "35602")] +#[stable(feature = "fused", since = "1.25.0")] impl<'a, T> FusedIterator for ExactChunks<'a, T> {} #[doc(hidden)] @@ -2636,7 +2636,7 @@ impl<'a, T> ExactSizeIterator for ExactChunksMut<'a, T> { } } -#[unstable(feature = "fused", issue = "35602")] +#[stable(feature = "fused", since = "1.25.0")] impl<'a, T> FusedIterator for ExactChunksMut<'a, T> {} #[doc(hidden)] diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs index 765b369e4b25..7e919b653f21 100644 --- a/src/libcore/str/mod.rs +++ b/src/libcore/str/mod.rs @@ -609,7 +609,7 @@ impl<'a> DoubleEndedIterator for Chars<'a> { } } -#[unstable(feature = "fused", issue = "35602")] +#[stable(feature = "fused", since = "1.25.0")] impl<'a> FusedIterator for Chars<'a> {} impl<'a> Chars<'a> { @@ -702,7 +702,7 @@ impl<'a> DoubleEndedIterator for CharIndices<'a> { } } -#[unstable(feature = "fused", issue = "35602")] +#[stable(feature = "fused", since = "1.25.0")] impl<'a> FusedIterator for CharIndices<'a> {} impl<'a> CharIndices<'a> { @@ -817,7 +817,7 @@ impl<'a> ExactSizeIterator for Bytes<'a> { } } -#[unstable(feature = "fused", issue = "35602")] +#[stable(feature = "fused", since = "1.25.0")] impl<'a> FusedIterator for Bytes<'a> {} #[unstable(feature = "trusted_len", issue = "37572")] @@ -977,10 +977,10 @@ macro_rules! generate_pattern_iterators { } } - #[unstable(feature = "fused", issue = "35602")] + #[stable(feature = "fused", since = "1.25.0")] impl<'a, P: Pattern<'a>> FusedIterator for $forward_iterator<'a, P> {} - #[unstable(feature = "fused", issue = "35602")] + #[stable(feature = "fused", since = "1.25.0")] impl<'a, P: Pattern<'a>> FusedIterator for $reverse_iterator<'a, P> where P::Searcher: ReverseSearcher<'a> {} @@ -1337,7 +1337,7 @@ impl<'a> DoubleEndedIterator for Lines<'a> { } } -#[unstable(feature = "fused", issue = "35602")] +#[stable(feature = "fused", since = "1.25.0")] impl<'a> FusedIterator for Lines<'a> {} /// Created with the method [`lines_any`]. @@ -1403,7 +1403,7 @@ impl<'a> DoubleEndedIterator for LinesAny<'a> { } } -#[unstable(feature = "fused", issue = "35602")] +#[stable(feature = "fused", since = "1.25.0")] #[allow(deprecated)] impl<'a> FusedIterator for LinesAny<'a> {} diff --git a/src/libstd/ascii.rs b/src/libstd/ascii.rs index 430c9df396a5..ce3e38de7eb1 100644 --- a/src/libstd/ascii.rs +++ b/src/libstd/ascii.rs @@ -590,7 +590,7 @@ impl DoubleEndedIterator for EscapeDefault { } #[stable(feature = "rust1", since = "1.0.0")] impl ExactSizeIterator for EscapeDefault {} -#[unstable(feature = "fused", issue = "35602")] +#[stable(feature = "fused", since = "1.25.0")] impl FusedIterator for EscapeDefault {} #[stable(feature = "std_debug", since = "1.16.0")] diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs index 4dfdc23ebee5..9e48efeb1136 100644 --- a/src/libstd/collections/hash/map.rs +++ b/src/libstd/collections/hash/map.rs @@ -1750,7 +1750,7 @@ impl<'a, K, V> ExactSizeIterator for Iter<'a, K, V> { } } -#[unstable(feature = "fused", issue = "35602")] +#[stable(feature = "fused", since = "1.25.0")] impl<'a, K, V> FusedIterator for Iter<'a, K, V> {} #[stable(feature = "rust1", since = "1.0.0")] @@ -1773,7 +1773,7 @@ impl<'a, K, V> ExactSizeIterator for IterMut<'a, K, V> { self.inner.len() } } -#[unstable(feature = "fused", issue = "35602")] +#[stable(feature = "fused", since = "1.25.0")] impl<'a, K, V> FusedIterator for IterMut<'a, K, V> {} #[stable(feature = "std_debug", since = "1.16.0")] @@ -1808,7 +1808,7 @@ impl ExactSizeIterator for IntoIter { self.inner.len() } } -#[unstable(feature = "fused", issue = "35602")] +#[stable(feature = "fused", since = "1.25.0")] impl FusedIterator for IntoIter {} #[stable(feature = "std_debug", since = "1.16.0")] @@ -1840,7 +1840,7 @@ impl<'a, K, V> ExactSizeIterator for Keys<'a, K, V> { self.inner.len() } } -#[unstable(feature = "fused", issue = "35602")] +#[stable(feature = "fused", since = "1.25.0")] impl<'a, K, V> FusedIterator for Keys<'a, K, V> {} #[stable(feature = "rust1", since = "1.0.0")] @@ -1863,7 +1863,7 @@ impl<'a, K, V> ExactSizeIterator for Values<'a, K, V> { self.inner.len() } } -#[unstable(feature = "fused", issue = "35602")] +#[stable(feature = "fused", since = "1.25.0")] impl<'a, K, V> FusedIterator for Values<'a, K, V> {} #[stable(feature = "map_values_mut", since = "1.10.0")] @@ -1886,7 +1886,7 @@ impl<'a, K, V> ExactSizeIterator for ValuesMut<'a, K, V> { self.inner.len() } } -#[unstable(feature = "fused", issue = "35602")] +#[stable(feature = "fused", since = "1.25.0")] impl<'a, K, V> FusedIterator for ValuesMut<'a, K, V> {} #[stable(feature = "std_debug", since = "1.16.0")] @@ -1921,7 +1921,7 @@ impl<'a, K, V> ExactSizeIterator for Drain<'a, K, V> { self.inner.len() } } -#[unstable(feature = "fused", issue = "35602")] +#[stable(feature = "fused", since = "1.25.0")] impl<'a, K, V> FusedIterator for Drain<'a, K, V> {} #[stable(feature = "std_debug", since = "1.16.0")] diff --git a/src/libstd/collections/hash/set.rs b/src/libstd/collections/hash/set.rs index e9427fb40a01..7a46603b2db5 100644 --- a/src/libstd/collections/hash/set.rs +++ b/src/libstd/collections/hash/set.rs @@ -1097,7 +1097,7 @@ impl<'a, K> ExactSizeIterator for Iter<'a, K> { self.iter.len() } } -#[unstable(feature = "fused", issue = "35602")] +#[stable(feature = "fused", since = "1.25.0")] impl<'a, K> FusedIterator for Iter<'a, K> {} #[stable(feature = "std_debug", since = "1.16.0")] @@ -1124,7 +1124,7 @@ impl ExactSizeIterator for IntoIter { self.iter.len() } } -#[unstable(feature = "fused", issue = "35602")] +#[stable(feature = "fused", since = "1.25.0")] impl FusedIterator for IntoIter {} #[stable(feature = "std_debug", since = "1.16.0")] @@ -1155,7 +1155,7 @@ impl<'a, K> ExactSizeIterator for Drain<'a, K> { self.iter.len() } } -#[unstable(feature = "fused", issue = "35602")] +#[stable(feature = "fused", since = "1.25.0")] impl<'a, K> FusedIterator for Drain<'a, K> {} #[stable(feature = "std_debug", since = "1.16.0")] @@ -1208,7 +1208,7 @@ impl<'a, T, S> fmt::Debug for Intersection<'a, T, S> } } -#[unstable(feature = "fused", issue = "35602")] +#[stable(feature = "fused", since = "1.25.0")] impl<'a, T, S> FusedIterator for Intersection<'a, T, S> where T: Eq + Hash, S: BuildHasher @@ -1244,7 +1244,7 @@ impl<'a, T, S> Iterator for Difference<'a, T, S> } } -#[unstable(feature = "fused", issue = "35602")] +#[stable(feature = "fused", since = "1.25.0")] impl<'a, T, S> FusedIterator for Difference<'a, T, S> where T: Eq + Hash, S: BuildHasher @@ -1283,7 +1283,7 @@ impl<'a, T, S> Iterator for SymmetricDifference<'a, T, S> } } -#[unstable(feature = "fused", issue = "35602")] +#[stable(feature = "fused", since = "1.25.0")] impl<'a, T, S> FusedIterator for SymmetricDifference<'a, T, S> where T: Eq + Hash, S: BuildHasher @@ -1307,7 +1307,7 @@ impl<'a, T, S> Clone for Union<'a, T, S> { } } -#[unstable(feature = "fused", issue = "35602")] +#[stable(feature = "fused", since = "1.25.0")] impl<'a, T, S> FusedIterator for Union<'a, T, S> where T: Eq + Hash, S: BuildHasher diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index d7d856fe3ad0..82c4443a45e6 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -266,7 +266,6 @@ #![feature(float_from_str_radix)] #![feature(fn_traits)] #![feature(fnbox)] -#![feature(fused)] #![feature(generic_param_attrs)] #![feature(hashmap_hasher)] #![feature(heap_api)] diff --git a/src/libstd/path.rs b/src/libstd/path.rs index 1608a752a463..0c54fb00d2d7 100644 --- a/src/libstd/path.rs +++ b/src/libstd/path.rs @@ -905,7 +905,7 @@ impl<'a> DoubleEndedIterator for Iter<'a> { } } -#[unstable(feature = "fused", issue = "35602")] +#[stable(feature = "fused", since = "1.25.0")] impl<'a> FusedIterator for Iter<'a> {} #[stable(feature = "rust1", since = "1.0.0")] @@ -1008,7 +1008,7 @@ impl<'a> DoubleEndedIterator for Components<'a> { } } -#[unstable(feature = "fused", issue = "35602")] +#[stable(feature = "fused", since = "1.25.0")] impl<'a> FusedIterator for Components<'a> {} #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libstd_unicode/char.rs b/src/libstd_unicode/char.rs index 844ff7a3c125..2bbbf6c06559 100644 --- a/src/libstd_unicode/char.rs +++ b/src/libstd_unicode/char.rs @@ -70,7 +70,7 @@ impl Iterator for ToLowercase { } } -#[unstable(feature = "fused", issue = "35602")] +#[stable(feature = "fused", since = "1.25.0")] impl FusedIterator for ToLowercase {} /// Returns an iterator that yields the uppercase equivalent of a `char`. @@ -92,7 +92,7 @@ impl Iterator for ToUppercase { } } -#[unstable(feature = "fused", issue = "35602")] +#[stable(feature = "fused", since = "1.25.0")] impl FusedIterator for ToUppercase {} #[derive(Debug)] diff --git a/src/libstd_unicode/lib.rs b/src/libstd_unicode/lib.rs index dcae7d0af409..f155b62e3cc7 100644 --- a/src/libstd_unicode/lib.rs +++ b/src/libstd_unicode/lib.rs @@ -36,7 +36,6 @@ #![feature(str_internals)] #![feature(decode_utf8)] #![feature(fn_traits)] -#![feature(fused)] #![feature(lang_items)] #![feature(non_exhaustive)] #![feature(staged_api)] diff --git a/src/libstd_unicode/u_str.rs b/src/libstd_unicode/u_str.rs index 5d1611acb7ee..ed2f205b580b 100644 --- a/src/libstd_unicode/u_str.rs +++ b/src/libstd_unicode/u_str.rs @@ -127,7 +127,7 @@ impl Iterator for Utf16Encoder } } -#[unstable(feature = "fused", issue = "35602")] +#[stable(feature = "fused", since = "1.25.0")] impl FusedIterator for Utf16Encoder where I: FusedIterator {} @@ -186,5 +186,5 @@ impl<'a> DoubleEndedIterator for SplitWhitespace<'a> { } } -#[unstable(feature = "fused", issue = "35602")] +#[stable(feature = "fused", since = "1.25.0")] impl<'a> FusedIterator for SplitWhitespace<'a> {} diff --git a/src/test/run-pass/issue-36053.rs b/src/test/run-pass/issue-36053.rs index 2411996cf054..ece58eedc56e 100644 --- a/src/test/run-pass/issue-36053.rs +++ b/src/test/run-pass/issue-36053.rs @@ -14,7 +14,6 @@ // `FusedIterator` in std but I was not able to isolate that into an // external crate. -#![feature(fused)] use std::iter::FusedIterator; struct Thing<'a>(&'a str); From c7c23fe9482c129855a667909ff58969f6efe1f6 Mon Sep 17 00:00:00 2001 From: Ulrik Sverdrup Date: Sat, 3 Mar 2018 14:15:28 +0100 Subject: [PATCH 28/68] core: Update stability attributes for FusedIterator --- src/liballoc/binary_heap.rs | 6 ++--- src/liballoc/boxed.rs | 2 +- src/liballoc/btree/map.rs | 16 ++++++------ src/liballoc/btree/set.rs | 14 +++++----- src/liballoc/linked_list.rs | 6 ++--- src/liballoc/str.rs | 2 +- src/liballoc/string.rs | 2 +- src/liballoc/vec.rs | 4 +-- src/liballoc/vec_deque.rs | 8 +++--- src/libcore/char.rs | 8 +++--- src/libcore/iter/mod.rs | 42 +++++++++++++++--------------- src/libcore/iter/range.rs | 6 ++--- src/libcore/iter/sources.rs | 8 +++--- src/libcore/iter/traits.rs | 4 +-- src/libcore/option.rs | 6 ++--- src/libcore/result.rs | 6 ++--- src/libcore/slice/mod.rs | 22 +++++++--------- src/libcore/str/mod.rs | 14 +++++----- src/libstd/ascii.rs | 2 +- src/libstd/collections/hash/map.rs | 14 +++++----- src/libstd/collections/hash/set.rs | 14 +++++----- src/libstd/path.rs | 6 ++--- src/libstd_unicode/char.rs | 4 +-- src/libstd_unicode/u_str.rs | 3 +-- 24 files changed, 108 insertions(+), 111 deletions(-) diff --git a/src/liballoc/binary_heap.rs b/src/liballoc/binary_heap.rs index a5694a90dbc9..8aaac5d6e08a 100644 --- a/src/liballoc/binary_heap.rs +++ b/src/liballoc/binary_heap.rs @@ -964,7 +964,7 @@ impl<'a, T> ExactSizeIterator for Iter<'a, T> { } } -#[stable(feature = "fused", since = "1.25.0")] +#[stable(feature = "fused", since = "1.26.0")] impl<'a, T> FusedIterator for Iter<'a, T> {} /// An owning iterator over the elements of a `BinaryHeap`. @@ -1019,7 +1019,7 @@ impl ExactSizeIterator for IntoIter { } } -#[stable(feature = "fused", since = "1.25.0")] +#[stable(feature = "fused", since = "1.26.0")] impl FusedIterator for IntoIter {} /// A draining iterator over the elements of a `BinaryHeap`. @@ -1065,7 +1065,7 @@ impl<'a, T: 'a> ExactSizeIterator for Drain<'a, T> { } } -#[stable(feature = "fused", since = "1.25.0")] +#[stable(feature = "fused", since = "1.26.0")] impl<'a, T: 'a> FusedIterator for Drain<'a, T> {} #[stable(feature = "binary_heap_extras_15", since = "1.5.0")] diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index 6b000b6fa91b..b776556d59f1 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -722,7 +722,7 @@ impl ExactSizeIterator for Box { } } -#[stable(feature = "fused", since = "1.25.0")] +#[stable(feature = "fused", since = "1.26.0")] impl FusedIterator for Box {} diff --git a/src/liballoc/btree/map.rs b/src/liballoc/btree/map.rs index 7b7a6374db9b..ed9c8c18f0d6 100644 --- a/src/liballoc/btree/map.rs +++ b/src/liballoc/btree/map.rs @@ -1156,7 +1156,7 @@ impl<'a, K: 'a, V: 'a> Iterator for Iter<'a, K, V> { } } -#[stable(feature = "fused", since = "1.25.0")] +#[stable(feature = "fused", since = "1.26.0")] impl<'a, K, V> FusedIterator for Iter<'a, K, V> {} #[stable(feature = "rust1", since = "1.0.0")] @@ -1235,7 +1235,7 @@ impl<'a, K: 'a, V: 'a> ExactSizeIterator for IterMut<'a, K, V> { } } -#[stable(feature = "fused", since = "1.25.0")] +#[stable(feature = "fused", since = "1.26.0")] impl<'a, K, V> FusedIterator for IterMut<'a, K, V> {} #[stable(feature = "rust1", since = "1.0.0")] @@ -1365,7 +1365,7 @@ impl ExactSizeIterator for IntoIter { } } -#[stable(feature = "fused", since = "1.25.0")] +#[stable(feature = "fused", since = "1.26.0")] impl FusedIterator for IntoIter {} #[stable(feature = "rust1", since = "1.0.0")] @@ -1395,7 +1395,7 @@ impl<'a, K, V> ExactSizeIterator for Keys<'a, K, V> { } } -#[stable(feature = "fused", since = "1.25.0")] +#[stable(feature = "fused", since = "1.26.0")] impl<'a, K, V> FusedIterator for Keys<'a, K, V> {} #[stable(feature = "rust1", since = "1.0.0")] @@ -1432,7 +1432,7 @@ impl<'a, K, V> ExactSizeIterator for Values<'a, K, V> { } } -#[stable(feature = "fused", since = "1.25.0")] +#[stable(feature = "fused", since = "1.26.0")] impl<'a, K, V> FusedIterator for Values<'a, K, V> {} #[stable(feature = "rust1", since = "1.0.0")] @@ -1482,7 +1482,7 @@ impl<'a, K, V> ExactSizeIterator for ValuesMut<'a, K, V> { } } -#[stable(feature = "fused", since = "1.25.0")] +#[stable(feature = "fused", since = "1.26.0")] impl<'a, K, V> FusedIterator for ValuesMut<'a, K, V> {} @@ -1561,7 +1561,7 @@ impl<'a, K, V> Range<'a, K, V> { } } -#[stable(feature = "fused", since = "1.25.0")] +#[stable(feature = "fused", since = "1.26.0")] impl<'a, K, V> FusedIterator for Range<'a, K, V> {} #[stable(feature = "btree_range", since = "1.17.0")] @@ -1630,7 +1630,7 @@ impl<'a, K, V> DoubleEndedIterator for RangeMut<'a, K, V> { } } -#[stable(feature = "fused", since = "1.25.0")] +#[stable(feature = "fused", since = "1.26.0")] impl<'a, K, V> FusedIterator for RangeMut<'a, K, V> {} impl<'a, K, V> RangeMut<'a, K, V> { diff --git a/src/liballoc/btree/set.rs b/src/liballoc/btree/set.rs index 34cb7a08ed70..2e3157147a08 100644 --- a/src/liballoc/btree/set.rs +++ b/src/liballoc/btree/set.rs @@ -946,7 +946,7 @@ impl<'a, T> ExactSizeIterator for Iter<'a, T> { fn len(&self) -> usize { self.iter.len() } } -#[stable(feature = "fused", since = "1.25.0")] +#[stable(feature = "fused", since = "1.26.0")] impl<'a, T> FusedIterator for Iter<'a, T> {} #[stable(feature = "rust1", since = "1.0.0")] @@ -971,7 +971,7 @@ impl ExactSizeIterator for IntoIter { fn len(&self) -> usize { self.iter.len() } } -#[stable(feature = "fused", since = "1.25.0")] +#[stable(feature = "fused", since = "1.26.0")] impl FusedIterator for IntoIter {} #[stable(feature = "btree_range", since = "1.17.0")] @@ -997,7 +997,7 @@ impl<'a, T> DoubleEndedIterator for Range<'a, T> { } } -#[stable(feature = "fused", since = "1.25.0")] +#[stable(feature = "fused", since = "1.26.0")] impl<'a, T> FusedIterator for Range<'a, T> {} /// Compare `x` and `y`, but return `short` if x is None and `long` if y is None @@ -1044,7 +1044,7 @@ impl<'a, T: Ord> Iterator for Difference<'a, T> { } } -#[stable(feature = "fused", since = "1.25.0")] +#[stable(feature = "fused", since = "1.26.0")] impl<'a, T: Ord> FusedIterator for Difference<'a, T> {} #[stable(feature = "rust1", since = "1.0.0")] @@ -1078,7 +1078,7 @@ impl<'a, T: Ord> Iterator for SymmetricDifference<'a, T> { } } -#[stable(feature = "fused", since = "1.25.0")] +#[stable(feature = "fused", since = "1.26.0")] impl<'a, T: Ord> FusedIterator for SymmetricDifference<'a, T> {} #[stable(feature = "rust1", since = "1.0.0")] @@ -1116,7 +1116,7 @@ impl<'a, T: Ord> Iterator for Intersection<'a, T> { } } -#[stable(feature = "fused", since = "1.25.0")] +#[stable(feature = "fused", since = "1.26.0")] impl<'a, T: Ord> FusedIterator for Intersection<'a, T> {} #[stable(feature = "rust1", since = "1.0.0")] @@ -1150,5 +1150,5 @@ impl<'a, T: Ord> Iterator for Union<'a, T> { } } -#[stable(feature = "fused", since = "1.25.0")] +#[stable(feature = "fused", since = "1.26.0")] impl<'a, T: Ord> FusedIterator for Union<'a, T> {} diff --git a/src/liballoc/linked_list.rs b/src/liballoc/linked_list.rs index 87939fddfc81..097d2e414f5c 100644 --- a/src/liballoc/linked_list.rs +++ b/src/liballoc/linked_list.rs @@ -897,7 +897,7 @@ impl<'a, T> DoubleEndedIterator for Iter<'a, T> { #[stable(feature = "rust1", since = "1.0.0")] impl<'a, T> ExactSizeIterator for Iter<'a, T> {} -#[stable(feature = "fused", since = "1.25.0")] +#[stable(feature = "fused", since = "1.26.0")] impl<'a, T> FusedIterator for Iter<'a, T> {} #[stable(feature = "rust1", since = "1.0.0")] @@ -946,7 +946,7 @@ impl<'a, T> DoubleEndedIterator for IterMut<'a, T> { #[stable(feature = "rust1", since = "1.0.0")] impl<'a, T> ExactSizeIterator for IterMut<'a, T> {} -#[stable(feature = "fused", since = "1.25.0")] +#[stable(feature = "fused", since = "1.26.0")] impl<'a, T> FusedIterator for IterMut<'a, T> {} impl<'a, T> IterMut<'a, T> { @@ -1117,7 +1117,7 @@ impl DoubleEndedIterator for IntoIter { #[stable(feature = "rust1", since = "1.0.0")] impl ExactSizeIterator for IntoIter {} -#[stable(feature = "fused", since = "1.25.0")] +#[stable(feature = "fused", since = "1.26.0")] impl FusedIterator for IntoIter {} #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/liballoc/str.rs b/src/liballoc/str.rs index 1a431bb26942..82f8476d670a 100644 --- a/src/liballoc/str.rs +++ b/src/liballoc/str.rs @@ -171,7 +171,7 @@ impl<'a> Iterator for EncodeUtf16<'a> { } } -#[stable(feature = "fused", since = "1.25.0")] +#[stable(feature = "fused", since = "1.26.0")] impl<'a> FusedIterator for EncodeUtf16<'a> {} #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/liballoc/string.rs b/src/liballoc/string.rs index 1fcabd8a4278..370fb6b4e890 100644 --- a/src/liballoc/string.rs +++ b/src/liballoc/string.rs @@ -2254,5 +2254,5 @@ impl<'a> DoubleEndedIterator for Drain<'a> { } } -#[stable(feature = "fused", since = "1.25.0")] +#[stable(feature = "fused", since = "1.26.0")] impl<'a> FusedIterator for Drain<'a> {} diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs index 03c9750fb392..9e5672ef148c 100644 --- a/src/liballoc/vec.rs +++ b/src/liballoc/vec.rs @@ -2389,7 +2389,7 @@ impl ExactSizeIterator for IntoIter { } } -#[stable(feature = "fused", since = "1.25.0")] +#[stable(feature = "fused", since = "1.26.0")] impl FusedIterator for IntoIter {} #[unstable(feature = "trusted_len", issue = "37572")] @@ -2495,7 +2495,7 @@ impl<'a, T> ExactSizeIterator for Drain<'a, T> { } } -#[stable(feature = "fused", since = "1.25.0")] +#[stable(feature = "fused", since = "1.26.0")] impl<'a, T> FusedIterator for Drain<'a, T> {} /// A place for insertion at the back of a `Vec`. diff --git a/src/liballoc/vec_deque.rs b/src/liballoc/vec_deque.rs index 3d7549abe6ff..68add3cbd51f 100644 --- a/src/liballoc/vec_deque.rs +++ b/src/liballoc/vec_deque.rs @@ -1991,7 +1991,7 @@ impl<'a, T> ExactSizeIterator for Iter<'a, T> { } } -#[stable(feature = "fused", since = "1.25.0")] +#[stable(feature = "fused", since = "1.26.0")] impl<'a, T> FusedIterator for Iter<'a, T> {} @@ -2084,7 +2084,7 @@ impl<'a, T> ExactSizeIterator for IterMut<'a, T> { } } -#[stable(feature = "fused", since = "1.25.0")] +#[stable(feature = "fused", since = "1.26.0")] impl<'a, T> FusedIterator for IterMut<'a, T> {} /// An owning iterator over the elements of a `VecDeque`. @@ -2140,7 +2140,7 @@ impl ExactSizeIterator for IntoIter { } } -#[stable(feature = "fused", since = "1.25.0")] +#[stable(feature = "fused", since = "1.26.0")] impl FusedIterator for IntoIter {} /// A draining iterator over the elements of a `VecDeque`. @@ -2247,7 +2247,7 @@ impl<'a, T: 'a> DoubleEndedIterator for Drain<'a, T> { #[stable(feature = "drain", since = "1.6.0")] impl<'a, T: 'a> ExactSizeIterator for Drain<'a, T> {} -#[stable(feature = "fused", since = "1.25.0")] +#[stable(feature = "fused", since = "1.26.0")] impl<'a, T: 'a> FusedIterator for Drain<'a, T> {} #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libcore/char.rs b/src/libcore/char.rs index 3ff31a7a9281..c90cca7dbe44 100644 --- a/src/libcore/char.rs +++ b/src/libcore/char.rs @@ -643,7 +643,7 @@ impl ExactSizeIterator for EscapeUnicode { } } -#[stable(feature = "fused", since = "1.25.0")] +#[stable(feature = "fused", since = "1.26.0")] impl FusedIterator for EscapeUnicode {} #[stable(feature = "char_struct_display", since = "1.16.0")] @@ -756,7 +756,7 @@ impl ExactSizeIterator for EscapeDefault { } } -#[stable(feature = "fused", since = "1.25.0")] +#[stable(feature = "fused", since = "1.26.0")] impl FusedIterator for EscapeDefault {} #[stable(feature = "char_struct_display", since = "1.16.0")] @@ -790,7 +790,7 @@ impl Iterator for EscapeDebug { #[stable(feature = "char_escape_debug", since = "1.20.0")] impl ExactSizeIterator for EscapeDebug { } -#[stable(feature = "fused", since = "1.25.0")] +#[stable(feature = "fused", since = "1.26.0")] impl FusedIterator for EscapeDebug {} #[stable(feature = "char_escape_debug", since = "1.20.0")] @@ -904,5 +904,5 @@ impl> Iterator for DecodeUtf8 { } } -#[stable(feature = "fused", since = "1.25.0")] +#[unstable(feature = "decode_utf8", issue = "33906")] impl> FusedIterator for DecodeUtf8 {} diff --git a/src/libcore/iter/mod.rs b/src/libcore/iter/mod.rs index 9a8f7fc4e6ab..a6802d606ca8 100644 --- a/src/libcore/iter/mod.rs +++ b/src/libcore/iter/mod.rs @@ -344,7 +344,7 @@ pub use self::sources::{Once, once}; pub use self::traits::{FromIterator, IntoIterator, DoubleEndedIterator, Extend}; #[stable(feature = "rust1", since = "1.0.0")] pub use self::traits::{ExactSizeIterator, Sum, Product}; -#[stable(feature = "fused", since = "1.25.0")] +#[stable(feature = "fused", since = "1.26.0")] pub use self::traits::FusedIterator; #[unstable(feature = "trusted_len", issue = "37572")] pub use self::traits::TrustedLen; @@ -506,7 +506,7 @@ impl ExactSizeIterator for Rev } } -#[stable(feature = "fused", since = "1.25.0")] +#[stable(feature = "fused", since = "1.26.0")] impl FusedIterator for Rev where I: FusedIterator + DoubleEndedIterator {} @@ -589,7 +589,7 @@ impl<'a, I, T: 'a> ExactSizeIterator for Cloned } } -#[stable(feature = "fused", since = "1.25.0")] +#[stable(feature = "fused", since = "1.26.0")] impl<'a, I, T: 'a> FusedIterator for Cloned where I: FusedIterator, T: Clone {} @@ -662,7 +662,7 @@ impl Iterator for Cycle where I: Clone + Iterator { } } -#[stable(feature = "fused", since = "1.25.0")] +#[stable(feature = "fused", since = "1.26.0")] impl FusedIterator for Cycle where I: Clone + Iterator {} /// An iterator for stepping iterators by a custom amount. @@ -1002,7 +1002,7 @@ impl DoubleEndedIterator for Chain where } // Note: *both* must be fused to handle double-ended iterators. -#[stable(feature = "fused", since = "1.25.0")] +#[stable(feature = "fused", since = "1.26.0")] impl FusedIterator for Chain where A: FusedIterator, B: FusedIterator, @@ -1262,7 +1262,7 @@ unsafe impl TrustedRandomAccess for Zip } } -#[stable(feature = "fused", since = "1.25.0")] +#[stable(feature = "fused", since = "1.26.0")] impl FusedIterator for Zip where A: FusedIterator, B: FusedIterator, {} @@ -1404,7 +1404,7 @@ impl ExactSizeIterator for Map } } -#[stable(feature = "fused", since = "1.25.0")] +#[stable(feature = "fused", since = "1.26.0")] impl FusedIterator for Map where F: FnMut(I::Item) -> B {} @@ -1553,7 +1553,7 @@ impl DoubleEndedIterator for Filter } } -#[stable(feature = "fused", since = "1.25.0")] +#[stable(feature = "fused", since = "1.26.0")] impl FusedIterator for Filter where P: FnMut(&I::Item) -> bool {} @@ -1663,7 +1663,7 @@ impl DoubleEndedIterator for FilterMap } } -#[stable(feature = "fused", since = "1.25.0")] +#[stable(feature = "fused", since = "1.26.0")] impl FusedIterator for FilterMap where F: FnMut(I::Item) -> Option {} @@ -1818,7 +1818,7 @@ unsafe impl TrustedRandomAccess for Enumerate } } -#[stable(feature = "fused", since = "1.25.0")] +#[stable(feature = "fused", since = "1.26.0")] impl FusedIterator for Enumerate where I: FusedIterator {} #[unstable(feature = "trusted_len", issue = "37572")] @@ -1938,7 +1938,7 @@ impl Iterator for Peekable { #[stable(feature = "rust1", since = "1.0.0")] impl ExactSizeIterator for Peekable {} -#[stable(feature = "fused", since = "1.25.0")] +#[stable(feature = "fused", since = "1.26.0")] impl FusedIterator for Peekable {} impl Peekable { @@ -2072,7 +2072,7 @@ impl Iterator for SkipWhile } } -#[stable(feature = "fused", since = "1.25.0")] +#[stable(feature = "fused", since = "1.26.0")] impl FusedIterator for SkipWhile where I: FusedIterator, P: FnMut(&I::Item) -> bool {} @@ -2151,7 +2151,7 @@ impl Iterator for TakeWhile } } -#[stable(feature = "fused", since = "1.25.0")] +#[stable(feature = "fused", since = "1.26.0")] impl FusedIterator for TakeWhile where I: FusedIterator, P: FnMut(&I::Item) -> bool {} @@ -2290,7 +2290,7 @@ impl DoubleEndedIterator for Skip where I: DoubleEndedIterator + ExactSize } } -#[stable(feature = "fused", since = "1.25.0")] +#[stable(feature = "fused", since = "1.26.0")] impl FusedIterator for Skip where I: FusedIterator {} /// An iterator that only iterates over the first `n` iterations of `iter`. @@ -2371,7 +2371,7 @@ impl Iterator for Take where I: Iterator{ #[stable(feature = "rust1", since = "1.0.0")] impl ExactSizeIterator for Take where I: ExactSizeIterator {} -#[stable(feature = "fused", since = "1.25.0")] +#[stable(feature = "fused", since = "1.26.0")] impl FusedIterator for Take where I: FusedIterator {} #[unstable(feature = "trusted_len", issue = "37572")] @@ -2517,7 +2517,7 @@ impl DoubleEndedIterator for FlatMap } } -#[stable(feature = "fused", since = "1.25.0")] +#[stable(feature = "fused", since = "1.26.0")] impl FusedIterator for FlatMap where I: FusedIterator, U: IntoIterator, F: FnMut(I::Item) -> U {} @@ -2605,7 +2605,7 @@ impl DoubleEndedIterator for Flatten } } -#[stable(feature = "fused", since = "1.25.0")] +#[stable(feature = "fused", since = "1.26.0")] impl FusedIterator for Flatten where I: FusedIterator, U: Iterator, I::Item: IntoIterator {} @@ -2765,7 +2765,7 @@ pub struct Fuse { done: bool } -#[stable(feature = "fused", since = "1.25.0")] +#[stable(feature = "fused", since = "1.26.0")] impl FusedIterator for Fuse where I: Iterator {} #[stable(feature = "rust1", since = "1.0.0")] @@ -2896,7 +2896,7 @@ unsafe impl TrustedRandomAccess for Fuse } } -#[stable(feature = "fused", since = "1.25.0")] +#[stable(feature = "fused", since = "1.26.0")] impl Iterator for Fuse where I: FusedIterator { #[inline] fn next(&mut self) -> Option<::Item> { @@ -2938,7 +2938,7 @@ impl Iterator for Fuse where I: FusedIterator { } } -#[stable(feature = "fused", since = "1.25.0")] +#[stable(feature = "fused", since = "1.26.0")] impl DoubleEndedIterator for Fuse where I: DoubleEndedIterator + FusedIterator { @@ -3082,6 +3082,6 @@ impl ExactSizeIterator for Inspect } } -#[stable(feature = "fused", since = "1.25.0")] +#[stable(feature = "fused", since = "1.26.0")] impl FusedIterator for Inspect where F: FnMut(&I::Item) {} diff --git a/src/libcore/iter/range.rs b/src/libcore/iter/range.rs index 7f3b227e8b73..9a3fd215dcfe 100644 --- a/src/libcore/iter/range.rs +++ b/src/libcore/iter/range.rs @@ -295,7 +295,7 @@ impl DoubleEndedIterator for ops::Range { } } -#[stable(feature = "fused", since = "1.25.0")] +#[stable(feature = "fused", since = "1.26.0")] impl FusedIterator for ops::Range {} #[stable(feature = "rust1", since = "1.0.0")] @@ -322,7 +322,7 @@ impl Iterator for ops::RangeFrom { } } -#[stable(feature = "fused", since = "1.25.0")] +#[stable(feature = "fused", since = "1.26.0")] impl FusedIterator for ops::RangeFrom {} #[unstable(feature = "trusted_len", issue = "37572")] @@ -463,5 +463,5 @@ impl DoubleEndedIterator for ops::RangeInclusive { } } -#[stable(feature = "fused", since = "1.25.0")] +#[stable(feature = "fused", since = "1.26.0")] impl FusedIterator for ops::RangeInclusive {} diff --git a/src/libcore/iter/sources.rs b/src/libcore/iter/sources.rs index 149dff83bc0e..0fc1a3aa8ac0 100644 --- a/src/libcore/iter/sources.rs +++ b/src/libcore/iter/sources.rs @@ -41,7 +41,7 @@ impl DoubleEndedIterator for Repeat { fn next_back(&mut self) -> Option { Some(self.element.clone()) } } -#[stable(feature = "fused", since = "1.25.0")] +#[stable(feature = "fused", since = "1.26.0")] impl FusedIterator for Repeat {} #[unstable(feature = "trusted_len", issue = "37572")] @@ -135,7 +135,7 @@ impl A> DoubleEndedIterator for RepeatWith { fn next_back(&mut self) -> Option { self.next() } } -#[unstable(feature = "fused", issue = "35602")] +#[unstable(feature = "iterator_repeat_with", issue = "48169")] impl A> FusedIterator for RepeatWith {} #[unstable(feature = "trusted_len", issue = "37572")] @@ -259,7 +259,7 @@ impl ExactSizeIterator for Empty { #[unstable(feature = "trusted_len", issue = "37572")] unsafe impl TrustedLen for Empty {} -#[stable(feature = "fused", since = "1.25.0")] +#[stable(feature = "fused", since = "1.26.0")] impl FusedIterator for Empty {} // not #[derive] because that adds a Clone bound on T, @@ -340,7 +340,7 @@ impl ExactSizeIterator for Once { #[unstable(feature = "trusted_len", issue = "37572")] unsafe impl TrustedLen for Once {} -#[stable(feature = "fused", since = "1.25.0")] +#[stable(feature = "fused", since = "1.26.0")] impl FusedIterator for Once {} /// Creates an iterator that yields an element exactly once. diff --git a/src/libcore/iter/traits.rs b/src/libcore/iter/traits.rs index a86f4e74706e..0267fcd37545 100644 --- a/src/libcore/iter/traits.rs +++ b/src/libcore/iter/traits.rs @@ -959,10 +959,10 @@ impl Product> for Result /// [`None`]: ../../std/option/enum.Option.html#variant.None /// [`Iterator::fuse`]: ../../std/iter/trait.Iterator.html#method.fuse /// [`Fuse`]: ../../std/iter/struct.Fuse.html -#[stable(feature = "fused", since = "1.25.0")] +#[stable(feature = "fused", since = "1.26.0")] pub trait FusedIterator: Iterator {} -#[stable(feature = "fused", since = "1.25.0")] +#[stable(feature = "fused", since = "1.26.0")] impl<'a, I: FusedIterator + ?Sized> FusedIterator for &'a mut I {} /// An iterator that reports an accurate length using size_hint. diff --git a/src/libcore/option.rs b/src/libcore/option.rs index 99c1d7d9b361..b66aad246fe0 100644 --- a/src/libcore/option.rs +++ b/src/libcore/option.rs @@ -1051,7 +1051,7 @@ impl<'a, A> DoubleEndedIterator for Iter<'a, A> { #[stable(feature = "rust1", since = "1.0.0")] impl<'a, A> ExactSizeIterator for Iter<'a, A> {} -#[stable(feature = "fused", since = "1.25.0")] +#[stable(feature = "fused", since = "1.26.0")] impl<'a, A> FusedIterator for Iter<'a, A> {} #[unstable(feature = "trusted_len", issue = "37572")] @@ -1096,7 +1096,7 @@ impl<'a, A> DoubleEndedIterator for IterMut<'a, A> { #[stable(feature = "rust1", since = "1.0.0")] impl<'a, A> ExactSizeIterator for IterMut<'a, A> {} -#[stable(feature = "fused", since = "1.25.0")] +#[stable(feature = "fused", since = "1.26.0")] impl<'a, A> FusedIterator for IterMut<'a, A> {} #[unstable(feature = "trusted_len", issue = "37572")] unsafe impl<'a, A> TrustedLen for IterMut<'a, A> {} @@ -1133,7 +1133,7 @@ impl DoubleEndedIterator for IntoIter { #[stable(feature = "rust1", since = "1.0.0")] impl ExactSizeIterator for IntoIter {} -#[stable(feature = "fused", since = "1.25.0")] +#[stable(feature = "fused", since = "1.26.0")] impl FusedIterator for IntoIter {} #[unstable(feature = "trusted_len", issue = "37572")] diff --git a/src/libcore/result.rs b/src/libcore/result.rs index 5131fc837ef2..c152d4979b90 100644 --- a/src/libcore/result.rs +++ b/src/libcore/result.rs @@ -1038,7 +1038,7 @@ impl<'a, T> DoubleEndedIterator for Iter<'a, T> { #[stable(feature = "rust1", since = "1.0.0")] impl<'a, T> ExactSizeIterator for Iter<'a, T> {} -#[stable(feature = "fused", since = "1.25.0")] +#[stable(feature = "fused", since = "1.26.0")] impl<'a, T> FusedIterator for Iter<'a, T> {} #[unstable(feature = "trusted_len", issue = "37572")] @@ -1082,7 +1082,7 @@ impl<'a, T> DoubleEndedIterator for IterMut<'a, T> { #[stable(feature = "rust1", since = "1.0.0")] impl<'a, T> ExactSizeIterator for IterMut<'a, T> {} -#[stable(feature = "fused", since = "1.25.0")] +#[stable(feature = "fused", since = "1.26.0")] impl<'a, T> FusedIterator for IterMut<'a, T> {} #[unstable(feature = "trusted_len", issue = "37572")] @@ -1125,7 +1125,7 @@ impl DoubleEndedIterator for IntoIter { #[stable(feature = "rust1", since = "1.0.0")] impl ExactSizeIterator for IntoIter {} -#[stable(feature = "fused", since = "1.25.0")] +#[stable(feature = "fused", since = "1.26.0")] impl FusedIterator for IntoIter {} #[unstable(feature = "trusted_len", issue = "37572")] diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs index 02207f1738f1..4f1ee2d94919 100644 --- a/src/libcore/slice/mod.rs +++ b/src/libcore/slice/mod.rs @@ -1461,7 +1461,7 @@ impl<'a, T> ExactSizeIterator for Iter<'a, T> { } } -#[stable(feature = "fused", since = "1.25.0")] +#[stable(feature = "fused", since = "1.26.0")] impl<'a, T> FusedIterator for Iter<'a, T> {} #[unstable(feature = "trusted_len", issue = "37572")] @@ -1589,7 +1589,7 @@ impl<'a, T> ExactSizeIterator for IterMut<'a, T> { } } -#[stable(feature = "fused", since = "1.25.0")] +#[stable(feature = "fused", since = "1.26.0")] impl<'a, T> FusedIterator for IterMut<'a, T> {} #[unstable(feature = "trusted_len", issue = "37572")] @@ -1737,7 +1737,7 @@ impl<'a, T, P> SplitIter for Split<'a, T, P> where P: FnMut(&T) -> bool { } } -#[stable(feature = "fused", since = "1.25.0")] +#[stable(feature = "fused", since = "1.26.0")] impl<'a, T, P> FusedIterator for Split<'a, T, P> where P: FnMut(&T) -> bool {} /// An iterator over the subslices of the vector which are separated @@ -1835,7 +1835,7 @@ impl<'a, T, P> DoubleEndedIterator for SplitMut<'a, T, P> where } } -#[stable(feature = "fused", since = "1.25.0")] +#[stable(feature = "fused", since = "1.26.0")] impl<'a, T, P> FusedIterator for SplitMut<'a, T, P> where P: FnMut(&T) -> bool {} /// An iterator over subslices separated by elements that match a predicate @@ -1892,7 +1892,6 @@ impl<'a, T, P> SplitIter for RSplit<'a, T, P> where P: FnMut(&T) -> bool { } } -//#[stable(feature = "fused", since = "1.25.0")] #[unstable(feature = "slice_rsplit", issue = "41020")] impl<'a, T, P> FusedIterator for RSplit<'a, T, P> where P: FnMut(&T) -> bool {} @@ -1951,7 +1950,6 @@ impl<'a, T, P> DoubleEndedIterator for RSplitMut<'a, T, P> where } } -//#[stable(feature = "fused", since = "1.25.0")] #[unstable(feature = "slice_rsplit", issue = "41020")] impl<'a, T, P> FusedIterator for RSplitMut<'a, T, P> where P: FnMut(&T) -> bool {} @@ -2088,7 +2086,7 @@ macro_rules! forward_iterator { } } - #[stable(feature = "fused", since = "1.25.0")] + #[stable(feature = "fused", since = "1.26.0")] impl<'a, $elem, P> FusedIterator for $name<'a, $elem, P> where P: FnMut(&T) -> bool {} } @@ -2194,7 +2192,7 @@ impl<'a, T> DoubleEndedIterator for Windows<'a, T> { #[stable(feature = "rust1", since = "1.0.0")] impl<'a, T> ExactSizeIterator for Windows<'a, T> {} -#[stable(feature = "fused", since = "1.25.0")] +#[stable(feature = "fused", since = "1.26.0")] impl<'a, T> FusedIterator for Windows<'a, T> {} #[doc(hidden)] @@ -2313,7 +2311,7 @@ impl<'a, T> DoubleEndedIterator for Chunks<'a, T> { #[stable(feature = "rust1", since = "1.0.0")] impl<'a, T> ExactSizeIterator for Chunks<'a, T> {} -#[stable(feature = "fused", since = "1.25.0")] +#[stable(feature = "fused", since = "1.26.0")] impl<'a, T> FusedIterator for Chunks<'a, T> {} #[doc(hidden)] @@ -2429,7 +2427,7 @@ impl<'a, T> DoubleEndedIterator for ChunksMut<'a, T> { #[stable(feature = "rust1", since = "1.0.0")] impl<'a, T> ExactSizeIterator for ChunksMut<'a, T> {} -#[stable(feature = "fused", since = "1.25.0")] +#[stable(feature = "fused", since = "1.26.0")] impl<'a, T> FusedIterator for ChunksMut<'a, T> {} #[doc(hidden)] @@ -2539,7 +2537,7 @@ impl<'a, T> ExactSizeIterator for ExactChunks<'a, T> { } } -#[stable(feature = "fused", since = "1.25.0")] +#[unstable(feature = "exact_chunks", issue = "47115")] impl<'a, T> FusedIterator for ExactChunks<'a, T> {} #[doc(hidden)] @@ -2636,7 +2634,7 @@ impl<'a, T> ExactSizeIterator for ExactChunksMut<'a, T> { } } -#[stable(feature = "fused", since = "1.25.0")] +#[unstable(feature = "exact_chunks", issue = "47115")] impl<'a, T> FusedIterator for ExactChunksMut<'a, T> {} #[doc(hidden)] diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs index 7e919b653f21..e225c9522bc0 100644 --- a/src/libcore/str/mod.rs +++ b/src/libcore/str/mod.rs @@ -609,7 +609,7 @@ impl<'a> DoubleEndedIterator for Chars<'a> { } } -#[stable(feature = "fused", since = "1.25.0")] +#[stable(feature = "fused", since = "1.26.0")] impl<'a> FusedIterator for Chars<'a> {} impl<'a> Chars<'a> { @@ -702,7 +702,7 @@ impl<'a> DoubleEndedIterator for CharIndices<'a> { } } -#[stable(feature = "fused", since = "1.25.0")] +#[stable(feature = "fused", since = "1.26.0")] impl<'a> FusedIterator for CharIndices<'a> {} impl<'a> CharIndices<'a> { @@ -817,7 +817,7 @@ impl<'a> ExactSizeIterator for Bytes<'a> { } } -#[stable(feature = "fused", since = "1.25.0")] +#[stable(feature = "fused", since = "1.26.0")] impl<'a> FusedIterator for Bytes<'a> {} #[unstable(feature = "trusted_len", issue = "37572")] @@ -977,10 +977,10 @@ macro_rules! generate_pattern_iterators { } } - #[stable(feature = "fused", since = "1.25.0")] + #[stable(feature = "fused", since = "1.26.0")] impl<'a, P: Pattern<'a>> FusedIterator for $forward_iterator<'a, P> {} - #[stable(feature = "fused", since = "1.25.0")] + #[stable(feature = "fused", since = "1.26.0")] impl<'a, P: Pattern<'a>> FusedIterator for $reverse_iterator<'a, P> where P::Searcher: ReverseSearcher<'a> {} @@ -1337,7 +1337,7 @@ impl<'a> DoubleEndedIterator for Lines<'a> { } } -#[stable(feature = "fused", since = "1.25.0")] +#[stable(feature = "fused", since = "1.26.0")] impl<'a> FusedIterator for Lines<'a> {} /// Created with the method [`lines_any`]. @@ -1403,7 +1403,7 @@ impl<'a> DoubleEndedIterator for LinesAny<'a> { } } -#[stable(feature = "fused", since = "1.25.0")] +#[stable(feature = "fused", since = "1.26.0")] #[allow(deprecated)] impl<'a> FusedIterator for LinesAny<'a> {} diff --git a/src/libstd/ascii.rs b/src/libstd/ascii.rs index ce3e38de7eb1..d5bf9e9bb2f6 100644 --- a/src/libstd/ascii.rs +++ b/src/libstd/ascii.rs @@ -590,7 +590,7 @@ impl DoubleEndedIterator for EscapeDefault { } #[stable(feature = "rust1", since = "1.0.0")] impl ExactSizeIterator for EscapeDefault {} -#[stable(feature = "fused", since = "1.25.0")] +#[stable(feature = "fused", since = "1.26.0")] impl FusedIterator for EscapeDefault {} #[stable(feature = "std_debug", since = "1.16.0")] diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs index 9e48efeb1136..e86264569a03 100644 --- a/src/libstd/collections/hash/map.rs +++ b/src/libstd/collections/hash/map.rs @@ -1750,7 +1750,7 @@ impl<'a, K, V> ExactSizeIterator for Iter<'a, K, V> { } } -#[stable(feature = "fused", since = "1.25.0")] +#[stable(feature = "fused", since = "1.26.0")] impl<'a, K, V> FusedIterator for Iter<'a, K, V> {} #[stable(feature = "rust1", since = "1.0.0")] @@ -1773,7 +1773,7 @@ impl<'a, K, V> ExactSizeIterator for IterMut<'a, K, V> { self.inner.len() } } -#[stable(feature = "fused", since = "1.25.0")] +#[stable(feature = "fused", since = "1.26.0")] impl<'a, K, V> FusedIterator for IterMut<'a, K, V> {} #[stable(feature = "std_debug", since = "1.16.0")] @@ -1808,7 +1808,7 @@ impl ExactSizeIterator for IntoIter { self.inner.len() } } -#[stable(feature = "fused", since = "1.25.0")] +#[stable(feature = "fused", since = "1.26.0")] impl FusedIterator for IntoIter {} #[stable(feature = "std_debug", since = "1.16.0")] @@ -1840,7 +1840,7 @@ impl<'a, K, V> ExactSizeIterator for Keys<'a, K, V> { self.inner.len() } } -#[stable(feature = "fused", since = "1.25.0")] +#[stable(feature = "fused", since = "1.26.0")] impl<'a, K, V> FusedIterator for Keys<'a, K, V> {} #[stable(feature = "rust1", since = "1.0.0")] @@ -1863,7 +1863,7 @@ impl<'a, K, V> ExactSizeIterator for Values<'a, K, V> { self.inner.len() } } -#[stable(feature = "fused", since = "1.25.0")] +#[stable(feature = "fused", since = "1.26.0")] impl<'a, K, V> FusedIterator for Values<'a, K, V> {} #[stable(feature = "map_values_mut", since = "1.10.0")] @@ -1886,7 +1886,7 @@ impl<'a, K, V> ExactSizeIterator for ValuesMut<'a, K, V> { self.inner.len() } } -#[stable(feature = "fused", since = "1.25.0")] +#[stable(feature = "fused", since = "1.26.0")] impl<'a, K, V> FusedIterator for ValuesMut<'a, K, V> {} #[stable(feature = "std_debug", since = "1.16.0")] @@ -1921,7 +1921,7 @@ impl<'a, K, V> ExactSizeIterator for Drain<'a, K, V> { self.inner.len() } } -#[stable(feature = "fused", since = "1.25.0")] +#[stable(feature = "fused", since = "1.26.0")] impl<'a, K, V> FusedIterator for Drain<'a, K, V> {} #[stable(feature = "std_debug", since = "1.16.0")] diff --git a/src/libstd/collections/hash/set.rs b/src/libstd/collections/hash/set.rs index 7a46603b2db5..f41b7a62918a 100644 --- a/src/libstd/collections/hash/set.rs +++ b/src/libstd/collections/hash/set.rs @@ -1097,7 +1097,7 @@ impl<'a, K> ExactSizeIterator for Iter<'a, K> { self.iter.len() } } -#[stable(feature = "fused", since = "1.25.0")] +#[stable(feature = "fused", since = "1.26.0")] impl<'a, K> FusedIterator for Iter<'a, K> {} #[stable(feature = "std_debug", since = "1.16.0")] @@ -1124,7 +1124,7 @@ impl ExactSizeIterator for IntoIter { self.iter.len() } } -#[stable(feature = "fused", since = "1.25.0")] +#[stable(feature = "fused", since = "1.26.0")] impl FusedIterator for IntoIter {} #[stable(feature = "std_debug", since = "1.16.0")] @@ -1155,7 +1155,7 @@ impl<'a, K> ExactSizeIterator for Drain<'a, K> { self.iter.len() } } -#[stable(feature = "fused", since = "1.25.0")] +#[stable(feature = "fused", since = "1.26.0")] impl<'a, K> FusedIterator for Drain<'a, K> {} #[stable(feature = "std_debug", since = "1.16.0")] @@ -1208,7 +1208,7 @@ impl<'a, T, S> fmt::Debug for Intersection<'a, T, S> } } -#[stable(feature = "fused", since = "1.25.0")] +#[stable(feature = "fused", since = "1.26.0")] impl<'a, T, S> FusedIterator for Intersection<'a, T, S> where T: Eq + Hash, S: BuildHasher @@ -1244,7 +1244,7 @@ impl<'a, T, S> Iterator for Difference<'a, T, S> } } -#[stable(feature = "fused", since = "1.25.0")] +#[stable(feature = "fused", since = "1.26.0")] impl<'a, T, S> FusedIterator for Difference<'a, T, S> where T: Eq + Hash, S: BuildHasher @@ -1283,7 +1283,7 @@ impl<'a, T, S> Iterator for SymmetricDifference<'a, T, S> } } -#[stable(feature = "fused", since = "1.25.0")] +#[stable(feature = "fused", since = "1.26.0")] impl<'a, T, S> FusedIterator for SymmetricDifference<'a, T, S> where T: Eq + Hash, S: BuildHasher @@ -1307,7 +1307,7 @@ impl<'a, T, S> Clone for Union<'a, T, S> { } } -#[stable(feature = "fused", since = "1.25.0")] +#[stable(feature = "fused", since = "1.26.0")] impl<'a, T, S> FusedIterator for Union<'a, T, S> where T: Eq + Hash, S: BuildHasher diff --git a/src/libstd/path.rs b/src/libstd/path.rs index 0c54fb00d2d7..cd2af99d6ac1 100644 --- a/src/libstd/path.rs +++ b/src/libstd/path.rs @@ -905,7 +905,7 @@ impl<'a> DoubleEndedIterator for Iter<'a> { } } -#[stable(feature = "fused", since = "1.25.0")] +#[stable(feature = "fused", since = "1.26.0")] impl<'a> FusedIterator for Iter<'a> {} #[stable(feature = "rust1", since = "1.0.0")] @@ -1008,7 +1008,7 @@ impl<'a> DoubleEndedIterator for Components<'a> { } } -#[stable(feature = "fused", since = "1.25.0")] +#[stable(feature = "fused", since = "1.26.0")] impl<'a> FusedIterator for Components<'a> {} #[stable(feature = "rust1", since = "1.0.0")] @@ -1076,7 +1076,7 @@ impl<'a> Iterator for Ancestors<'a> { } } -#[unstable(feature = "fused", issue = "35602")] +#[unstable(feature = "path_ancestors", issue = "48581")] impl<'a> FusedIterator for Ancestors<'a> {} //////////////////////////////////////////////////////////////////////////////// diff --git a/src/libstd_unicode/char.rs b/src/libstd_unicode/char.rs index 2bbbf6c06559..8d3df749ed7d 100644 --- a/src/libstd_unicode/char.rs +++ b/src/libstd_unicode/char.rs @@ -70,7 +70,7 @@ impl Iterator for ToLowercase { } } -#[stable(feature = "fused", since = "1.25.0")] +#[stable(feature = "fused", since = "1.26.0")] impl FusedIterator for ToLowercase {} /// Returns an iterator that yields the uppercase equivalent of a `char`. @@ -92,7 +92,7 @@ impl Iterator for ToUppercase { } } -#[stable(feature = "fused", since = "1.25.0")] +#[stable(feature = "fused", since = "1.26.0")] impl FusedIterator for ToUppercase {} #[derive(Debug)] diff --git a/src/libstd_unicode/u_str.rs b/src/libstd_unicode/u_str.rs index ed2f205b580b..a72e1210d93f 100644 --- a/src/libstd_unicode/u_str.rs +++ b/src/libstd_unicode/u_str.rs @@ -127,7 +127,6 @@ impl Iterator for Utf16Encoder } } -#[stable(feature = "fused", since = "1.25.0")] impl FusedIterator for Utf16Encoder where I: FusedIterator {} @@ -186,5 +185,5 @@ impl<'a> DoubleEndedIterator for SplitWhitespace<'a> { } } -#[stable(feature = "fused", since = "1.25.0")] +#[stable(feature = "fused", since = "1.26.0")] impl<'a> FusedIterator for SplitWhitespace<'a> {} From fc33b2567cac0ae453807f4118872ab81a16ddf7 Mon Sep 17 00:00:00 2001 From: flip1995 Date: Sat, 3 Mar 2018 21:55:04 +0100 Subject: [PATCH 29/68] Improve getting literal representation --- src/librustc_lint/types.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs index 02aef271c37d..e778b2d38610 100644 --- a/src/librustc_lint/types.rs +++ b/src/librustc_lint/types.rs @@ -368,7 +368,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeLimits { let src = cx.sess().codemap().span_to_snippet(lit.span).ok()?; let firstch = src.chars().next()?; - if let Some(0) = char::to_digit(firstch, 10) { + if firstch == '0' { match src.chars().nth(1) { Some('x') | Some('b') => return Some(src), _ => return None, From 683bdc7f0a20236c7dd5a8a731951ef5db14b3be Mon Sep 17 00:00:00 2001 From: Shotaro Yamada Date: Sun, 4 Mar 2018 09:00:09 +0900 Subject: [PATCH 30/68] Add comments --- src/liballoc/str.rs | 58 ++++++++++++++++++++++++++++++--------------- 1 file changed, 39 insertions(+), 19 deletions(-) diff --git a/src/liballoc/str.rs b/src/liballoc/str.rs index 08ba4a180ed5..6d153bf02b3b 100644 --- a/src/liballoc/str.rs +++ b/src/liballoc/str.rs @@ -2071,35 +2071,55 @@ impl str { return String::new(); } - // n = 2^j + k (2^j > k) + // If `n` is larger than zero, it can be split as + // `n = 2^expn + rem (2^expn > rem, expn >= 0, rem >= 0)`. + // `2^expn` is the number represented by the leftmost '1' bit of `n`, + // and `rem` is the remaining part of `n`. - // 2^j: - let mut s = Vec::with_capacity(self.len() * n); - s.extend(self.as_bytes()); - let mut m = n >> 1; - while m > 0 { - let len = s.len(); - unsafe { - ptr::copy_nonoverlapping(s.as_ptr(), (s.as_mut_ptr() as *mut u8).add(len), len); - s.set_len(len * 2); + // Using `Vec` to access `set_len()`. + let mut buf = Vec::with_capacity(self.len() * n); + + // `2^expn` repetition is done by doubling `buf` `expn`-times. + buf.extend(self.as_bytes()); + { + let mut m = n >> 1; + // If `m > 0`, there are remaining bits up to the leftmost '1'. + while m > 0 { + // `buf.extend(buf)`: + unsafe { + ptr::copy_nonoverlapping( + buf.as_ptr(), + (buf.as_mut_ptr() as *mut u8).add(buf.len()), + buf.len(), + ); + // `buf` has capacity of `self.len() * n`. + let buf_len = buf.len(); + buf.set_len(buf_len * 2); + } + + m >>= 1; } - m >>= 1; } - // k: - let res_len = n * self.len(); - if res_len > s.len() { + // `rem` (`= n - 2^expn`) repetition is done by copying + // first `rem` repetitions from `buf` itself. + let rem_len = self.len() * n - buf.len(); // `self.len() * rem` + if rem_len > 0 { + // `buf.extend(buf[0 .. rem_len])`: unsafe { + // This is non-overlapping since `2^expn > rem`. ptr::copy_nonoverlapping( - s.as_ptr(), - (s.as_mut_ptr() as *mut u8).add(s.len()), - res_len - s.len(), + buf.as_ptr(), + (buf.as_mut_ptr() as *mut u8).add(buf.len()), + rem_len, ); - s.set_len(res_len); + // `buf.len() + rem_len` equals to `buf.capacity()` (`self.len() * n`). + let buf_len = buf.len(); + buf.set_len(buf_len + rem_len); } } - unsafe { String::from_utf8_unchecked(s) } + unsafe { String::from_utf8_unchecked(buf) } } /// Checks if all characters in this string are within the ASCII range. From 3d58543d49266a7ec3eb5f5f2ffaf902fce17c53 Mon Sep 17 00:00:00 2001 From: Shotaro Yamada Date: Sun, 4 Mar 2018 09:43:29 +0900 Subject: [PATCH 31/68] Avoid unnecessary calculation --- src/liballoc/str.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/liballoc/str.rs b/src/liballoc/str.rs index 6d153bf02b3b..64e815b1fbaa 100644 --- a/src/liballoc/str.rs +++ b/src/liballoc/str.rs @@ -2113,9 +2113,9 @@ impl str { (buf.as_mut_ptr() as *mut u8).add(buf.len()), rem_len, ); - // `buf.len() + rem_len` equals to `buf.capacity()` (`self.len() * n`). - let buf_len = buf.len(); - buf.set_len(buf_len + rem_len); + // `buf.len() + rem_len` equals to `buf.capacity()` (`= self.len() * n`). + let buf_cap = buf.capacity(); + buf.set_len(buf_cap); } } From 0b0e1b71d5818438f062b35b5890ce72a38f2678 Mon Sep 17 00:00:00 2001 From: "leonardo.yvens" Date: Sun, 4 Mar 2018 08:12:03 -0300 Subject: [PATCH 32/68] Refactor contrived match. --- src/librustc_mir/transform/lower_128bit.rs | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/src/librustc_mir/transform/lower_128bit.rs b/src/librustc_mir/transform/lower_128bit.rs index 981b0b854bda..83cd7bf549d5 100644 --- a/src/librustc_mir/transform/lower_128bit.rs +++ b/src/librustc_mir/transform/lower_128bit.rs @@ -77,19 +77,12 @@ impl Lower128Bit { }; let bin_statement = block.statements.pop().unwrap(); - let (source_info, place, lhs, mut rhs) = match bin_statement { - Statement { - source_info, - kind: StatementKind::Assign( - place, - Rvalue::BinaryOp(_, lhs, rhs)) - } => (source_info, place, lhs, rhs), - Statement { - source_info, - kind: StatementKind::Assign( - place, - Rvalue::CheckedBinaryOp(_, lhs, rhs)) - } => (source_info, place, lhs, rhs), + let source_info = bin_statement.source_info; + let (place, lhs, mut rhs) = match bin_statement.kind { + StatementKind::Assign(place, Rvalue::BinaryOp(_, lhs, rhs)) + | StatementKind::Assign(place, Rvalue::CheckedBinaryOp(_, lhs, rhs)) => { + (place, lhs, rhs) + } _ => bug!("Statement doesn't match pattern any more?"), }; From 1c191b209b3af4f23e4bb1c249e0f259f2ee0390 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 26 Feb 2018 15:04:40 +0100 Subject: [PATCH 33/68] Add note for unterminated raw string error --- src/libsyntax/parse/lexer/mod.rs | 33 ++++++++++++++++++++++++-------- src/test/ui/raw_string.rs | 14 ++++++++++++++ src/test/ui/raw_string.stderr | 8 ++++++++ 3 files changed, 47 insertions(+), 8 deletions(-) create mode 100644 src/test/ui/raw_string.rs create mode 100644 src/test/ui/raw_string.stderr diff --git a/src/libsyntax/parse/lexer/mod.rs b/src/libsyntax/parse/lexer/mod.rs index b5368b3ecabd..94195ccc72c4 100644 --- a/src/libsyntax/parse/lexer/mod.rs +++ b/src/libsyntax/parse/lexer/mod.rs @@ -132,6 +132,18 @@ impl<'a> StringReader<'a> { self.advance_token()?; Ok(ret_val) } + + fn fail_unterminated_raw_string(&self, pos: BytePos, hash_count: usize) { + let mut err = self.struct_span_fatal(pos, pos, "unterminated raw string"); + err.span_label(self.mk_sp(pos, pos), "unterminated raw string"); + if hash_count > 0 { + err.note(&format!("this raw string should be terminated with `\"{}`", + "#".repeat(hash_count))); + } + err.emit(); + FatalError.raise(); + } + fn fatal(&self, m: &str) -> FatalError { self.fatal_span(self.peek_span, m) } @@ -269,6 +281,15 @@ impl<'a> StringReader<'a> { Self::push_escaped_char_for_msg(&mut m, c); self.fatal_span_(from_pos, to_pos, &m[..]) } + + fn struct_span_fatal(&self, + from_pos: BytePos, + to_pos: BytePos, + m: &str) + -> DiagnosticBuilder<'a> { + self.sess.span_diagnostic.struct_span_fatal(self.mk_sp(from_pos, to_pos), m) + } + fn struct_fatal_span_char(&self, from_pos: BytePos, to_pos: BytePos, @@ -1404,8 +1425,7 @@ impl<'a> StringReader<'a> { } if self.is_eof() { - let last_bpos = self.pos; - self.fatal_span_(start_bpos, last_bpos, "unterminated raw string").raise(); + self.fail_unterminated_raw_string(start_bpos, hash_count); } else if !self.ch_is('"') { let last_bpos = self.pos; let curr_char = self.ch.unwrap(); @@ -1421,8 +1441,7 @@ impl<'a> StringReader<'a> { let mut valid = true; 'outer: loop { if self.is_eof() { - let last_bpos = self.pos; - self.fatal_span_(start_bpos, last_bpos, "unterminated raw string").raise(); + self.fail_unterminated_raw_string(start_bpos, hash_count); } // if self.ch_is('"') { // content_end_bpos = self.pos; @@ -1636,8 +1655,7 @@ impl<'a> StringReader<'a> { } if self.is_eof() { - let pos = self.pos; - self.fatal_span_(start_bpos, pos, "unterminated raw string").raise(); + self.fail_unterminated_raw_string(start_bpos, hash_count); } else if !self.ch_is('"') { let pos = self.pos; let ch = self.ch.unwrap(); @@ -1653,8 +1671,7 @@ impl<'a> StringReader<'a> { 'outer: loop { match self.ch { None => { - let pos = self.pos; - self.fatal_span_(start_bpos, pos, "unterminated raw string").raise() + self.fail_unterminated_raw_string(start_bpos, hash_count); } Some('"') => { content_end_bpos = self.pos; diff --git a/src/test/ui/raw_string.rs b/src/test/ui/raw_string.rs new file mode 100644 index 000000000000..f1eb91d44fda --- /dev/null +++ b/src/test/ui/raw_string.rs @@ -0,0 +1,14 @@ +// Copyright 2018 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 = r##"lol"#; + //~^ ERROR unterminated raw string +} diff --git a/src/test/ui/raw_string.stderr b/src/test/ui/raw_string.stderr new file mode 100644 index 000000000000..b8aa596ef953 --- /dev/null +++ b/src/test/ui/raw_string.stderr @@ -0,0 +1,8 @@ +error: unterminated raw string + --> $DIR/raw_string.rs:12:13 + | +LL | let x = r##"lol"#; + | ^ unterminated raw string + | + = note: this raw string should be terminated with `"##` + From 16ac85ce4dce1e185f2e6ce27df3833e07a9e502 Mon Sep 17 00:00:00 2001 From: debris Date: Sun, 4 Mar 2018 14:58:10 +0100 Subject: [PATCH 34/68] Remove useless powerpc64 entry from ARCH_TABLE, closes #47737 --- src/test/codegen/abi-main-signature-16bit-c-int.rs | 1 - src/test/codegen/fastcall-inreg.rs | 2 -- src/test/codegen/global_asm.rs | 2 -- src/test/codegen/global_asm_include.rs | 2 -- src/test/codegen/global_asm_x2.rs | 2 -- src/test/codegen/repr-transparent-aggregates-1.rs | 1 - src/tools/compiletest/src/util.rs | 1 - 7 files changed, 11 deletions(-) diff --git a/src/test/codegen/abi-main-signature-16bit-c-int.rs b/src/test/codegen/abi-main-signature-16bit-c-int.rs index fbe2fd10e7a1..1e02fe4befdf 100644 --- a/src/test/codegen/abi-main-signature-16bit-c-int.rs +++ b/src/test/codegen/abi-main-signature-16bit-c-int.rs @@ -18,7 +18,6 @@ // ignore-hexagon // ignore-mips // ignore-powerpc -// ignore-powerpc64 // ignore-s390x // ignore-sparc // ignore-wasm32 diff --git a/src/test/codegen/fastcall-inreg.rs b/src/test/codegen/fastcall-inreg.rs index 346c5da8d1b8..b24899cc363a 100644 --- a/src/test/codegen/fastcall-inreg.rs +++ b/src/test/codegen/fastcall-inreg.rs @@ -25,8 +25,6 @@ // ignore-mips64 // ignore-mips64el // ignore-msp430 -// ignore-powerpc64 -// ignore-powerpc64le // ignore-powerpc // ignore-r600 // ignore-amdgcn diff --git a/src/test/codegen/global_asm.rs b/src/test/codegen/global_asm.rs index 5bd0c1b4076e..5661592d0c7b 100644 --- a/src/test/codegen/global_asm.rs +++ b/src/test/codegen/global_asm.rs @@ -21,8 +21,6 @@ // ignore-mips64 // ignore-mips64el // ignore-msp430 -// ignore-powerpc64 -// ignore-powerpc64le // ignore-powerpc // ignore-r600 // ignore-amdgcn diff --git a/src/test/codegen/global_asm_include.rs b/src/test/codegen/global_asm_include.rs index 401b1fad566d..d8b5db12404a 100644 --- a/src/test/codegen/global_asm_include.rs +++ b/src/test/codegen/global_asm_include.rs @@ -21,8 +21,6 @@ // ignore-mips64 // ignore-mips64el // ignore-msp430 -// ignore-powerpc64 -// ignore-powerpc64le // ignore-powerpc // ignore-r600 // ignore-amdgcn diff --git a/src/test/codegen/global_asm_x2.rs b/src/test/codegen/global_asm_x2.rs index 8b59165e9e61..caa0506550dd 100644 --- a/src/test/codegen/global_asm_x2.rs +++ b/src/test/codegen/global_asm_x2.rs @@ -21,8 +21,6 @@ // ignore-mips64 // ignore-mips64el // ignore-msp430 -// ignore-powerpc64 -// ignore-powerpc64le // ignore-powerpc // ignore-r600 // ignore-amdgcn diff --git a/src/test/codegen/repr-transparent-aggregates-1.rs b/src/test/codegen/repr-transparent-aggregates-1.rs index 2eeed2b788ce..655e67cf7eef 100644 --- a/src/test/codegen/repr-transparent-aggregates-1.rs +++ b/src/test/codegen/repr-transparent-aggregates-1.rs @@ -14,7 +14,6 @@ // ignore-mips // ignore-mips64 // ignore-powerpc -// ignore-powerpc64 // See repr-transparent.rs #![crate_type="lib"] diff --git a/src/tools/compiletest/src/util.rs b/src/tools/compiletest/src/util.rs index 3c9dae915b5a..cf63cb2e5d90 100644 --- a/src/tools/compiletest/src/util.rs +++ b/src/tools/compiletest/src/util.rs @@ -43,7 +43,6 @@ const ARCH_TABLE: &'static [(&'static str, &'static str)] = &[ ("mips", "mips"), ("msp430", "msp430"), ("powerpc", "powerpc"), - ("powerpc64", "powerpc64"), ("s390x", "s390x"), ("sparc", "sparc"), ("x86_64", "x86_64"), From 2f2ac9ac47862621774a9e7fa6b6396e14f8b8c7 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Sun, 4 Mar 2018 12:13:21 -0800 Subject: [PATCH 35/68] Include stdsimd in rust-src component Closes #48734 --- src/bootstrap/dist.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index 576e50782474..aa0a7c52246b 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -810,6 +810,7 @@ impl Step for Src { "src/libterm", "src/jemalloc", "src/libprofiler_builtins", + "src/stdsimd", ]; let std_src_dirs_exclude = [ "src/libcompiler_builtins/compiler-rt/test", From 542bc75deaaf4e84dcd7a196685bc1a1cb100d32 Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Wed, 14 Feb 2018 16:11:02 +0100 Subject: [PATCH 36/68] Turn features() into a query. --- src/librustc/dep_graph/dep_node.rs | 10 +-- src/librustc/hir/lowering.rs | 8 +-- src/librustc/ich/impls_syntax.rs | 19 ++++++ src/librustc/infer/error_reporting/mod.rs | 4 +- src/librustc/middle/stability.rs | 14 ++-- src/librustc/session/mod.rs | 66 ++++++------------- src/librustc/traits/specialize/mod.rs | 2 +- src/librustc/ty/context.rs | 64 ++++++++++++++++-- src/librustc/ty/maps/config.rs | 6 ++ src/librustc/ty/maps/mod.rs | 8 +++ src/librustc/ty/maps/plumbing.rs | 1 + src/librustc/ty/mod.rs | 2 +- src/librustc_borrowck/borrowck/mod.rs | 2 +- src/librustc_const_eval/_match.rs | 4 +- src/librustc_const_eval/check_match.rs | 2 +- src/librustc_const_eval/eval.rs | 2 +- src/librustc_driver/driver.rs | 12 ++-- src/librustc_incremental/assert_dep_graph.rs | 2 +- .../persist/dirty_clean.rs | 2 +- src/librustc_lint/builtin.rs | 2 +- src/librustc_lint/unused.rs | 2 +- src/librustc_metadata/native_libs.rs | 4 +- .../borrow_check/error_reporting.rs | 4 +- src/librustc_mir/borrow_check/mod.rs | 10 +-- .../borrow_check/nll/type_check/mod.rs | 2 +- src/librustc_mir/build/cfg.rs | 2 +- src/librustc_mir/build/matches/simplify.rs | 2 +- .../transform/clean_end_regions.rs | 2 +- src/librustc_mir/transform/qualify_consts.rs | 2 +- src/librustc_mir/util/borrowck_errors.rs | 2 +- src/librustc_plugin/load.rs | 2 +- src/librustc_resolve/build_reduced_graph.rs | 2 +- src/librustc_resolve/lib.rs | 6 +- src/librustc_resolve/macros.rs | 4 +- src/librustc_resolve/resolve_imports.rs | 2 +- src/librustc_trans_utils/symbol_names_test.rs | 2 +- src/librustc_typeck/astconv.rs | 2 +- src/librustc_typeck/check/_match.rs | 2 +- src/librustc_typeck/check/coercion.rs | 2 +- src/librustc_typeck/check/method/probe.rs | 2 +- src/librustc_typeck/check/mod.rs | 4 +- src/librustc_typeck/check/wfcheck.rs | 2 +- src/librustc_typeck/coherence/mod.rs | 2 +- src/librustc_typeck/collect.rs | 6 +- src/librustc_typeck/lib.rs | 2 +- src/librustdoc/test.rs | 2 +- src/libsyntax/ext/tt/macro_rules.rs | 17 +++-- src/libsyntax/ext/tt/quoted.rs | 15 ++--- src/libsyntax/feature_gate.rs | 7 ++ 49 files changed, 207 insertions(+), 140 deletions(-) diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs index aa678ba788a5..5f6a7c452c4c 100644 --- a/src/librustc/dep_graph/dep_node.rs +++ b/src/librustc/dep_graph/dep_node.rs @@ -436,6 +436,9 @@ impl DepKind { } define_dep_nodes!( <'tcx> + // We use this for most things when incr. comp. is turned off. + [] Null, + // 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 @@ -605,8 +608,8 @@ define_dep_nodes!( <'tcx> [input] MissingExternCrateItem(CrateNum), [input] UsedCrateSource(CrateNum), [input] PostorderCnums, - [input] HasCloneClosures(CrateNum), - [input] HasCopyClosures(CrateNum), + [] HasCloneClosures(CrateNum), + [] HasCopyClosures(CrateNum), // This query is not expected to have inputs -- as a result, it's // not a good candidate for "replay" because it's essentially a @@ -630,8 +633,6 @@ define_dep_nodes!( <'tcx> [] CompileCodegenUnit(InternedString), [input] OutputFilenames, [anon] NormalizeTy, - // We use this for most things when incr. comp. is turned off. - [] Null, [] SubstituteNormalizeAndTestPredicates { key: (DefId, &'tcx Substs<'tcx>) }, @@ -642,6 +643,7 @@ define_dep_nodes!( <'tcx> [] GetSymbolExportLevel(DefId), + [input] Features, ); trait DepNodeParams<'a, 'gcx: 'tcx + 'a, 'tcx: 'a> : fmt::Debug { diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index fa745bf16557..877027a21a22 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -550,7 +550,7 @@ impl<'a> LoweringContext<'a> { { assert!(!self.is_collecting_in_band_lifetimes); assert!(self.lifetimes_to_define.is_empty()); - self.is_collecting_in_band_lifetimes = self.sess.features.borrow().in_band_lifetimes; + self.is_collecting_in_band_lifetimes = self.sess.features_untracked().in_band_lifetimes; assert!(self.in_band_ty_params.is_empty()); @@ -964,7 +964,7 @@ impl<'a> LoweringContext<'a> { let span = t.span; match itctx { ImplTraitContext::Existential => { - let has_feature = self.sess.features.borrow().conservative_impl_trait; + let has_feature = self.sess.features_untracked().conservative_impl_trait; if !t.span.allows_unstable() && !has_feature { emit_feature_err(&self.sess.parse_sess, "conservative_impl_trait", t.span, GateIssue::Language, @@ -988,7 +988,7 @@ impl<'a> LoweringContext<'a> { }, lifetimes) }, ImplTraitContext::Universal(def_id) => { - let has_feature = self.sess.features.borrow().universal_impl_trait; + let has_feature = self.sess.features_untracked().universal_impl_trait; if !t.span.allows_unstable() && !has_feature { emit_feature_err(&self.sess.parse_sess, "universal_impl_trait", t.span, GateIssue::Language, @@ -3713,7 +3713,7 @@ impl<'a> LoweringContext<'a> { } fn maybe_lint_bare_trait(&self, span: Span, id: NodeId, is_global: bool) { - if self.sess.features.borrow().dyn_trait { + if self.sess.features_untracked().dyn_trait { self.sess.buffer_lint_with_diagnostic( builtin::BARE_TRAIT_OBJECT, id, span, "trait objects without an explicit `dyn` are deprecated", diff --git a/src/librustc/ich/impls_syntax.rs b/src/librustc/ich/impls_syntax.rs index c31a5c9d86d7..f935cbfcde99 100644 --- a/src/librustc/ich/impls_syntax.rs +++ b/src/librustc/ich/impls_syntax.rs @@ -17,6 +17,7 @@ use std::hash as std_hash; use std::mem; use syntax::ast; +use syntax::feature_gate; use syntax::parse::token; use syntax::symbol::InternedString; use syntax::tokenstream; @@ -460,3 +461,21 @@ fn stable_non_narrow_char(swc: ::syntax_pos::NonNarrowChar, (pos.0 - filemap_start.0, width as u32) } + + + +impl<'gcx> HashStable> for feature_gate::Features { + fn hash_stable(&self, + hcx: &mut StableHashingContext<'gcx>, + hasher: &mut StableHasher) { + // Unfortunately we cannot exhaustively list fields here, since the + // struct is macro generated. + self.declared_stable_lang_features.hash_stable(hcx, hasher); + self.declared_lib_features.hash_stable(hcx, hasher); + + self.walk_feature_fields(|feature_name, value| { + feature_name.hash_stable(hcx, hasher); + value.hash_stable(hcx, hasher); + }); + } +} diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index 37a84361aea2..559b2720076f 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -289,11 +289,11 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { ) { debug!("report_region_errors(): {} errors to start", errors.len()); - if will_later_be_reported_by_nll && self.tcx.sess.nll() { + if will_later_be_reported_by_nll && self.tcx.nll() { // With `#![feature(nll)]`, we want to present a nice user // experience, so don't even mention the errors from the // AST checker. - if self.tcx.sess.features.borrow().nll { + if self.tcx.features().nll { return; } diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs index e80ea16f565a..16c33d6bd837 100644 --- a/src/librustc/middle/stability.rs +++ b/src/librustc/middle/stability.rs @@ -131,7 +131,7 @@ impl<'a, 'tcx: 'a> Annotator<'a, 'tcx> { item_sp: Span, kind: AnnotationKind, visit_children: F) where F: FnOnce(&mut Self) { - if self.tcx.sess.features.borrow().staged_api { + if self.tcx.features().staged_api { // This crate explicitly wants staged API. debug!("annotate(id = {:?}, attrs = {:?})", id, attrs); if let Some(..) = attr::find_deprecation(self.tcx.sess.diagnostic(), attrs, item_sp) { @@ -398,7 +398,7 @@ impl<'a, 'tcx> Index<'tcx> { pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Index<'tcx> { let is_staged_api = tcx.sess.opts.debugging_opts.force_unstable_if_unmarked || - tcx.sess.features.borrow().staged_api; + tcx.features().staged_api; let mut staged_api = FxHashMap(); staged_api.insert(LOCAL_CRATE, is_staged_api); let mut index = Index { @@ -408,7 +408,7 @@ impl<'a, 'tcx> Index<'tcx> { active_features: FxHashSet(), }; - let ref active_lib_features = tcx.sess.features.borrow().declared_lib_features; + let ref active_lib_features = tcx.features().declared_lib_features; // Put the active features into a map for quick lookup index.active_features = active_lib_features.iter().map(|&(ref s, _)| s.clone()).collect(); @@ -677,7 +677,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> { // There's no good place to insert stability check for non-Copy unions, // so semi-randomly perform it here in stability.rs - hir::ItemUnion(..) if !self.tcx.sess.features.borrow().untagged_unions => { + hir::ItemUnion(..) if !self.tcx.features().untagged_unions => { let def_id = self.tcx.hir.local_def_id(item.id); let adt_def = self.tcx.adt_def(def_id); let ty = self.tcx.type_of(def_id); @@ -721,8 +721,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { /// were expected to be library features), and the list of features used from /// libraries, identify activated features that don't exist and error about them. pub fn check_unused_or_stable_features<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { - let sess = &tcx.sess; - let access_levels = &tcx.privacy_access_levels(LOCAL_CRATE); if tcx.stability().staged_api[&LOCAL_CRATE] { @@ -736,12 +734,12 @@ pub fn check_unused_or_stable_features<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { krate.visit_all_item_likes(&mut missing.as_deep_visitor()); } - let ref declared_lib_features = sess.features.borrow().declared_lib_features; + let ref declared_lib_features = tcx.features().declared_lib_features; let mut remaining_lib_features: FxHashMap = declared_lib_features.clone().into_iter().collect(); remaining_lib_features.remove(&Symbol::intern("proc_macro")); - for &(ref stable_lang_feature, span) in &sess.features.borrow().declared_stable_lang_features { + for &(ref stable_lang_feature, span) in &tcx.features().declared_stable_lang_features { let version = find_lang_feature_accepted_version(&stable_lang_feature.as_str()) .expect("unexpectedly couldn't find version feature was stabilized"); tcx.lint_node(lint::builtin::STABLE_FEATURES, diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs index bd87a8f918ab..f6da4b55301e 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -20,7 +20,7 @@ use lint::builtin::BuiltinLintDiagnostics; use middle::allocator::AllocatorKind; use middle::dependency_format; use session::search_paths::PathKind; -use session::config::{BorrowckMode, DebugInfoLevel, OutputType, Epoch}; +use session::config::{DebugInfoLevel, OutputType, Epoch}; use ty::tls; use util::nodemap::{FxHashMap, FxHashSet}; use util::common::{duration_to_secs_str, ErrorReported}; @@ -93,7 +93,8 @@ pub struct Session { /// multiple crates with the same name to coexist. See the /// trans::back::symbol_names module for more information. pub crate_disambiguator: RefCell>, - pub features: RefCell, + + features: RefCell>, /// The maximum recursion limit for potentially infinitely recursive /// operations such as auto-dereference and monomorphization. @@ -194,6 +195,7 @@ impl Session { None => bug!("accessing disambiguator before initialization"), } } + pub fn struct_span_warn<'a, S: Into>(&'a self, sp: S, msg: &str) @@ -456,16 +458,22 @@ impl Session { self.opts.debugging_opts.print_llvm_passes } - /// If true, we should use NLL-style region checking instead of - /// lexical style. - pub fn nll(&self) -> bool { - self.features.borrow().nll || self.opts.debugging_opts.nll + /// Get the features enabled for the current compilation session. Do not use + /// DO NOT USE THIS METHOD if there is a TyCtxt available, as it circumvents + /// dependency tracking. Use tcx.features() instead. + #[inline] + pub fn features_untracked(&self) -> cell::Ref { + let features = self.features.borrow(); + + if features.is_none() { + bug!("Access to Session::features before it is initialized"); + } + + cell::Ref::map(features, |r| r.as_ref().unwrap()) } - /// If true, we should use the MIR-based borrowck (we may *also* use - /// the AST-based borrowck). - pub fn use_mir(&self) -> bool { - self.borrowck_mode().use_mir() + pub fn init_features(&self, features: feature_gate::Features) { + *(self.features.borrow_mut()) = Some(features); } /// If true, we should gather causal information during NLL @@ -475,42 +483,6 @@ impl Session { self.opts.debugging_opts.nll_dump_cause } - /// If true, we should enable two-phase borrows checks. This is - /// done with either `-Ztwo-phase-borrows` or with - /// `#![feature(nll)]`. - pub fn two_phase_borrows(&self) -> bool { - self.features.borrow().nll || self.opts.debugging_opts.two_phase_borrows - } - - /// What mode(s) of borrowck should we run? AST? MIR? both? - /// (Also considers the `#![feature(nll)]` setting.) - pub fn borrowck_mode(&self) -> BorrowckMode { - match self.opts.borrowck_mode { - mode @ BorrowckMode::Mir | - mode @ BorrowckMode::Compare => mode, - - mode @ BorrowckMode::Ast => { - if self.nll() { - BorrowckMode::Mir - } else { - mode - } - } - - } - } - - /// Should we emit EndRegion MIR statements? These are consumed by - /// MIR borrowck, but not when NLL is used. They are also consumed - /// by the validation stuff. - pub fn emit_end_regions(&self) -> bool { - // FIXME(#46875) -- we should not emit end regions when NLL is enabled, - // but for now we can't stop doing so because it causes false positives - self.opts.debugging_opts.emit_end_regions || - self.opts.debugging_opts.mir_emit_validate > 0 || - self.use_mir() - } - /// Calculates the flavor of LTO to use for this compilation. pub fn lto(&self) -> config::Lto { // If our target has codegen requirements ignore the command line @@ -1029,7 +1001,7 @@ pub fn build_session_(sopts: config::Options, crate_types: RefCell::new(Vec::new()), dependency_formats: RefCell::new(FxHashMap()), crate_disambiguator: RefCell::new(None), - features: RefCell::new(feature_gate::Features::new()), + features: RefCell::new(None), recursion_limit: Cell::new(64), type_length_limit: Cell::new(1048576), next_node_id: Cell::new(NodeId::new(1)), diff --git a/src/librustc/traits/specialize/mod.rs b/src/librustc/traits/specialize/mod.rs index 43940d7cea3e..d11565618a68 100644 --- a/src/librustc/traits/specialize/mod.rs +++ b/src/librustc/traits/specialize/mod.rs @@ -164,7 +164,7 @@ pub(super) fn specializes<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // The feature gate should prevent introducing new specializations, but not // taking advantage of upstream ones. - if !tcx.sess.features.borrow().specialization && + if !tcx.features().specialization && (impl1_def_id.is_local() || impl2_def_id.is_local()) { return false; } diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index d04c47710173..a7f065d57aee 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -14,7 +14,7 @@ use dep_graph::DepGraph; use dep_graph::{DepNode, DepConstructor}; use errors::DiagnosticBuilder; use session::Session; -use session::config::OutputFilenames; +use session::config::{BorrowckMode, OutputFilenames}; use middle; use hir::{TraitCandidate, HirId, ItemLocalId}; use hir::def::{Def, Export}; @@ -71,6 +71,7 @@ use syntax::abi; use syntax::ast::{self, Name, NodeId}; use syntax::attr; use syntax::codemap::MultiSpan; +use syntax::feature_gate; use syntax::symbol::{Symbol, keywords}; use syntax_pos::Span; @@ -1255,6 +1256,10 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { self.all_crate_nums(LOCAL_CRATE) } + pub fn features(self) -> Lrc { + self.features_query(LOCAL_CRATE) + } + pub fn def_key(self, id: DefId) -> hir_map::DefKey { if id.is_local() { self.hir.def_key(id) @@ -1362,6 +1367,53 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { self.on_disk_query_result_cache.serialize(self.global_tcx(), encoder) } + /// If true, we should use NLL-style region checking instead of + /// lexical style. + pub fn nll(self) -> bool { + self.features().nll || self.sess.opts.debugging_opts.nll + } + + /// If true, we should use the MIR-based borrowck (we may *also* use + /// the AST-based borrowck). + pub fn use_mir(self) -> bool { + self.borrowck_mode().use_mir() + } + + /// If true, we should enable two-phase borrows checks. This is + /// done with either `-Ztwo-phase-borrows` or with + /// `#![feature(nll)]`. + pub fn two_phase_borrows(self) -> bool { + self.features().nll || self.sess.opts.debugging_opts.two_phase_borrows + } + + /// What mode(s) of borrowck should we run? AST? MIR? both? + /// (Also considers the `#![feature(nll)]` setting.) + pub fn borrowck_mode(&self) -> BorrowckMode { + match self.sess.opts.borrowck_mode { + mode @ BorrowckMode::Mir | + mode @ BorrowckMode::Compare => mode, + + mode @ BorrowckMode::Ast => { + if self.nll() { + BorrowckMode::Mir + } else { + mode + } + } + + } + } + + /// Should we emit EndRegion MIR statements? These are consumed by + /// MIR borrowck, but not when NLL is used. They are also consumed + /// by the validation stuff. + pub fn emit_end_regions(self) -> bool { + // FIXME(#46875) -- we should not emit end regions when NLL is enabled, + // but for now we can't stop doing so because it causes false positives + self.sess.opts.debugging_opts.emit_end_regions || + self.sess.opts.debugging_opts.mir_emit_validate > 0 || + self.use_mir() + } } impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> { @@ -2020,7 +2072,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } pub fn mk_diverging_default(self) -> Ty<'tcx> { - if self.sess.features.borrow().never_type { + if self.features().never_type { self.types.never } else { self.intern_tup(&[], true) @@ -2395,13 +2447,17 @@ pub fn provide(providers: &mut ty::maps::Providers) { }; providers.has_copy_closures = |tcx, cnum| { assert_eq!(cnum, LOCAL_CRATE); - tcx.sess.features.borrow().copy_closures + tcx.features().copy_closures }; providers.has_clone_closures = |tcx, cnum| { assert_eq!(cnum, LOCAL_CRATE); - tcx.sess.features.borrow().clone_closures + tcx.features().clone_closures }; providers.fully_normalize_monormophic_ty = |tcx, ty| { tcx.fully_normalize_associated_types_in(&ty) }; + providers.features_query = |tcx, cnum| { + assert_eq!(cnum, LOCAL_CRATE); + Lrc::new(tcx.sess.features_untracked().clone()) + }; } diff --git a/src/librustc/ty/maps/config.rs b/src/librustc/ty/maps/config.rs index eb07876b05f2..c91b30440e5e 100644 --- a/src/librustc/ty/maps/config.rs +++ b/src/librustc/ty/maps/config.rs @@ -593,6 +593,12 @@ impl<'tcx> QueryDescription<'tcx> for queries::fully_normalize_monormophic_ty<'t } } +impl<'tcx> QueryDescription<'tcx> for queries::features_query<'tcx> { + fn describe(_tcx: TyCtxt, _: CrateNum) -> String { + format!("looking up enabled feature gates") + } +} + impl<'tcx> QueryDescription<'tcx> for queries::typeck_tables_of<'tcx> { #[inline] fn cache_on_disk(def_id: Self::Key) -> bool { diff --git a/src/librustc/ty/maps/mod.rs b/src/librustc/ty/maps/mod.rs index 6edb1d9be35d..c211713db6bc 100644 --- a/src/librustc/ty/maps/mod.rs +++ b/src/librustc/ty/maps/mod.rs @@ -52,6 +52,7 @@ use syntax_pos::{Span, DUMMY_SP}; use syntax_pos::symbol::InternedString; use syntax::attr; use syntax::ast; +use syntax::feature_gate; use syntax::symbol::Symbol; #[macro_use] @@ -374,12 +375,19 @@ define_maps! { <'tcx> // Get an estimate of the size of an InstanceDef based on its MIR for CGU partitioning. [] fn instance_def_size_estimate: instance_def_size_estimate_dep_node(ty::InstanceDef<'tcx>) -> usize, + + [] fn features_query: features_node(CrateNum) -> Lrc, } ////////////////////////////////////////////////////////////////////// // These functions are little shims used to find the dep-node for a // given query when there is not a *direct* mapping: + +fn features_node<'tcx>(_: CrateNum) -> DepConstructor<'tcx> { + DepConstructor::Features +} + fn erase_regions_ty<'tcx>(ty: Ty<'tcx>) -> DepConstructor<'tcx> { DepConstructor::EraseRegionsTy { ty } } diff --git a/src/librustc/ty/maps/plumbing.rs b/src/librustc/ty/maps/plumbing.rs index b654b6bc42a1..3443b9b61b21 100644 --- a/src/librustc/ty/maps/plumbing.rs +++ b/src/librustc/ty/maps/plumbing.rs @@ -936,6 +936,7 @@ pub fn force_from_dep_node<'a, 'gcx, 'lcx>(tcx: TyCtxt<'a, 'gcx, 'lcx>, DepKind::TargetFeaturesEnabled => { force!(target_features_enabled, def_id!()); } DepKind::GetSymbolExportLevel => { force!(symbol_export_level, def_id!()); } + DepKind::Features => { force!(features_query, LOCAL_CRATE); } } true diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 9ba33a57c205..f6f4e1ceb156 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -2335,7 +2335,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { /// Returns true if the impls are the same polarity and are implementing /// a trait which contains no items pub fn impls_are_allowed_to_overlap(self, def_id1: DefId, def_id2: DefId) -> bool { - if !self.sess.features.borrow().overlapping_marker_traits { + if !self.features().overlapping_marker_traits { return false; } let trait1_is_empty = self.impl_trait_ref(def_id1) diff --git a/src/librustc_borrowck/borrowck/mod.rs b/src/librustc_borrowck/borrowck/mod.rs index 4fe6ee45295a..bb198adea4a6 100644 --- a/src/librustc_borrowck/borrowck/mod.rs +++ b/src/librustc_borrowck/borrowck/mod.rs @@ -276,7 +276,7 @@ impl<'b, 'tcx: 'b> BorrowckErrors for BorrowckCtxt<'b, 'tcx> { o: Origin) -> DiagnosticBuilder<'a> { - if !o.should_emit_errors(self.tcx.sess.borrowck_mode()) { + if !o.should_emit_errors(self.tcx.borrowck_mode()) { self.tcx.sess.diagnostic().cancel(&mut diag); } diag diff --git a/src/librustc_const_eval/_match.rs b/src/librustc_const_eval/_match.rs index 54e3418d4f01..8e3b99f2dbfe 100644 --- a/src/librustc_const_eval/_match.rs +++ b/src/librustc_const_eval/_match.rs @@ -201,7 +201,7 @@ impl<'a, 'tcx> MatchCheckCtxt<'a, 'tcx> { } fn is_uninhabited(&self, ty: Ty<'tcx>) -> bool { - if self.tcx.sess.features.borrow().never_type { + if self.tcx.features().never_type { self.tcx.is_ty_uninhabited_from(self.module, ty) } else { false @@ -227,7 +227,7 @@ impl<'a, 'tcx> MatchCheckCtxt<'a, 'tcx> { substs: &'tcx ty::subst::Substs<'tcx>) -> bool { - if self.tcx.sess.features.borrow().never_type { + if self.tcx.features().never_type { self.tcx.is_enum_variant_uninhabited_from(self.module, variant, substs) } else { false diff --git a/src/librustc_const_eval/check_match.rs b/src/librustc_const_eval/check_match.rs index ae53ed0e1140..6f7143c185cb 100644 --- a/src/librustc_const_eval/check_match.rs +++ b/src/librustc_const_eval/check_match.rs @@ -212,7 +212,7 @@ impl<'a, 'tcx> MatchVisitor<'a, 'tcx> { let pat_ty = self.tables.node_id_to_type(scrut.hir_id); let module = self.tcx.hir.get_module_parent(scrut.id); if inlined_arms.is_empty() { - let scrutinee_is_uninhabited = if self.tcx.sess.features.borrow().never_type { + let scrutinee_is_uninhabited = if self.tcx.features().never_type { self.tcx.is_ty_uninhabited_from(module, pat_ty) } else { self.conservative_is_uninhabited(pat_ty) diff --git a/src/librustc_const_eval/eval.rs b/src/librustc_const_eval/eval.rs index 8e4ec93c14ba..2a571fa82643 100644 --- a/src/librustc_const_eval/eval.rs +++ b/src/librustc_const_eval/eval.rs @@ -398,7 +398,7 @@ fn eval_const_expr_partial<'a, 'tcx>(cx: &ConstContext<'a, 'tcx>, }).collect::, _>>()?)))) } hir::ExprIndex(ref arr, ref idx) => { - if !tcx.sess.features.borrow().const_indexing { + if !tcx.features().const_indexing { signal!(e, IndexOpFeatureGated); } let arr = cx.eval(arr)?; diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index 15afea192138..571cc46bc641 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -650,7 +650,7 @@ pub fn phase_2_configure_and_expand_inner<'a, F>(sess: &'a Session, let (mut krate, features) = syntax::config::features(krate, &sess.parse_sess, sess.opts.test); // these need to be set "early" so that expansion sees `quote` if enabled. - *sess.features.borrow_mut() = features; + sess.init_features(features); *sess.crate_types.borrow_mut() = collect_crate_types(sess, &krate.attrs); @@ -699,7 +699,7 @@ pub fn phase_2_configure_and_expand_inner<'a, F>(sess: &'a Session, let mut registry = registry.unwrap_or(Registry::new(sess, krate.span)); time(time_passes, "plugin registration", || { - if sess.features.borrow().rustc_diagnostic_macros { + if sess.features_untracked().rustc_diagnostic_macros { registry.register_macro("__diagnostic_used", diagnostics::plugin::expand_diagnostic_used); registry.register_macro("__register_diagnostic", @@ -749,7 +749,7 @@ pub fn phase_2_configure_and_expand_inner<'a, F>(sess: &'a Session, crate_loader, &resolver_arenas); resolver.whitelisted_legacy_custom_derives = whitelisted_legacy_custom_derives; - syntax_ext::register_builtins(&mut resolver, syntax_exts, sess.features.borrow().quote); + syntax_ext::register_builtins(&mut resolver, syntax_exts, sess.features_untracked().quote); krate = time(time_passes, "expansion", || { // Windows dlls do not have rpaths, so they don't know how to find their @@ -780,7 +780,7 @@ pub fn phase_2_configure_and_expand_inner<'a, F>(sess: &'a Session, .filter(|p| env::join_paths(iter::once(p)).is_ok())) .unwrap()); } - let features = sess.features.borrow(); + let features = sess.features_untracked(); let cfg = syntax::ext::expand::ExpansionConfig { features: Some(&features), recursion_limit: sess.recursion_limit.get(), @@ -819,7 +819,7 @@ pub fn phase_2_configure_and_expand_inner<'a, F>(sess: &'a Session, sess.opts.test, krate, sess.diagnostic(), - &sess.features.borrow()) + &sess.features_untracked()) }); // If we're actually rustdoc then there's no need to actually compile @@ -886,7 +886,7 @@ pub fn phase_2_configure_and_expand_inner<'a, F>(sess: &'a Session, sess.track_errors(|| { syntax::feature_gate::check_crate(&krate, &sess.parse_sess, - &sess.features.borrow(), + &sess.features_untracked(), &attributes, sess.opts.unstable_features); }) diff --git a/src/librustc_incremental/assert_dep_graph.rs b/src/librustc_incremental/assert_dep_graph.rs index 5976b80d90f8..17a6176b79e9 100644 --- a/src/librustc_incremental/assert_dep_graph.rs +++ b/src/librustc_incremental/assert_dep_graph.rs @@ -69,7 +69,7 @@ pub fn assert_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { // if the `rustc_attrs` feature is not enabled, then the // attributes we are interested in cannot be present anyway, so // skip the walk. - if !tcx.sess.features.borrow().rustc_attrs { + if !tcx.features().rustc_attrs { return; } diff --git a/src/librustc_incremental/persist/dirty_clean.rs b/src/librustc_incremental/persist/dirty_clean.rs index c3e283535ec8..e114606a6311 100644 --- a/src/librustc_incremental/persist/dirty_clean.rs +++ b/src/librustc_incremental/persist/dirty_clean.rs @@ -219,7 +219,7 @@ impl Assertion { pub fn check_dirty_clean_annotations<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { // can't add `#[rustc_dirty]` etc without opting in to this feature - if !tcx.sess.features.borrow().rustc_attrs { + if !tcx.features().rustc_attrs { return; } diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index 66f34a72edf2..62ac898337ca 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -1356,7 +1356,7 @@ impl UnreachablePub { // visibility is token at start of declaration (can be macro // variable rather than literal `pub`) let pub_span = cx.tcx.sess.codemap().span_until_char(def_span, ' '); - let replacement = if cx.tcx.sess.features.borrow().crate_visibility_modifier { + let replacement = if cx.tcx.features().crate_visibility_modifier { "crate" } else { "pub(crate)" diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs index 439533fae49d..6ab3172c4fef 100644 --- a/src/librustc_lint/unused.rs +++ b/src/librustc_lint/unused.rs @@ -72,7 +72,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedResults { let mut fn_warned = false; let mut op_warned = false; - if cx.tcx.sess.features.borrow().fn_must_use { + if cx.tcx.features().fn_must_use { let maybe_def = match expr.node { hir::ExprCall(ref callee, _) => { match callee.node { diff --git a/src/librustc_metadata/native_libs.rs b/src/librustc_metadata/native_libs.rs index c0ce32cc9706..2504f8dc251f 100644 --- a/src/librustc_metadata/native_libs.rs +++ b/src/librustc_metadata/native_libs.rs @@ -146,7 +146,7 @@ impl<'a, 'tcx> Collector<'a, 'tcx> { None => self.tcx.sess.err(msg), } } - if lib.cfg.is_some() && !self.tcx.sess.features.borrow().link_cfg { + if lib.cfg.is_some() && !self.tcx.features().link_cfg { feature_gate::emit_feature_err(&self.tcx.sess.parse_sess, "link_cfg", span.unwrap(), @@ -154,7 +154,7 @@ impl<'a, 'tcx> Collector<'a, 'tcx> { "is feature gated"); } if lib.kind == cstore::NativeStaticNobundle && - !self.tcx.sess.features.borrow().static_nobundle { + !self.tcx.features().static_nobundle { feature_gate::emit_feature_err(&self.tcx.sess.parse_sess, "static_nobundle", span.unwrap(), diff --git a/src/librustc_mir/borrow_check/error_reporting.rs b/src/librustc_mir/borrow_check/error_reporting.rs index c6635d59154e..b77e7cf2ec8b 100644 --- a/src/librustc_mir/borrow_check/error_reporting.rs +++ b/src/librustc_mir/borrow_check/error_reporting.rs @@ -535,7 +535,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { err.span_label(borrow_span, "borrowed value does not live long enough"); err.span_label(drop_span, "borrowed value only lives until here"); - if !self.tcx.sess.nll() { + if !self.tcx.nll() { self.tcx.note_and_explain_region( scope_tree, &mut err, @@ -572,7 +572,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { err.span_label(proper_span, "temporary value does not live long enough"); err.span_label(drop_span, "temporary value only lives until here"); - if !self.tcx.sess.nll() { + if !self.tcx.nll() { self.tcx.note_and_explain_region( scope_tree, &mut err, diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index c6ed971f767c..1ff0ffaaa68b 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -72,7 +72,7 @@ fn mir_borrowck<'a, 'tcx>( let input_mir = tcx.mir_validated(def_id); debug!("run query mir_borrowck: {}", tcx.item_path_str(def_id)); - if !tcx.has_attr(def_id, "rustc_mir_borrowck") && !tcx.sess.use_mir() { + if !tcx.has_attr(def_id, "rustc_mir_borrowck") && !tcx.use_mir() { return None; } @@ -101,7 +101,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>( // contain non-lexical lifetimes. It will have a lifetime tied // to the inference context. let mut mir: Mir<'tcx> = input_mir.clone(); - let free_regions = if !tcx.sess.nll() { + let free_regions = if !tcx.nll() { None } else { let mir = &mut mir; @@ -204,7 +204,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>( ); (Some(Rc::new(regioncx)), opt_closure_req) } else { - assert!(!tcx.sess.nll()); + assert!(!tcx.nll()); (None, None) }; let flow_inits = flow_inits; // remove mut @@ -719,7 +719,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { /// allowed to be split into separate Reservation and /// Activation phases. fn allow_two_phase_borrow(&self, kind: BorrowKind) -> bool { - self.tcx.sess.two_phase_borrows() && + self.tcx.two_phase_borrows() && (kind.allows_two_phase_borrow() || self.tcx.sess.opts.debugging_opts.two_phase_beyond_autoref) } @@ -1253,7 +1253,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { span: Span, flow_state: &Flows<'cx, 'gcx, 'tcx>, ) { - if !self.tcx.sess.two_phase_borrows() { + if !self.tcx.two_phase_borrows() { return; } diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs index a06d39d225c4..3af10c5c2516 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs @@ -1587,7 +1587,7 @@ impl MirPass for TypeckMir { // When NLL is enabled, the borrow checker runs the typeck // itself, so we don't need this MIR pass anymore. - if tcx.sess.nll() { + if tcx.nll() { return; } diff --git a/src/librustc_mir/build/cfg.rs b/src/librustc_mir/build/cfg.rs index 932aad0bb1d8..1ed8289d4418 100644 --- a/src/librustc_mir/build/cfg.rs +++ b/src/librustc_mir/build/cfg.rs @@ -50,7 +50,7 @@ impl<'tcx> CFG<'tcx> { block: BasicBlock, source_info: SourceInfo, region_scope: region::Scope) { - if tcx.sess.emit_end_regions() { + if tcx.emit_end_regions() { if let region::ScopeData::CallSite(_) = region_scope.data() { // The CallSite scope (aka the root scope) is sort of weird, in that it is // supposed to "separate" the "interior" and "exterior" of a closure. Being diff --git a/src/librustc_mir/build/matches/simplify.rs b/src/librustc_mir/build/matches/simplify.rs index b16d7ed23650..abea55835466 100644 --- a/src/librustc_mir/build/matches/simplify.rs +++ b/src/librustc_mir/build/matches/simplify.rs @@ -113,7 +113,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { PatternKind::Variant { adt_def, substs, variant_index, ref subpatterns } => { let irrefutable = adt_def.variants.iter().enumerate().all(|(i, v)| { i == variant_index || { - self.hir.tcx().sess.features.borrow().never_type && + self.hir.tcx().features().never_type && self.hir.tcx().is_variant_uninhabited_from_all_modules(v, substs) } }); diff --git a/src/librustc_mir/transform/clean_end_regions.rs b/src/librustc_mir/transform/clean_end_regions.rs index 7986313aa813..6e8985d99d28 100644 --- a/src/librustc_mir/transform/clean_end_regions.rs +++ b/src/librustc_mir/transform/clean_end_regions.rs @@ -42,7 +42,7 @@ impl MirPass for CleanEndRegions { tcx: TyCtxt<'a, 'tcx, 'tcx>, _source: MirSource, mir: &mut Mir<'tcx>) { - if !tcx.sess.emit_end_regions() { return; } + if !tcx.emit_end_regions() { return; } let mut gather = GatherBorrowedRegions { seen_regions: FxHashSet() diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index 0b0ce1fb4d48..8f5831270d6e 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -936,7 +936,7 @@ This does not pose a problem by itself because they can't be accessed directly." if self.mode != Mode::Fn && // feature-gate is not enabled, - !self.tcx.sess.features.borrow() + !self.tcx.features() .declared_lib_features .iter() .any(|&(ref sym, _)| sym == feature_name) && diff --git a/src/librustc_mir/util/borrowck_errors.rs b/src/librustc_mir/util/borrowck_errors.rs index 4a7ee397aec0..89242ca32bcb 100644 --- a/src/librustc_mir/util/borrowck_errors.rs +++ b/src/librustc_mir/util/borrowck_errors.rs @@ -514,7 +514,7 @@ impl<'b, 'gcx, 'tcx> BorrowckErrors for TyCtxt<'b, 'gcx, 'tcx> { o: Origin) -> DiagnosticBuilder<'a> { - if !o.should_emit_errors(self.sess.borrowck_mode()) { + if !o.should_emit_errors(self.borrowck_mode()) { self.sess.diagnostic().cancel(&mut diag); } diag diff --git a/src/librustc_plugin/load.rs b/src/librustc_plugin/load.rs index a46b85d93cbb..bf59165a9c46 100644 --- a/src/librustc_plugin/load.rs +++ b/src/librustc_plugin/load.rs @@ -52,7 +52,7 @@ pub fn load_plugins(sess: &Session, // do not report any error now. since crate attributes are // not touched by expansion, every use of plugin without // the feature enabled will result in an error later... - if sess.features.borrow().plugin { + if sess.features_untracked().plugin { for attr in &krate.attrs { if !attr.check_name("plugin") { continue; diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index b9899f499148..bf7b81c4d0e4 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -590,7 +590,7 @@ impl<'a> Resolver<'a> { }; let ext = Lrc::new(macro_rules::compile(&self.session.parse_sess, - &self.session.features, + &self.session.features_untracked(), ¯o_def)); self.macro_map.insert(def_id, ext.clone()); ext diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 317bd9217b59..fc1ff2481840 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -1524,7 +1524,7 @@ impl<'a> Resolver<'a> { invocations.insert(Mark::root(), arenas.alloc_invocation_data(InvocationData::root(graph_root))); - let features = session.features.borrow(); + let features = session.features_untracked(); let mut macro_defs = FxHashMap(); macro_defs.insert(Mark::root(), root_def_id); @@ -2998,7 +2998,7 @@ impl<'a> Resolver<'a> { let prim = self.primitive_type_table.primitive_types[&path[0].node.name]; match prim { TyUint(UintTy::U128) | TyInt(IntTy::I128) => { - if !self.session.features.borrow().i128_type { + if !self.session.features_untracked().i128_type { emit_feature_err(&self.session.parse_sess, "i128_type", span, GateIssue::Language, "128-bit type is unstable"); @@ -3089,7 +3089,7 @@ impl<'a> Resolver<'a> { let prev_name = path[0].node.name; if prev_name == keywords::Extern.name() || prev_name == keywords::CrateRoot.name() && - self.session.features.borrow().extern_absolute_paths { + self.session.features_untracked().extern_absolute_paths { // `::extern_crate::a::b` let crate_id = self.crate_loader.resolve_crate_from_path(name, ident.span); let crate_root = diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index 81cc5e59bbbf..95fa0f3b52fe 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -744,7 +744,7 @@ impl<'a> Resolver<'a> { let def_id = self.definitions.local_def_id(item.id); let ext = Lrc::new(macro_rules::compile(&self.session.parse_sess, - &self.session.features, + &self.session.features_untracked(), item)); self.macro_map.insert(def_id, ext); @@ -838,7 +838,7 @@ impl<'a> Resolver<'a> { } fn gate_legacy_custom_derive(&mut self, name: Symbol, span: Span) { - if !self.session.features.borrow().custom_derive { + if !self.session.features_untracked().custom_derive { let sess = &self.session.parse_sess; let explain = feature_gate::EXPLAIN_CUSTOM_DERIVE; emit_feature_err(sess, "custom_derive", span, GateIssue::Language, explain); diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index 438ab3a3513f..01c1ded94578 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -609,7 +609,7 @@ impl<'a, 'b:'a> ImportResolver<'a, 'b> { if module_path.len() == 1 && (module_path[0].node.name == keywords::CrateRoot.name() || module_path[0].node.name == keywords::Extern.name()) { let is_extern = module_path[0].node.name == keywords::Extern.name() || - self.session.features.borrow().extern_absolute_paths; + self.session.features_untracked().extern_absolute_paths; match directive.subclass { GlobImport { .. } if is_extern => { return Some((directive.span, diff --git a/src/librustc_trans_utils/symbol_names_test.rs b/src/librustc_trans_utils/symbol_names_test.rs index 5d7d4f3055ba..267c8d2bd03c 100644 --- a/src/librustc_trans_utils/symbol_names_test.rs +++ b/src/librustc_trans_utils/symbol_names_test.rs @@ -28,7 +28,7 @@ pub fn report_symbol_names<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { // if the `rustc_attrs` feature is not enabled, then the // attributes we are interested in cannot be present anyway, so // skip the walk. - if !tcx.sess.features.borrow().rustc_attrs { + if !tcx.features().rustc_attrs { return; } diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 6a6c49c90483..0df1225cf262 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -415,7 +415,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { let trait_def = self.tcx().trait_def(trait_def_id); - if !self.tcx().sess.features.borrow().unboxed_closures && + if !self.tcx().features().unboxed_closures && trait_segment.with_parameters(|p| p.parenthesized) != trait_def.paren_sugar { // For now, require that parenthetical notation be used only with `Fn()` etc. let msg = if trait_def.paren_sugar { diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index da66a2e52e81..a261c12bcdd9 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -114,7 +114,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { } }; if pat_adjustments.len() > 0 { - if tcx.sess.features.borrow().match_default_bindings { + if tcx.features().match_default_bindings { debug!("default binding mode is now {:?}", def_bm); self.inh.tables.borrow_mut() .pat_adjustments_mut() diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs index e2d6817697e8..abb0acd699cb 100644 --- a/src/librustc_typeck/check/coercion.rs +++ b/src/librustc_typeck/check/coercion.rs @@ -586,7 +586,7 @@ impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> { } } - if has_unsized_tuple_coercion && !self.tcx.sess.features.borrow().unsized_tuple_coercion { + if has_unsized_tuple_coercion && !self.tcx.features().unsized_tuple_coercion { feature_gate::emit_feature_err(&self.tcx.sess.parse_sess, "unsized_tuple_coercion", self.cause.span, diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index c95ead285594..841559013a09 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -324,7 +324,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> { // possible that there will be multiple applicable methods. if !is_suggestion.0 { if reached_raw_pointer - && !self.tcx.sess.features.borrow().arbitrary_self_types { + && !self.tcx.features().arbitrary_self_types { // this case used to be allowed by the compiler, // so we do a future-compat lint here for the 2015 epoch // (see https://github.com/rust-lang/rust/issues/46906) diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index db5a458bb8ce..0f59973eab25 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -1105,7 +1105,7 @@ fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>, } fcx.demand_suptype(span, ret_ty, actual_return_ty); - if fcx.tcx.sess.features.borrow().termination_trait { + if fcx.tcx.features().termination_trait { // If the termination trait language item is activated, check that the main return type // implements the termination trait. if let Some(term_id) = fcx.tcx.lang_items().termination() { @@ -1616,7 +1616,7 @@ pub fn check_enum<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let repr_type_ty = def.repr.discr_type().to_ty(tcx); if repr_type_ty == tcx.types.i128 || repr_type_ty == tcx.types.u128 { - if !tcx.sess.features.borrow().repr128 { + if !tcx.features().repr128 { emit_feature_err(&tcx.sess.parse_sess, "repr128", sp, diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index 39e757c52ff2..d10ee358e072 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -536,7 +536,7 @@ impl<'a, 'gcx> CheckTypeWellFormedVisitor<'a, 'gcx> { let is_self_ty = |ty| fcx.infcx.can_eq(fcx.param_env, self_ty, ty).is_ok(); let self_kind = ExplicitSelf::determine(self_arg_ty, is_self_ty); - if !fcx.tcx.sess.features.borrow().arbitrary_self_types { + if !fcx.tcx.features().arbitrary_self_types { match self_kind { ExplicitSelf::ByValue | ExplicitSelf::ByReference(_, _) | diff --git a/src/librustc_typeck/coherence/mod.rs b/src/librustc_typeck/coherence/mod.rs index f65d627781f0..d3de31d630a9 100644 --- a/src/librustc_typeck/coherence/mod.rs +++ b/src/librustc_typeck/coherence/mod.rs @@ -74,7 +74,7 @@ fn enforce_trait_manually_implementable(tcx: TyCtxt, impl_def_id: DefId, trait_d return; } - if tcx.sess.features.borrow().unboxed_closures { + if tcx.features().unboxed_closures { // the feature gate allows all Fn traits return; } diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 1c8d22e4666a..f7158593f0b6 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -711,7 +711,7 @@ fn trait_def<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, }; let paren_sugar = tcx.has_attr(def_id, "rustc_paren_sugar"); - if paren_sugar && !tcx.sess.features.borrow().unboxed_closures { + if paren_sugar && !tcx.features().unboxed_closures { let mut err = tcx.sess.struct_span_err( item.span, "the `#[rustc_paren_sugar]` attribute is a temporary means of controlling \ @@ -953,7 +953,7 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } if !allow_defaults && p.default.is_some() { - if !tcx.sess.features.borrow().default_type_parameter_fallback { + if !tcx.features().default_type_parameter_fallback { tcx.lint_node( lint::builtin::INVALID_TYPE_PARAM_DEFAULT, p.id, @@ -1692,7 +1692,7 @@ fn compute_sig_of_foreign_fn_decl<'a, 'tcx>( // feature gate SIMD types in FFI, since I (huonw) am not sure the // ABIs are handled at all correctly. if abi != abi::Abi::RustIntrinsic && abi != abi::Abi::PlatformIntrinsic - && !tcx.sess.features.borrow().simd_ffi { + && !tcx.features().simd_ffi { let check = |ast_ty: &hir::Ty, ty: Ty| { if ty.is_simd() { tcx.sess.struct_span_err(ast_ty.span, diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index af32738d9d04..d9bd96b0d769 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -207,7 +207,7 @@ fn check_main_fn_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let actual = tcx.fn_sig(main_def_id); let expected_return_type = if tcx.lang_items().termination().is_some() - && tcx.sess.features.borrow().termination_trait { + && tcx.features().termination_trait { // we take the return type of the given main function, the real check is done // in `check_fn` actual.output().skip_binder() diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index f4c9d556c8ab..e4477bee5c0e 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -629,7 +629,7 @@ impl<'a, 'hir> HirCollector<'a, 'hir> { nested: F) { let mut attrs = Attributes::from_ast(self.sess.diagnostic(), attrs); if let Some(ref cfg) = attrs.cfg { - if !cfg.matches(&self.sess.parse_sess, Some(&self.sess.features.borrow())) { + if !cfg.matches(&self.sess.parse_sess, Some(&self.sess.features_untracked())) { return; } } diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs index 728b3e4076d1..9162a582599f 100644 --- a/src/libsyntax/ext/tt/macro_rules.rs +++ b/src/libsyntax/ext/tt/macro_rules.rs @@ -26,7 +26,6 @@ use parse::token::Token::*; use symbol::Symbol; use tokenstream::{TokenStream, TokenTree}; -use std::cell::RefCell; use std::collections::HashMap; use std::collections::hash_map::Entry; @@ -184,7 +183,7 @@ fn generic_extension<'cx>(cx: &'cx mut ExtCtxt, // Holy self-referential! /// Converts a `macro_rules!` invocation into a syntax extension. -pub fn compile(sess: &ParseSess, features: &RefCell, def: &ast::Item) -> SyntaxExtension { +pub fn compile(sess: &ParseSess, features: &Features, def: &ast::Item) -> SyntaxExtension { let lhs_nm = ast::Ident::with_empty_ctxt(Symbol::gensym("lhs")); let rhs_nm = ast::Ident::with_empty_ctxt(Symbol::gensym("rhs")); @@ -296,7 +295,7 @@ pub fn compile(sess: &ParseSess, features: &RefCell, def: &ast::Item) } fn check_lhs_nt_follows(sess: &ParseSess, - features: &RefCell, + features: &Features, attrs: &[ast::Attribute], lhs: "ed::TokenTree) -> bool { // lhs is going to be like TokenTree::Delimited(...), where the @@ -353,7 +352,7 @@ fn check_rhs(sess: &ParseSess, rhs: "ed::TokenTree) -> bool { } fn check_matcher(sess: &ParseSess, - features: &RefCell, + features: &Features, attrs: &[ast::Attribute], matcher: &[quoted::TokenTree]) -> bool { let first_sets = FirstSets::new(matcher); @@ -601,7 +600,7 @@ impl TokenSet { // Requires that `first_sets` is pre-computed for `matcher`; // see `FirstSets::new`. fn check_matcher_core(sess: &ParseSess, - features: &RefCell, + features: &Features, attrs: &[ast::Attribute], first_sets: &FirstSets, matcher: &[quoted::TokenTree], @@ -869,7 +868,7 @@ fn is_in_follow(tok: "ed::TokenTree, frag: &str) -> Result, + features: &Features, attrs: &[ast::Attribute], tok: "ed::TokenTree) -> Result<(), String> { debug!("has_legal_fragment_specifier({:?})", tok); @@ -884,7 +883,7 @@ fn has_legal_fragment_specifier(sess: &ParseSess, } fn is_legal_fragment_specifier(sess: &ParseSess, - features: &RefCell, + features: &Features, attrs: &[ast::Attribute], frag_name: &str, frag_span: Span) -> bool { @@ -892,7 +891,7 @@ fn is_legal_fragment_specifier(sess: &ParseSess, "item" | "block" | "stmt" | "expr" | "pat" | "path" | "ty" | "ident" | "meta" | "tt" | "" => true, "lifetime" => { - if !features.borrow().macro_lifetime_matcher && + if !features.macro_lifetime_matcher && !attr::contains_name(attrs, "allow_internal_unstable") { let explain = feature_gate::EXPLAIN_LIFETIME_MATCHER; emit_feature_err(sess, @@ -904,7 +903,7 @@ fn is_legal_fragment_specifier(sess: &ParseSess, true }, "vis" => { - if !features.borrow().macro_vis_matcher && + if !features.macro_vis_matcher && !attr::contains_name(attrs, "allow_internal_unstable") { let explain = feature_gate::EXPLAIN_VIS_MATCHER; emit_feature_err(sess, diff --git a/src/libsyntax/ext/tt/quoted.rs b/src/libsyntax/ext/tt/quoted.rs index c9d7f78c2e30..122bb9ba024a 100644 --- a/src/libsyntax/ext/tt/quoted.rs +++ b/src/libsyntax/ext/tt/quoted.rs @@ -17,7 +17,6 @@ use symbol::keywords; use syntax_pos::{BytePos, Span, DUMMY_SP}; use tokenstream; -use std::cell::RefCell; use std::iter::Peekable; use rustc_data_structures::sync::Lrc; @@ -183,7 +182,7 @@ pub fn parse( input: tokenstream::TokenStream, expect_matchers: bool, sess: &ParseSess, - features: &RefCell, + features: &Features, attrs: &[ast::Attribute], ) -> Vec { // Will contain the final collection of `self::TokenTree` @@ -251,7 +250,7 @@ fn parse_tree( trees: &mut Peekable, expect_matchers: bool, sess: &ParseSess, - features: &RefCell, + features: &Features, attrs: &[ast::Attribute], ) -> TokenTree where @@ -382,7 +381,7 @@ fn parse_sep_and_kleene_op( input: &mut Peekable, span: Span, sess: &ParseSess, - features: &RefCell, + features: &Features, attrs: &[ast::Attribute], ) -> (Option, KleeneOp) where @@ -415,7 +414,7 @@ where match parse_kleene_op(input, span) { // #2 is a KleeneOp (this is the only valid option) :) Ok(Ok(op)) if op == KleeneOp::ZeroOrOne => { - if !features.borrow().macro_at_most_once_rep + if !features.macro_at_most_once_rep && !attr::contains_name(attrs, "allow_internal_unstable") { let explain = feature_gate::EXPLAIN_MACRO_AT_MOST_ONCE_REP; @@ -438,7 +437,7 @@ where Err(span) => span, } } else { - if !features.borrow().macro_at_most_once_rep + if !features.macro_at_most_once_rep && !attr::contains_name(attrs, "allow_internal_unstable") { let explain = feature_gate::EXPLAIN_MACRO_AT_MOST_ONCE_REP; @@ -460,7 +459,7 @@ where Ok(Err((tok, span))) => match parse_kleene_op(input, span) { // #2 is a KleeneOp :D Ok(Ok(op)) if op == KleeneOp::ZeroOrOne => { - if !features.borrow().macro_at_most_once_rep + if !features.macro_at_most_once_rep && !attr::contains_name(attrs, "allow_internal_unstable") { let explain = feature_gate::EXPLAIN_MACRO_AT_MOST_ONCE_REP; @@ -487,7 +486,7 @@ where Err(span) => span, }; - if !features.borrow().macro_at_most_once_rep + if !features.macro_at_most_once_rep && !attr::contains_name(attrs, "allow_internal_unstable") { sess.span_diagnostic diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 058df1d51690..45d82bc7af38 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -62,6 +62,7 @@ macro_rules! declare_features { &[$((stringify!($feature), $ver, $issue, set!($feature))),+]; /// A set of features to be used by later passes. + #[derive(Clone)] pub struct Features { /// `#![feature]` attrs for stable language features, for error reporting pub declared_stable_lang_features: Vec<(Symbol, Span)>, @@ -78,6 +79,12 @@ macro_rules! declare_features { $($feature: false),+ } } + + pub fn walk_feature_fields(&self, mut f: F) + where F: FnMut(&str, bool) + { + $(f(stringify!($feature), self.$feature);)+ + } } }; From 9f8b9a0d3e1d7567e74df612a53e989610ba1b24 Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Wed, 14 Feb 2018 16:26:56 +0100 Subject: [PATCH 37/68] incr.comp.: Add regression test for detecting feature gate changes. --- src/test/incremental/feature_gate.rs | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 src/test/incremental/feature_gate.rs diff --git a/src/test/incremental/feature_gate.rs b/src/test/incremental/feature_gate.rs new file mode 100644 index 000000000000..de2f9ab52f60 --- /dev/null +++ b/src/test/incremental/feature_gate.rs @@ -0,0 +1,23 @@ +// Copyright 2018 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 test makes sure that we detect changed feature gates. + +// revisions:rpass1 cfail2 +// compile-flags: -Z query-dep-graph + +#![feature(rustc_attrs)] +#![cfg_attr(rpass1, feature(nll))] + +fn main() { + let mut v = vec![1]; + v.push(v[0]); + //[cfail2]~^ ERROR cannot borrow +} From 17b72bc1ea13256753d57a58f22ac79af6163188 Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Thu, 15 Feb 2018 15:53:26 +0100 Subject: [PATCH 38/68] Fix procedural_mbe_matching test case after libsyntax change. --- src/test/run-pass-fulldeps/auxiliary/procedural_mbe_matching.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 9ebc438ad5a0..fd8f7b9e384f 100644 --- a/src/test/run-pass-fulldeps/auxiliary/procedural_mbe_matching.rs +++ b/src/test/run-pass-fulldeps/auxiliary/procedural_mbe_matching.rs @@ -41,7 +41,7 @@ fn expand_mbe_matches(cx: &mut ExtCtxt, _: Span, args: &[TokenTree]) let mbe_matcher = quoted::parse(mbe_matcher.into_iter().collect(), true, cx.parse_sess, - &RefCell::new(Features::new()), + &Features::new(), &[]); let map = match TokenTree::parse(cx, &mbe_matcher, args.iter().cloned().collect()) { Success(map) => map, From 93625f12e080ac85f5a7a712a316847a891c1d07 Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Wed, 28 Feb 2018 14:11:15 +0100 Subject: [PATCH 39/68] Fix some merge fallout. --- src/librustc/session/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs index f6da4b55301e..5e9eeb973007 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -458,7 +458,7 @@ impl Session { self.opts.debugging_opts.print_llvm_passes } - /// Get the features enabled for the current compilation session. Do not use + /// Get the features enabled for the current compilation session. /// DO NOT USE THIS METHOD if there is a TyCtxt available, as it circumvents /// dependency tracking. Use tcx.features() instead. #[inline] From 88f32d15afac7bc5cff5daca7a0ac80fdedb6dce Mon Sep 17 00:00:00 2001 From: Tobias Bucher Date: Mon, 5 Mar 2018 18:37:05 +0100 Subject: [PATCH 40/68] Remove a couple of `isize` references from hashmap docs Also fix a spelling mistake. --- src/libstd/collections/hash/map.rs | 54 +++++++++++++++--------------- src/libstd/collections/hash/set.rs | 4 +-- 2 files changed, 29 insertions(+), 29 deletions(-) diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs index 4dfdc23ebee5..b023fec810ec 100644 --- a/src/libstd/collections/hash/map.rs +++ b/src/libstd/collections/hash/map.rs @@ -620,7 +620,7 @@ impl HashMap { /// /// ``` /// use std::collections::HashMap; - /// let mut map: HashMap<&str, isize> = HashMap::new(); + /// let mut map: HashMap<&str, i32> = HashMap::new(); /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] @@ -637,7 +637,7 @@ impl HashMap { /// /// ``` /// use std::collections::HashMap; - /// let mut map: HashMap<&str, isize> = HashMap::with_capacity(10); + /// let mut map: HashMap<&str, i32> = HashMap::with_capacity(10); /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] @@ -724,7 +724,7 @@ impl HashMap /// use std::collections::hash_map::RandomState; /// /// let hasher = RandomState::new(); - /// let map: HashMap = HashMap::with_hasher(hasher); + /// let map: HashMap = HashMap::with_hasher(hasher); /// let hasher: &RandomState = map.hasher(); /// ``` #[stable(feature = "hashmap_public_hasher", since = "1.9.0")] @@ -741,7 +741,7 @@ impl HashMap /// /// ``` /// use std::collections::HashMap; - /// let map: HashMap = HashMap::with_capacity(100); + /// let map: HashMap = HashMap::with_capacity(100); /// assert!(map.capacity() >= 100); /// ``` #[inline] @@ -770,7 +770,7 @@ impl HashMap /// /// ``` /// use std::collections::HashMap; - /// let mut map: HashMap<&str, isize> = HashMap::new(); + /// let mut map: HashMap<&str, i32> = HashMap::new(); /// map.reserve(10); /// ``` #[stable(feature = "rust1", since = "1.0.0")] @@ -849,7 +849,7 @@ impl HashMap /// ``` /// use std::collections::HashMap; /// - /// let mut map: HashMap = HashMap::with_capacity(100); + /// let mut map: HashMap = HashMap::with_capacity(100); /// map.insert(1, 2); /// map.insert(3, 4); /// assert!(map.capacity() >= 100); @@ -1306,7 +1306,7 @@ impl HashMap /// ``` /// use std::collections::HashMap; /// - /// let mut map: HashMap = (0..8).map(|x|(x, x*10)).collect(); + /// let mut map: HashMap = (0..8).map(|x|(x, x*10)).collect(); /// map.retain(|&k, _| k % 2 == 0); /// assert_eq!(map.len(), 4); /// ``` @@ -1722,7 +1722,7 @@ impl IntoIterator for HashMap /// map.insert("c", 3); /// /// // Not possible with .iter() - /// let vec: Vec<(&str, isize)> = map.into_iter().collect(); + /// let vec: Vec<(&str, i32)> = map.into_iter().collect(); /// ``` fn into_iter(self) -> IntoIter { IntoIter { inner: self.table.into_iter() } @@ -2786,24 +2786,24 @@ mod test_map { assert_eq!(m2.len(), 2); } - thread_local! { static DROP_VECTOR: RefCell> = RefCell::new(Vec::new()) } + thread_local! { static DROP_VECTOR: RefCell> = RefCell::new(Vec::new()) } #[derive(Hash, PartialEq, Eq)] - struct Dropable { + struct Droppable { k: usize, } - impl Dropable { - fn new(k: usize) -> Dropable { + impl Droppable { + fn new(k: usize) -> Droppable { DROP_VECTOR.with(|slot| { slot.borrow_mut()[k] += 1; }); - Dropable { k: k } + Droppable { k: k } } } - impl Drop for Dropable { + impl Drop for Droppable { fn drop(&mut self) { DROP_VECTOR.with(|slot| { slot.borrow_mut()[self.k] -= 1; @@ -2811,9 +2811,9 @@ mod test_map { } } - impl Clone for Dropable { - fn clone(&self) -> Dropable { - Dropable::new(self.k) + impl Clone for Droppable { + fn clone(&self) -> Droppable { + Droppable::new(self.k) } } @@ -2833,8 +2833,8 @@ mod test_map { }); for i in 0..100 { - let d1 = Dropable::new(i); - let d2 = Dropable::new(i + 100); + let d1 = Droppable::new(i); + let d2 = Droppable::new(i + 100); m.insert(d1, d2); } @@ -2845,7 +2845,7 @@ mod test_map { }); for i in 0..50 { - let k = Dropable::new(i); + let k = Droppable::new(i); let v = m.remove(&k); assert!(v.is_some()); @@ -2892,8 +2892,8 @@ mod test_map { }); for i in 0..100 { - let d1 = Dropable::new(i); - let d2 = Dropable::new(i + 100); + let d1 = Droppable::new(i); + let d2 = Droppable::new(i + 100); hm.insert(d1, d2); } @@ -2943,13 +2943,13 @@ mod test_map { #[test] fn test_empty_remove() { - let mut m: HashMap = HashMap::new(); + let mut m: HashMap = HashMap::new(); assert_eq!(m.remove(&0), None); } #[test] fn test_empty_entry() { - let mut m: HashMap = HashMap::new(); + let mut m: HashMap = HashMap::new(); match m.entry(0) { Occupied(_) => panic!(), Vacant(_) => {} @@ -2960,7 +2960,7 @@ mod test_map { #[test] fn test_empty_iter() { - let mut m: HashMap = HashMap::new(); + let mut m: HashMap = HashMap::new(); assert_eq!(m.drain().next(), None); assert_eq!(m.keys().next(), None); assert_eq!(m.values().next(), None); @@ -3461,7 +3461,7 @@ mod test_map { fn test_entry_take_doesnt_corrupt() { #![allow(deprecated)] //rand // Test for #19292 - fn check(m: &HashMap) { + fn check(m: &HashMap) { for k in m.keys() { assert!(m.contains_key(k), "{} is in keys() but not in the map?", k); @@ -3570,7 +3570,7 @@ mod test_map { #[test] fn test_retain() { - let mut map: HashMap = (0..100).map(|x|(x, x*10)).collect(); + let mut map: HashMap = (0..100).map(|x|(x, x*10)).collect(); map.retain(|&k, _| k % 2 == 0); assert_eq!(map.len(), 50); diff --git a/src/libstd/collections/hash/set.rs b/src/libstd/collections/hash/set.rs index e9427fb40a01..67d413b5a38c 100644 --- a/src/libstd/collections/hash/set.rs +++ b/src/libstd/collections/hash/set.rs @@ -724,7 +724,7 @@ impl HashSet /// use std::collections::HashSet; /// /// let xs = [1,2,3,4,5,6]; - /// let mut set: HashSet = xs.iter().cloned().collect(); + /// let mut set: HashSet = xs.iter().cloned().collect(); /// set.retain(|&k| k % 2 == 0); /// assert_eq!(set.len(), 3); /// ``` @@ -1745,7 +1745,7 @@ mod test_set { #[test] fn test_retain() { let xs = [1, 2, 3, 4, 5, 6]; - let mut set: HashSet = xs.iter().cloned().collect(); + let mut set: HashSet = xs.iter().cloned().collect(); set.retain(|&k| k % 2 == 0); assert_eq!(set.len(), 3); assert!(set.contains(&2)); From 2e7e68b76223b9f14b54852584a5334f33a8798d Mon Sep 17 00:00:00 2001 From: "leonardo.yvens" Date: Mon, 5 Mar 2018 15:58:54 -0300 Subject: [PATCH 41/68] while let all the things --- src/librustc/hir/print.rs | 9 ++------ src/librustc/middle/reachable.rs | 6 +---- .../obligation_forest/mod.rs | 8 +------ src/libstd/sys_common/wtf8.rs | 23 ++++++++----------- src/libsyntax_ext/format.rs | 17 +++++--------- src/libsyntax_pos/lib.rs | 7 +----- 6 files changed, 20 insertions(+), 50 deletions(-) diff --git a/src/librustc/hir/print.rs b/src/librustc/hir/print.rs index ed8cea3eb656..d91aa3a38519 100644 --- a/src/librustc/hir/print.rs +++ b/src/librustc/hir/print.rs @@ -2208,13 +2208,8 @@ impl<'a> State<'a> { if self.next_comment().is_none() { self.s.hardbreak()?; } - loop { - match self.next_comment() { - Some(ref cmnt) => { - self.print_comment(cmnt)?; - } - _ => break, - } + while let Some(ref cmnt) = self.next_comment() { + self.print_comment(cmnt)? } Ok(()) } diff --git a/src/librustc/middle/reachable.rs b/src/librustc/middle/reachable.rs index 749685182a8f..5658b5b68329 100644 --- a/src/librustc/middle/reachable.rs +++ b/src/librustc/middle/reachable.rs @@ -206,11 +206,7 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> { // Step 2: Mark all symbols that the symbols on the worklist touch. fn propagate(&mut self) { let mut scanned = FxHashSet(); - loop { - let search_item = match self.worklist.pop() { - Some(item) => item, - None => break, - }; + while let Some(search_item) = self.worklist.pop() { if !scanned.insert(search_item) { continue } diff --git a/src/librustc_data_structures/obligation_forest/mod.rs b/src/librustc_data_structures/obligation_forest/mod.rs index 02cae52166ac..42a17d33fa6f 100644 --- a/src/librustc_data_structures/obligation_forest/mod.rs +++ b/src/librustc_data_structures/obligation_forest/mod.rs @@ -415,13 +415,7 @@ impl ObligationForest { } } - loop { - // non-standard `while let` to bypass #6393 - let i = match error_stack.pop() { - Some(i) => i, - None => break - }; - + while let Some(i) = error_stack.pop() { let node = &self.nodes[i]; match node.state.get() { diff --git a/src/libstd/sys_common/wtf8.rs b/src/libstd/sys_common/wtf8.rs index 46d554d6411b..9fff8b91f96f 100644 --- a/src/libstd/sys_common/wtf8.rs +++ b/src/libstd/sys_common/wtf8.rs @@ -428,20 +428,15 @@ impl fmt::Debug for Wtf8 { formatter.write_str("\"")?; let mut pos = 0; - loop { - match self.next_surrogate(pos) { - None => break, - Some((surrogate_pos, surrogate)) => { - write_str_escaped( - formatter, - unsafe { str::from_utf8_unchecked( - &self.bytes[pos .. surrogate_pos] - )}, - )?; - write!(formatter, "\\u{{{:x}}}", surrogate)?; - pos = surrogate_pos + 3; - } - } + while let Some((surrogate_pos, surrogate)) = self.next_surrogate(pos) { + write_str_escaped( + formatter, + unsafe { str::from_utf8_unchecked( + &self.bytes[pos .. surrogate_pos] + )}, + )?; + write!(formatter, "\\u{{{:x}}}", surrogate)?; + pos = surrogate_pos + 3; } write_str_escaped( formatter, diff --git a/src/libsyntax_ext/format.rs b/src/libsyntax_ext/format.rs index a7822414c695..8fd95aa1ca86 100644 --- a/src/libsyntax_ext/format.rs +++ b/src/libsyntax_ext/format.rs @@ -732,18 +732,13 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt, let mut parser = parse::Parser::new(fmt_str); let mut pieces = vec![]; - loop { - match parser.next() { - Some(mut piece) => { - if !parser.errors.is_empty() { - break; - } - cx.verify_piece(&piece); - cx.resolve_name_inplace(&mut piece); - pieces.push(piece); - } - None => break, + while let Some(mut piece) = parser.next() { + if !parser.errors.is_empty() { + break; } + cx.verify_piece(&piece); + cx.resolve_name_inplace(&mut piece); + pieces.push(piece); } let numbered_position_args = pieces.iter().any(|arg: &parse::Piece| { diff --git a/src/libsyntax_pos/lib.rs b/src/libsyntax_pos/lib.rs index 9f746adbe657..ed9eb5d5c926 100644 --- a/src/libsyntax_pos/lib.rs +++ b/src/libsyntax_pos/lib.rs @@ -322,12 +322,7 @@ impl Span { pub fn macro_backtrace(mut self) -> Vec { let mut prev_span = DUMMY_SP; let mut result = vec![]; - loop { - let info = match self.ctxt().outer().expn_info() { - Some(info) => info, - None => break, - }; - + while let Some(info) = self.ctxt().outer().expn_info() { let (pre, post) = match info.callee.format { ExpnFormat::MacroAttribute(..) => ("#[", "]"), ExpnFormat::MacroBang(..) => ("", "!"), From 2cb8c5fff690cff5e98c84f9bd08411f79347bd9 Mon Sep 17 00:00:00 2001 From: Mark Mansi Date: Thu, 22 Feb 2018 18:59:04 -0600 Subject: [PATCH 42/68] Run rustfmt on tidy/src/deps.rs --- src/tools/tidy/src/deps.rs | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index 4dedf6bfe779..c3fb0d3913fd 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -29,19 +29,19 @@ static LICENSES: &'static [&'static str] = &[ // tooling. It is _crucial_ that no exception crates be dependencies // of the Rust runtime (std / test). static EXCEPTIONS: &'static [&'static str] = &[ - "mdbook", // MPL2, mdbook - "openssl", // BSD+advertising clause, cargo, mdbook - "pest", // MPL2, mdbook via handlebars - "thread-id", // Apache-2.0, mdbook - "toml-query", // MPL-2.0, mdbook - "is-match", // MPL-2.0, mdbook - "cssparser", // MPL-2.0, rustdoc - "smallvec", // MPL-2.0, rustdoc + "mdbook", // MPL2, mdbook + "openssl", // BSD+advertising clause, cargo, mdbook + "pest", // MPL2, mdbook via handlebars + "thread-id", // Apache-2.0, mdbook + "toml-query", // MPL-2.0, mdbook + "is-match", // MPL-2.0, mdbook + "cssparser", // MPL-2.0, rustdoc + "smallvec", // MPL-2.0, rustdoc "fuchsia-zircon-sys", // BSD-3-Clause, rustdoc, rustc, cargo - "fuchsia-zircon", // BSD-3-Clause, rustdoc, rustc, cargo (jobserver & tempdir) - "cssparser-macros", // MPL-2.0, rustdoc - "selectors", // MPL-2.0, rustdoc - "clippy_lints", // MPL-2.0 rls + "fuchsia-zircon", // BSD-3-Clause, rustdoc, rustc, cargo (jobserver & tempdir) + "cssparser-macros", // MPL-2.0, rustdoc + "selectors", // MPL-2.0, rustdoc + "clippy_lints", // MPL-2.0 rls ]; pub fn check(path: &Path, bad: &mut bool) { @@ -57,7 +57,8 @@ pub fn check(path: &Path, bad: &mut bool) { if dir.path() .to_str() .unwrap() - .contains(&format!("src/vendor/{}", exception)) { + .contains(&format!("src/vendor/{}", exception)) + { continue 'next_path; } } @@ -102,7 +103,7 @@ fn extract_license(line: &str) -> String { let first_quote = line.find('"'); let last_quote = line.rfind('"'); if let (Some(f), Some(l)) = (first_quote, last_quote) { - let license = &line[f + 1 .. l]; + let license = &line[f + 1..l]; license.into() } else { "bad-license-parse".into() From 3ee410498db9826c3ccb81ce8c0aa40f7f3b4082 Mon Sep 17 00:00:00 2001 From: Mark Mansi Date: Thu, 22 Feb 2018 19:52:56 -0600 Subject: [PATCH 43/68] Start adding a whitelist for rustc dependencies --- src/Cargo.lock | 5 +++ src/tools/tidy/Cargo.toml | 5 +++ src/tools/tidy/src/deps.rs | 76 +++++++++++++++++++++++++++++++++----- src/tools/tidy/src/lib.rs | 5 +++ 4 files changed, 82 insertions(+), 9 deletions(-) diff --git a/src/Cargo.lock b/src/Cargo.lock index 7620fe8ddb3c..5e7909ff4355 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -2585,6 +2585,11 @@ dependencies = [ [[package]] name = "tidy" version = "0.1.0" +dependencies = [ + "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "time" diff --git a/src/tools/tidy/Cargo.toml b/src/tools/tidy/Cargo.toml index 664aecfcbdb9..f7b491823f83 100644 --- a/src/tools/tidy/Cargo.toml +++ b/src/tools/tidy/Cargo.toml @@ -2,3 +2,8 @@ name = "tidy" version = "0.1.0" authors = ["Alex Crichton "] + +[dependencies] +serde = "1.0.8" +serde_derive = "1.0.8" +serde_json = "1.0.2" diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index c3fb0d3913fd..2cb8a70844e1 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -14,6 +14,10 @@ use std::fs::File; use std::io::Read; use std::path::Path; +use std::process::Command; + +use serde_json; + static LICENSES: &'static [&'static str] = &[ "MIT/Apache-2.0", "MIT / Apache-2.0", @@ -44,31 +48,68 @@ static EXCEPTIONS: &'static [&'static str] = &[ "clippy_lints", // MPL-2.0 rls ]; +// Whitelist of crates rustc is allowed to depend on. Avoid adding to the list if possible. +static WHITELIST: &'static [(&'static str, &'static str)] = &[]; + +// Some type for Serde to deserialize the output of `cargo metadata` to... + +#[derive(Deserialize)] +struct Output { + packages: Vec, + _resolve: String, +} + +#[derive(Deserialize)] +struct Package { + _id: String, + name: String, + version: String, + _source: Option, + _manifest_path: String, +} + +/// Checks the dependency at the given path. Changes `bad` to `true` if a check failed. +/// +/// Specifically, this checks that the license is correct and that the dependencies are on the +/// whitelist. pub fn check(path: &Path, bad: &mut bool) { + // Check licences let path = path.join("vendor"); assert!(path.exists(), "vendor directory missing"); let mut saw_dir = false; - 'next_path: for dir in t!(path.read_dir()) { + for dir in t!(path.read_dir()) { saw_dir = true; let dir = t!(dir); // skip our exceptions - for exception in EXCEPTIONS { - if dir.path() + if EXCEPTIONS.iter().any(|exception| { + dir.path() .to_str() .unwrap() .contains(&format!("src/vendor/{}", exception)) - { - continue 'next_path; - } + }) { + continue; } let toml = dir.path().join("Cargo.toml"); - if !check_license(&toml) { - *bad = true; - } + *bad = *bad || !check_license(&toml); } assert!(saw_dir, "no vendored source"); + + // Check dependencies + let deps = get_deps(&path); + *bad = *bad + || deps.iter().any( + |&Package { + ref name, + ref version, + .. + }| { + WHITELIST + .iter() + .all(|&(wname, wversion)| name != wname || version != wversion) + }, + ); } fn check_license(path: &Path) -> bool { @@ -109,3 +150,20 @@ fn extract_license(line: &str) -> String { "bad-license-parse".into() } } + +fn get_deps(path: &Path) -> Vec { + // Run `cargo metadata` to get the set of dependencies + let output = Command::new("cargo") + .arg("metadata") + .arg("--format-version") + .arg("1") + .arg("--manifest-path") + .arg(path.join("Cargo.toml")) + .output() + .expect("Unable to run `cargo metadata`") + .stdout; + let output = String::from_utf8_lossy(&output); + let output: Output = serde_json::from_str(&output).unwrap(); + + output.packages +} diff --git a/src/tools/tidy/src/lib.rs b/src/tools/tidy/src/lib.rs index 5134c8699126..c927ff19b279 100644 --- a/src/tools/tidy/src/lib.rs +++ b/src/tools/tidy/src/lib.rs @@ -15,6 +15,11 @@ #![deny(warnings)] +extern crate serde; +extern crate serde_json; +#[macro_use] +extern crate serde_derive; + use std::fs; use std::path::Path; From d62621839a64352e41f8908021cfe8e7d91f064a Mon Sep 17 00:00:00 2001 From: Mark Mansi Date: Thu, 22 Feb 2018 19:57:55 -0600 Subject: [PATCH 44/68] Comments --- src/tools/tidy/src/deps.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index 2cb8a70844e1..30eadd9ec9dc 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -51,7 +51,7 @@ static EXCEPTIONS: &'static [&'static str] = &[ // Whitelist of crates rustc is allowed to depend on. Avoid adding to the list if possible. static WHITELIST: &'static [(&'static str, &'static str)] = &[]; -// Some type for Serde to deserialize the output of `cargo metadata` to... +// Some types for Serde to deserialize the output of `cargo metadata` to... #[derive(Deserialize)] struct Output { @@ -151,6 +151,7 @@ fn extract_license(line: &str) -> String { } } +/// Get the dependencies of the crate at the given path using `cargo metadata`. fn get_deps(path: &Path) -> Vec { // Run `cargo metadata` to get the set of dependencies let output = Command::new("cargo") From 3570b9df6ae615691bfe296b5af816332a25299b Mon Sep 17 00:00:00 2001 From: Mark Mansi Date: Fri, 23 Feb 2018 18:01:51 -0600 Subject: [PATCH 45/68] MAKE IT FAILgit statusgit status --- src/tools/tidy/src/deps.rs | 72 +++++++++++++++++++++++++++----------- src/tools/tidy/src/main.rs | 1 + 2 files changed, 53 insertions(+), 20 deletions(-) diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index 30eadd9ec9dc..a2d42a00c36d 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -10,10 +10,10 @@ //! Check license of third-party deps by inspecting src/vendor +use std::collections::HashSet; use std::fs::File; use std::io::Read; use std::path::Path; - use std::process::Command; use serde_json; @@ -56,22 +56,40 @@ static WHITELIST: &'static [(&'static str, &'static str)] = &[]; #[derive(Deserialize)] struct Output { packages: Vec, - _resolve: String, + + // Not used, but needed to not confuse serde :P + #[allow(dead_code)] resolve: Resolve, } #[derive(Deserialize)] struct Package { - _id: String, name: String, version: String, - _source: Option, - _manifest_path: String, + + // Not used, but needed to not confuse serde :P + #[allow(dead_code)] id: String, + #[allow(dead_code)] source: Option, + #[allow(dead_code)] manifest_path: String, +} + +// Not used, but needed to not confuse serde :P +#[allow(dead_code)] +#[derive(Deserialize)] +struct Resolve { + nodes: Vec, +} + +// Not used, but needed to not confuse serde :P +#[allow(dead_code)] +#[derive(Deserialize)] +struct ResolveNode { + id: String, + dependencies: Vec, } /// Checks the dependency at the given path. Changes `bad` to `true` if a check failed. /// -/// Specifically, this checks that the license is correct and that the dependencies are on the -/// whitelist. +/// Specifically, this checks that the license is correct. pub fn check(path: &Path, bad: &mut bool) { // Check licences let path = path.join("vendor"); @@ -95,21 +113,35 @@ pub fn check(path: &Path, bad: &mut bool) { *bad = *bad || !check_license(&toml); } assert!(saw_dir, "no vendored source"); +} +/// Checks the dependency at the given path. Changes `bad` to `true` if a check failed. +/// +/// Specifically, this checks that the dependencies are on the whitelist. +pub fn check_whitelist(path: &Path, bad: &mut bool) { // Check dependencies - let deps = get_deps(&path); - *bad = *bad - || deps.iter().any( - |&Package { - ref name, - ref version, - .. - }| { - WHITELIST - .iter() - .all(|&(wname, wversion)| name != wname || version != wversion) - }, - ); + let deps: HashSet<_> = get_deps(&path) + .into_iter() + .map(|Package { name, version, .. }| (name, version)) + .collect(); + let whitelist: HashSet<(String, String)> = WHITELIST + .iter() + .map(|&(n, v)| (n.to_owned(), v.to_owned())) + .collect(); + + // Dependencies not in the whitelist + let mut unapproved: Vec<_> = deps.difference(&whitelist).collect(); + + // For ease of reading + unapproved.sort(); + + if unapproved.len() > 0 { + println!("Dependencies not on the whitelist:"); + for dep in unapproved { + println!("* {} {}", dep.0, dep.1); // name version + } + *bad = true; + } } fn check_license(path: &Path) -> bool { diff --git a/src/tools/tidy/src/main.rs b/src/tools/tidy/src/main.rs index f6640c902bcb..f64536e2f59e 100644 --- a/src/tools/tidy/src/main.rs +++ b/src/tools/tidy/src/main.rs @@ -41,6 +41,7 @@ fn main() { if !args.iter().any(|s| *s == "--no-vendor") { deps::check(&path, &mut bad); } + deps::check_whitelist(&path, &mut bad); if bad { eprintln!("some tidy checks failed"); From 6e016c587ff4feae9f2401c744f6d69fa3e22c77 Mon Sep 17 00:00:00 2001 From: Mark Mansi Date: Fri, 23 Feb 2018 18:25:21 -0600 Subject: [PATCH 46/68] Trying to get paths right... --- src/tools/tidy/src/deps.rs | 311 ++++++++++++++++++++++++++++++++++++- 1 file changed, 310 insertions(+), 1 deletion(-) diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index a2d42a00c36d..b7f697f39ae2 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -49,7 +49,315 @@ static EXCEPTIONS: &'static [&'static str] = &[ ]; // Whitelist of crates rustc is allowed to depend on. Avoid adding to the list if possible. -static WHITELIST: &'static [(&'static str, &'static str)] = &[]; +static WHITELIST: &'static [(&'static str, &'static str)] = &[ +// ("advapi32-sys", "0.2.0"), +// ("aho-corasick", "0.5.3"), +// ("aho-corasick", "0.6.4"), +// ("alloc", "0.0.0"), +// ("alloc_jemalloc", "0.0.0"), +// ("alloc_system", "0.0.0"), +// ("ansi_term", "0.10.2"), +// ("ar", "0.3.1"), +// ("arena", "0.0.0"), +// ("atty", "0.2.6"), +// ("backtrace", "0.3.5"), +// ("backtrace-sys", "0.1.16"), +// ("bin_lib", "0.1.0"), +// ("bitflags", "0.7.0"), +// ("bitflags", "0.9.1"), +// ("bitflags", "1.0.1"), +// ("bootstrap", "0.0.0"), +// ("borrow_error", "0.1.0"), +// ("bufstream", "0.1.3"), +// ("build-manifest", "0.1.0"), +// ("build_helper", "0.1.0"), +// ("byteorder", "1.2.1"), +// ("cargo", "0.26.0"), +// ("cargo_metadata", "0.2.3"), +// ("cargo_metadata", "0.4.0"), +// ("cargotest", "0.1.0"), +// ("cargotest2", "0.1.0"), +// ("cc", "1.0.4"), +// ("cfg-if", "0.1.2"), +// ("chrono", "0.4.0"), +// ("clap", "2.29.0"), +// ("clippy", "0.0.186"), +// ("clippy-mini-macro-test", "0.2.0"), +// ("clippy_lints", "0.0.186"), +// ("cmake", "0.1.29"), +// ("coco", "0.1.1"), +// ("commoncrypto", "0.2.0"), +// ("commoncrypto-sys", "0.2.0"), +// ("compiler_builtins", "0.0.0"), +// ("compiletest", "0.0.0"), +// ("compiletest_rs", "0.3.6"), +// ("completion", "0.1.0"), +// ("core", "0.0.0"), +// ("core-foundation", "0.4.6"), +// ("core-foundation-sys", "0.4.6"), +// ("crates-io", "0.15.0"), +// ("crossbeam", "0.2.12"), +// ("crossbeam", "0.3.2"), +// ("crypto-hash", "0.3.0"), +// ("curl", "0.4.11"), +// ("curl-sys", "0.4.1"), +// ("deglob", "0.1.0"), +// ("derive-new", "0.5.0"), +// ("diff", "0.1.11"), +// ("dlmalloc", "0.0.0"), +// ("docopt", "0.8.3"), +// ("dtoa", "0.4.2"), +// ("duct", "0.8.2"), +// ("either", "1.4.0"), +// ("endian-type", "0.1.2"), +// ("enum_primitive", "0.1.1"), +// ("env_logger", "0.3.5"), +// ("env_logger", "0.4.3"), +// ("env_logger", "0.5.3"), +// ("error-chain", "0.11.0"), +// ("error-chain", "0.8.1"), +// ("error_index_generator", "0.0.0"), +// ("failure", "0.1.1"), +// ("failure_derive", "0.1.1"), +// ("features", "0.1.0"), +// ("filetime", "0.1.15"), +// ("find_all_refs_no_cfg_test", "0.1.0"), +// ("find_impls", "0.1.0"), +// ("flate2", "1.0.1"), +// ("fmt_macros", "0.0.0"), +// ("fnv", "1.0.6"), +// ("foreign-types", "0.3.2"), +// ("foreign-types-shared", "0.1.1"), +// ("fs2", "0.4.3"), +// ("fuchsia-zircon", "0.3.3"), +// ("fuchsia-zircon-sys", "0.3.3"), +// ("futures", "0.1.17"), +// ("getopts", "0.2.15"), +// ("git2", "0.6.11"), +// ("git2-curl", "0.7.0"), +// ("glob", "0.2.11"), +// ("globset", "0.2.1"), +// ("graphviz", "0.0.0"), +// ("hamcrest", "0.1.1"), +// ("handlebars", "0.29.1"), +// ("hex", "0.2.0"), +// ("hex", "0.3.1"), +// ("home", "0.3.0"), +// ("idna", "0.1.4"), +// ("if_chain", "0.1.2"), +// ("ignore", "0.3.1"), +// ("infer_bin", "0.1.0"), +// ("infer_custom_bin", "0.1.0"), +// ("infer_lib", "0.1.0"), +// ("installer", "0.0.0"), +// ("is-match", "0.1.0"), +// ("itertools", "0.6.5"), +// ("itertools", "0.7.6"), +// ("itoa", "0.3.4"), +// ("jobserver", "0.1.9"), +// ("json", "0.11.12"), +// ("jsonrpc-core", "8.0.1"), +// ("kernel32-sys", "0.2.2"), +// ("languageserver-types", "0.30.0"), +// ("lazy_static", "0.2.11"), +// ("lazy_static", "1.0.0"), +// ("lazycell", "0.5.1"), +// ("libc", "0.0.0"), +// ("libc", "0.2.36"), +// ("libgit2-sys", "0.6.19"), +// ("libssh2-sys", "0.2.6"), +// ("libz-sys", "1.0.18"), +// ("linkchecker", "0.1.0"), +// ("log", "0.3.9"), +// ("log", "0.4.1"), +// ("log_settings", "0.1.1"), +// ("lzma-sys", "0.1.9"), +// ("matches", "0.1.6"), +// ("mdbook", "0.1.2"), +// ("memchr", "0.1.11"), +// ("memchr", "2.0.1"), +// ("miniz-sys", "0.1.10"), +// ("miow", "0.2.1"), +// ("miri", "0.1.0"), +// ("multiple_bins", "0.1.0"), +// ("net2", "0.2.31"), +// ("nibble_vec", "0.0.3"), +// ("nix", "0.8.1"), +// ("num", "0.1.41"), +// ("num-bigint", "0.1.41"), +// ("num-complex", "0.1.41"), +// ("num-integer", "0.1.35"), +// ("num-iter", "0.1.34"), +// ("num-rational", "0.1.40"), +// ("num-traits", "0.1.41"), +// ("num_cpus", "1.8.0"), +// ("open", "1.2.1"), +// ("openssl", "0.9.23"), +// ("openssl-probe", "0.1.2"), +// ("openssl-sys", "0.9.24"), +// ("os_pipe", "0.5.1"), +// ("owning_ref", "0.3.3"), +// ("panic_abort", "0.0.0"), +// ("panic_unwind", "0.0.0"), +// ("parking_lot", "0.5.3"), +// ("parking_lot_core", "0.2.9"), +// ("percent-encoding", "1.0.1"), +// ("pest", "0.3.3"), +// ("pkg-config", "0.3.9"), +// ("proc_macro", "0.0.0"), +// ("profiler_builtins", "0.0.0"), +// ("pulldown-cmark", "0.0.15"), +// ("pulldown-cmark", "0.1.0"), +// ("quick-error", "1.2.1"), +// ("quine-mc_cluskey", "0.2.4"), +// ("quote", "0.3.15"), +// ("racer", "2.0.12"), +// ("radix_trie", "0.1.2"), +// ("rand", "0.3.20"), +// ("rayon", "0.9.0"), +// ("rayon-core", "1.3.0"), +// ("redox_syscall", "0.1.37"), +// ("redox_termios", "0.1.1"), +// ("reformat", "0.1.0"), +// ("reformat_with_range", "0.1.0"), +// ("regex", "0.1.80"), +// ("regex", "0.2.5"), +// ("regex-syntax", "0.3.9"), +// ("regex-syntax", "0.4.2"), +// ("remote-test-client", "0.1.0"), +// ("remote-test-server", "0.1.0"), +// ("rls", "0.125.0"), +// ("rls-analysis", "0.11.0"), +// ("rls-blacklist", "0.1.0"), +// ("rls-data", "0.15.0"), +// ("rls-rustc", "0.2.1"), +// ("rls-span", "0.4.0"), +// ("rls-vfs", "0.4.4"), +// ("rustbook", "0.1.0"), +// ("rustc", "0.0.0"), +// ("rustc-ap-rustc_cratesio_shim", "29.0.0"), +// ("rustc-ap-rustc_data_structures", "29.0.0"), +// ("rustc-ap-rustc_errors", "29.0.0"), +// ("rustc-ap-serialize", "29.0.0"), +// ("rustc-ap-syntax", "29.0.0"), +// ("rustc-ap-syntax_pos", "29.0.0"), +// ("rustc-demangle", "0.1.5"), +// ("rustc-main", "0.0.0"), +// ("rustc-serialize", "0.3.24"), +// ("rustc_allocator", "0.0.0"), +// ("rustc_apfloat", "0.0.0"), +// ("rustc_asan", "0.0.0"), +// ("rustc_back", "0.0.0"), +// ("rustc_binaryen", "0.0.0"), +// ("rustc_borrowck", "0.0.0"), +// ("rustc_const_eval", "0.0.0"), +// ("rustc_const_math", "0.0.0"), +// ("rustc_cratesio_shim", "0.0.0"), +// ("rustc_data_structures", "0.0.0"), +// ("rustc_driver", "0.0.0"), +// ("rustc_errors", "0.0.0"), +// ("rustc_incremental", "0.0.0"), +// ("rustc_lint", "0.0.0"), +// ("rustc_llvm", "0.0.0"), +// ("rustc_lsan", "0.0.0"), +// ("rustc_metadata", "0.0.0"), +// ("rustc_mir", "0.0.0"), +// ("rustc_msan", "0.0.0"), +// ("rustc_passes", "0.0.0"), +// ("rustc_platform_intrinsics", "0.0.0"), +// ("rustc_plugin", "0.0.0"), +// ("rustc_privacy", "0.0.0"), +// ("rustc_resolve", "0.0.0"), +// ("rustc_save_analysis", "0.0.0"), +// ("rustc_trans", "0.0.0"), +// ("rustc_trans_utils", "0.0.0"), +// ("rustc_tsan", "0.0.0"), +// ("rustc_typeck", "0.0.0"), +// ("rustdoc", "0.0.0"), +// ("rustdoc-themes", "0.1.0"), +// ("rustdoc-tool", "0.0.0"), +// ("rustfmt-nightly", "0.3.8"), +// ("same-file", "0.1.3"), +// ("same-file", "1.0.2"), +// ("schannel", "0.1.10"), +// ("scoped-tls", "0.1.0"), +// ("scopeguard", "0.1.2"), +// ("scopeguard", "0.3.3"), +// ("semver", "0.6.0"), +// ("semver", "0.8.0"), +// ("semver", "0.9.0"), +// ("semver-parser", "0.7.0"), +// ("serde", "1.0.27"), +// ("serde_derive", "1.0.27"), +// ("serde_derive_internals", "0.19.0"), +// ("serde_ignored", "0.0.4"), +// ("serde_json", "1.0.9"), +// ("serialize", "0.0.0"), +// ("shared_child", "0.2.1"), +// ("shell-escape", "0.1.3"), +// ("shlex", "0.1.1"), +// ("smallvec", "0.6.0"), +// ("socket2", "0.3.0"), +// ("stable_deref_trait", "1.0.0"), +// ("std", "0.0.0"), +// ("std_unicode", "0.0.0"), +// ("strsim", "0.6.0"), +// ("syn", "0.11.11"), +// ("synom", "0.11.3"), +// ("synstructure", "0.6.1"), +// ("syntax", "0.0.0"), +// ("syntax_ext", "0.0.0"), +// ("syntax_pos", "0.0.0"), +// ("syntex_errors", "0.52.0"), +// ("syntex_pos", "0.52.0"), +// ("syntex_syntax", "0.52.0"), +// ("tar", "0.4.14"), +// ("tempdir", "0.3.5"), +// ("term", "0.0.0"), +// ("term", "0.4.6"), +// ("termcolor", "0.3.3"), +// ("termion", "1.5.1"), +// ("test", "0.0.0"), +// ("textwrap", "0.9.0"), +// ("thread-id", "2.0.0"), +// ("thread_local", "0.2.7"), +// ("thread_local", "0.3.5"), +// ("tidy", "0.1.0"), +// ("time", "0.1.39"), +// ("toml", "0.2.1"), +// ("toml", "0.4.5"), +// ("toml-query", "0.6.0"), +// ("unicode-bidi", "0.3.4"), +// ("unicode-normalization", "0.1.5"), +// ("unicode-segmentation", "1.2.0"), +// ("unicode-width", "0.1.4"), +// ("unicode-xid", "0.0.3"), +// ("unicode-xid", "0.0.4"), +// ("unreachable", "1.0.0"), +// ("unstable-book-gen", "0.1.0"), +// ("unwind", "0.0.0"), +// ("url", "1.6.0"), +// ("url_serde", "0.2.0"), +// ("userenv-sys", "0.2.0"), +// ("utf8-ranges", "0.1.3"), +// ("utf8-ranges", "1.0.0"), +// ("vcpkg", "0.2.2"), +// ("vec_map", "0.8.0"), +// ("void", "1.0.2"), +// ("walkdir", "1.0.7"), +// ("walkdir", "2.0.1"), +// ("winapi", "0.2.8"), +// ("winapi", "0.3.4"), +// ("winapi-build", "0.1.1"), +// ("winapi-i686-pc-windows-gnu", "0.4.0"), +// ("winapi-x86_64-pc-windows-gnu", "0.4.0"), +// ("wincolor", "0.1.4"), +// ("workspace_symbol", "0.1.0"), +// ("ws2_32-sys", "0.2.1"), +// ("xattr", "0.1.11"), +// ("xz2", "0.1.4"), +// ("yaml-rust", "0.3.5"), +]; // Some types for Serde to deserialize the output of `cargo metadata` to... @@ -186,6 +494,7 @@ fn extract_license(line: &str) -> String { /// Get the dependencies of the crate at the given path using `cargo metadata`. fn get_deps(path: &Path) -> Vec { // Run `cargo metadata` to get the set of dependencies + println!("Getting metadata from {:?}", path.join("Cargo.toml")); let output = Command::new("cargo") .arg("metadata") .arg("--format-version") From b9b1c378c5399d15eeab6c0347f97d9b32269270 Mon Sep 17 00:00:00 2001 From: Mark Mansi Date: Mon, 26 Feb 2018 11:05:43 -0600 Subject: [PATCH 47/68] Get the path to cargo from rustbuild --- src/bootstrap/test.rs | 1 + src/tools/tidy/src/deps.rs | 9 ++++----- src/tools/tidy/src/main.rs | 7 +++++-- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index c0998c1e42c9..48490493525f 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -528,6 +528,7 @@ impl Step for Tidy { println!("tidy check ({})", host); let mut cmd = builder.tool_cmd(Tool::Tidy); cmd.arg(build.src.join("src")); + cmd.arg(&build.initial_cargo); if !build.config.vendor { cmd.arg("--no-vendor"); } diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index b7f697f39ae2..4c9c0d8cf668 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -426,9 +426,9 @@ pub fn check(path: &Path, bad: &mut bool) { /// Checks the dependency at the given path. Changes `bad` to `true` if a check failed. /// /// Specifically, this checks that the dependencies are on the whitelist. -pub fn check_whitelist(path: &Path, bad: &mut bool) { +pub fn check_whitelist(path: &Path, cargo: &Path, bad: &mut bool) { // Check dependencies - let deps: HashSet<_> = get_deps(&path) + let deps: HashSet<_> = get_deps(&path, &cargo) .into_iter() .map(|Package { name, version, .. }| (name, version)) .collect(); @@ -492,10 +492,9 @@ fn extract_license(line: &str) -> String { } /// Get the dependencies of the crate at the given path using `cargo metadata`. -fn get_deps(path: &Path) -> Vec { +fn get_deps(path: &Path, cargo: &Path) -> Vec { // Run `cargo metadata` to get the set of dependencies - println!("Getting metadata from {:?}", path.join("Cargo.toml")); - let output = Command::new("cargo") + let output = Command::new(cargo) .arg("metadata") .arg("--format-version") .arg("1") diff --git a/src/tools/tidy/src/main.rs b/src/tools/tidy/src/main.rs index f64536e2f59e..afa3ebd19831 100644 --- a/src/tools/tidy/src/main.rs +++ b/src/tools/tidy/src/main.rs @@ -24,9 +24,12 @@ use std::path::PathBuf; use std::env; fn main() { - let path = env::args_os().skip(1).next().expect("need an argument"); + let path = env::args_os().skip(1).next().expect("need path to src"); let path = PathBuf::from(path); + let cargo = env::args_os().skip(2).next().expect("need path to cargo"); + let cargo = PathBuf::from(cargo); + let args: Vec = env::args().skip(1).collect(); let mut bad = false; @@ -41,7 +44,7 @@ fn main() { if !args.iter().any(|s| *s == "--no-vendor") { deps::check(&path, &mut bad); } - deps::check_whitelist(&path, &mut bad); + deps::check_whitelist(&path, &cargo, &mut bad); if bad { eprintln!("some tidy checks failed"); From 50876d1ca47ab34473b70c7364b1bfb835f5c25a Mon Sep 17 00:00:00 2001 From: Mark Mansi Date: Mon, 26 Feb 2018 23:45:04 -0600 Subject: [PATCH 48/68] Only check the whitelist for some crates --- src/tools/tidy/src/deps.rs | 495 +++++++++++-------------------------- 1 file changed, 151 insertions(+), 344 deletions(-) diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index 4c9c0d8cf668..0d351c9e7350 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -28,10 +28,10 @@ static LICENSES: &'static [&'static str] = &[ "Unlicense/MIT", ]; -// These are exceptions to Rust's permissive licensing policy, and -// should be considered bugs. Exceptions are only allowed in Rust -// tooling. It is _crucial_ that no exception crates be dependencies -// of the Rust runtime (std / test). +/// These are exceptions to Rust's permissive licensing policy, and +/// should be considered bugs. Exceptions are only allowed in Rust +/// tooling. It is _crucial_ that no exception crates be dependencies +/// of the Rust runtime (std / test). static EXCEPTIONS: &'static [&'static str] = &[ "mdbook", // MPL2, mdbook "openssl", // BSD+advertising clause, cargo, mdbook @@ -48,353 +48,122 @@ static EXCEPTIONS: &'static [&'static str] = &[ "clippy_lints", // MPL-2.0 rls ]; -// Whitelist of crates rustc is allowed to depend on. Avoid adding to the list if possible. -static WHITELIST: &'static [(&'static str, &'static str)] = &[ -// ("advapi32-sys", "0.2.0"), -// ("aho-corasick", "0.5.3"), -// ("aho-corasick", "0.6.4"), -// ("alloc", "0.0.0"), -// ("alloc_jemalloc", "0.0.0"), -// ("alloc_system", "0.0.0"), -// ("ansi_term", "0.10.2"), -// ("ar", "0.3.1"), -// ("arena", "0.0.0"), -// ("atty", "0.2.6"), -// ("backtrace", "0.3.5"), -// ("backtrace-sys", "0.1.16"), -// ("bin_lib", "0.1.0"), -// ("bitflags", "0.7.0"), -// ("bitflags", "0.9.1"), -// ("bitflags", "1.0.1"), -// ("bootstrap", "0.0.0"), -// ("borrow_error", "0.1.0"), -// ("bufstream", "0.1.3"), -// ("build-manifest", "0.1.0"), -// ("build_helper", "0.1.0"), -// ("byteorder", "1.2.1"), -// ("cargo", "0.26.0"), -// ("cargo_metadata", "0.2.3"), -// ("cargo_metadata", "0.4.0"), -// ("cargotest", "0.1.0"), -// ("cargotest2", "0.1.0"), -// ("cc", "1.0.4"), -// ("cfg-if", "0.1.2"), -// ("chrono", "0.4.0"), -// ("clap", "2.29.0"), -// ("clippy", "0.0.186"), -// ("clippy-mini-macro-test", "0.2.0"), -// ("clippy_lints", "0.0.186"), -// ("cmake", "0.1.29"), -// ("coco", "0.1.1"), -// ("commoncrypto", "0.2.0"), -// ("commoncrypto-sys", "0.2.0"), -// ("compiler_builtins", "0.0.0"), -// ("compiletest", "0.0.0"), -// ("compiletest_rs", "0.3.6"), -// ("completion", "0.1.0"), -// ("core", "0.0.0"), -// ("core-foundation", "0.4.6"), -// ("core-foundation-sys", "0.4.6"), -// ("crates-io", "0.15.0"), -// ("crossbeam", "0.2.12"), -// ("crossbeam", "0.3.2"), -// ("crypto-hash", "0.3.0"), -// ("curl", "0.4.11"), -// ("curl-sys", "0.4.1"), -// ("deglob", "0.1.0"), -// ("derive-new", "0.5.0"), -// ("diff", "0.1.11"), -// ("dlmalloc", "0.0.0"), -// ("docopt", "0.8.3"), -// ("dtoa", "0.4.2"), -// ("duct", "0.8.2"), -// ("either", "1.4.0"), -// ("endian-type", "0.1.2"), -// ("enum_primitive", "0.1.1"), -// ("env_logger", "0.3.5"), -// ("env_logger", "0.4.3"), -// ("env_logger", "0.5.3"), -// ("error-chain", "0.11.0"), -// ("error-chain", "0.8.1"), -// ("error_index_generator", "0.0.0"), -// ("failure", "0.1.1"), -// ("failure_derive", "0.1.1"), -// ("features", "0.1.0"), -// ("filetime", "0.1.15"), -// ("find_all_refs_no_cfg_test", "0.1.0"), -// ("find_impls", "0.1.0"), -// ("flate2", "1.0.1"), -// ("fmt_macros", "0.0.0"), -// ("fnv", "1.0.6"), -// ("foreign-types", "0.3.2"), -// ("foreign-types-shared", "0.1.1"), -// ("fs2", "0.4.3"), -// ("fuchsia-zircon", "0.3.3"), -// ("fuchsia-zircon-sys", "0.3.3"), -// ("futures", "0.1.17"), -// ("getopts", "0.2.15"), -// ("git2", "0.6.11"), -// ("git2-curl", "0.7.0"), -// ("glob", "0.2.11"), -// ("globset", "0.2.1"), -// ("graphviz", "0.0.0"), -// ("hamcrest", "0.1.1"), -// ("handlebars", "0.29.1"), -// ("hex", "0.2.0"), -// ("hex", "0.3.1"), -// ("home", "0.3.0"), -// ("idna", "0.1.4"), -// ("if_chain", "0.1.2"), -// ("ignore", "0.3.1"), -// ("infer_bin", "0.1.0"), -// ("infer_custom_bin", "0.1.0"), -// ("infer_lib", "0.1.0"), -// ("installer", "0.0.0"), -// ("is-match", "0.1.0"), -// ("itertools", "0.6.5"), -// ("itertools", "0.7.6"), -// ("itoa", "0.3.4"), -// ("jobserver", "0.1.9"), -// ("json", "0.11.12"), -// ("jsonrpc-core", "8.0.1"), -// ("kernel32-sys", "0.2.2"), -// ("languageserver-types", "0.30.0"), -// ("lazy_static", "0.2.11"), -// ("lazy_static", "1.0.0"), -// ("lazycell", "0.5.1"), -// ("libc", "0.0.0"), -// ("libc", "0.2.36"), -// ("libgit2-sys", "0.6.19"), -// ("libssh2-sys", "0.2.6"), -// ("libz-sys", "1.0.18"), -// ("linkchecker", "0.1.0"), -// ("log", "0.3.9"), -// ("log", "0.4.1"), -// ("log_settings", "0.1.1"), -// ("lzma-sys", "0.1.9"), -// ("matches", "0.1.6"), -// ("mdbook", "0.1.2"), -// ("memchr", "0.1.11"), -// ("memchr", "2.0.1"), -// ("miniz-sys", "0.1.10"), -// ("miow", "0.2.1"), -// ("miri", "0.1.0"), -// ("multiple_bins", "0.1.0"), -// ("net2", "0.2.31"), -// ("nibble_vec", "0.0.3"), -// ("nix", "0.8.1"), -// ("num", "0.1.41"), -// ("num-bigint", "0.1.41"), -// ("num-complex", "0.1.41"), -// ("num-integer", "0.1.35"), -// ("num-iter", "0.1.34"), -// ("num-rational", "0.1.40"), -// ("num-traits", "0.1.41"), -// ("num_cpus", "1.8.0"), -// ("open", "1.2.1"), -// ("openssl", "0.9.23"), -// ("openssl-probe", "0.1.2"), -// ("openssl-sys", "0.9.24"), -// ("os_pipe", "0.5.1"), -// ("owning_ref", "0.3.3"), -// ("panic_abort", "0.0.0"), -// ("panic_unwind", "0.0.0"), -// ("parking_lot", "0.5.3"), -// ("parking_lot_core", "0.2.9"), -// ("percent-encoding", "1.0.1"), -// ("pest", "0.3.3"), -// ("pkg-config", "0.3.9"), -// ("proc_macro", "0.0.0"), -// ("profiler_builtins", "0.0.0"), -// ("pulldown-cmark", "0.0.15"), -// ("pulldown-cmark", "0.1.0"), -// ("quick-error", "1.2.1"), -// ("quine-mc_cluskey", "0.2.4"), -// ("quote", "0.3.15"), -// ("racer", "2.0.12"), -// ("radix_trie", "0.1.2"), -// ("rand", "0.3.20"), -// ("rayon", "0.9.0"), -// ("rayon-core", "1.3.0"), -// ("redox_syscall", "0.1.37"), -// ("redox_termios", "0.1.1"), -// ("reformat", "0.1.0"), -// ("reformat_with_range", "0.1.0"), -// ("regex", "0.1.80"), -// ("regex", "0.2.5"), -// ("regex-syntax", "0.3.9"), -// ("regex-syntax", "0.4.2"), -// ("remote-test-client", "0.1.0"), -// ("remote-test-server", "0.1.0"), -// ("rls", "0.125.0"), -// ("rls-analysis", "0.11.0"), -// ("rls-blacklist", "0.1.0"), -// ("rls-data", "0.15.0"), -// ("rls-rustc", "0.2.1"), -// ("rls-span", "0.4.0"), -// ("rls-vfs", "0.4.4"), -// ("rustbook", "0.1.0"), -// ("rustc", "0.0.0"), -// ("rustc-ap-rustc_cratesio_shim", "29.0.0"), -// ("rustc-ap-rustc_data_structures", "29.0.0"), -// ("rustc-ap-rustc_errors", "29.0.0"), -// ("rustc-ap-serialize", "29.0.0"), -// ("rustc-ap-syntax", "29.0.0"), -// ("rustc-ap-syntax_pos", "29.0.0"), -// ("rustc-demangle", "0.1.5"), -// ("rustc-main", "0.0.0"), -// ("rustc-serialize", "0.3.24"), -// ("rustc_allocator", "0.0.0"), -// ("rustc_apfloat", "0.0.0"), -// ("rustc_asan", "0.0.0"), -// ("rustc_back", "0.0.0"), -// ("rustc_binaryen", "0.0.0"), -// ("rustc_borrowck", "0.0.0"), -// ("rustc_const_eval", "0.0.0"), -// ("rustc_const_math", "0.0.0"), -// ("rustc_cratesio_shim", "0.0.0"), -// ("rustc_data_structures", "0.0.0"), -// ("rustc_driver", "0.0.0"), -// ("rustc_errors", "0.0.0"), -// ("rustc_incremental", "0.0.0"), -// ("rustc_lint", "0.0.0"), -// ("rustc_llvm", "0.0.0"), -// ("rustc_lsan", "0.0.0"), -// ("rustc_metadata", "0.0.0"), -// ("rustc_mir", "0.0.0"), -// ("rustc_msan", "0.0.0"), -// ("rustc_passes", "0.0.0"), -// ("rustc_platform_intrinsics", "0.0.0"), -// ("rustc_plugin", "0.0.0"), -// ("rustc_privacy", "0.0.0"), -// ("rustc_resolve", "0.0.0"), -// ("rustc_save_analysis", "0.0.0"), -// ("rustc_trans", "0.0.0"), -// ("rustc_trans_utils", "0.0.0"), -// ("rustc_tsan", "0.0.0"), -// ("rustc_typeck", "0.0.0"), -// ("rustdoc", "0.0.0"), -// ("rustdoc-themes", "0.1.0"), -// ("rustdoc-tool", "0.0.0"), -// ("rustfmt-nightly", "0.3.8"), -// ("same-file", "0.1.3"), -// ("same-file", "1.0.2"), -// ("schannel", "0.1.10"), -// ("scoped-tls", "0.1.0"), -// ("scopeguard", "0.1.2"), -// ("scopeguard", "0.3.3"), -// ("semver", "0.6.0"), -// ("semver", "0.8.0"), -// ("semver", "0.9.0"), -// ("semver-parser", "0.7.0"), -// ("serde", "1.0.27"), -// ("serde_derive", "1.0.27"), -// ("serde_derive_internals", "0.19.0"), -// ("serde_ignored", "0.0.4"), -// ("serde_json", "1.0.9"), -// ("serialize", "0.0.0"), -// ("shared_child", "0.2.1"), -// ("shell-escape", "0.1.3"), -// ("shlex", "0.1.1"), -// ("smallvec", "0.6.0"), -// ("socket2", "0.3.0"), -// ("stable_deref_trait", "1.0.0"), -// ("std", "0.0.0"), -// ("std_unicode", "0.0.0"), -// ("strsim", "0.6.0"), -// ("syn", "0.11.11"), -// ("synom", "0.11.3"), -// ("synstructure", "0.6.1"), -// ("syntax", "0.0.0"), -// ("syntax_ext", "0.0.0"), -// ("syntax_pos", "0.0.0"), -// ("syntex_errors", "0.52.0"), -// ("syntex_pos", "0.52.0"), -// ("syntex_syntax", "0.52.0"), -// ("tar", "0.4.14"), -// ("tempdir", "0.3.5"), -// ("term", "0.0.0"), -// ("term", "0.4.6"), -// ("termcolor", "0.3.3"), -// ("termion", "1.5.1"), -// ("test", "0.0.0"), -// ("textwrap", "0.9.0"), -// ("thread-id", "2.0.0"), -// ("thread_local", "0.2.7"), -// ("thread_local", "0.3.5"), -// ("tidy", "0.1.0"), -// ("time", "0.1.39"), -// ("toml", "0.2.1"), -// ("toml", "0.4.5"), -// ("toml-query", "0.6.0"), -// ("unicode-bidi", "0.3.4"), -// ("unicode-normalization", "0.1.5"), -// ("unicode-segmentation", "1.2.0"), -// ("unicode-width", "0.1.4"), -// ("unicode-xid", "0.0.3"), -// ("unicode-xid", "0.0.4"), -// ("unreachable", "1.0.0"), -// ("unstable-book-gen", "0.1.0"), -// ("unwind", "0.0.0"), -// ("url", "1.6.0"), -// ("url_serde", "0.2.0"), -// ("userenv-sys", "0.2.0"), -// ("utf8-ranges", "0.1.3"), -// ("utf8-ranges", "1.0.0"), -// ("vcpkg", "0.2.2"), -// ("vec_map", "0.8.0"), -// ("void", "1.0.2"), -// ("walkdir", "1.0.7"), -// ("walkdir", "2.0.1"), -// ("winapi", "0.2.8"), -// ("winapi", "0.3.4"), -// ("winapi-build", "0.1.1"), -// ("winapi-i686-pc-windows-gnu", "0.4.0"), -// ("winapi-x86_64-pc-windows-gnu", "0.4.0"), -// ("wincolor", "0.1.4"), -// ("workspace_symbol", "0.1.0"), -// ("ws2_32-sys", "0.2.1"), -// ("xattr", "0.1.11"), -// ("xz2", "0.1.4"), -// ("yaml-rust", "0.3.5"), +/// Which crates to check against the whitelist? +static WHITELIST_CRATES: &'static [Crate] = + &[Crate("rustc", "0.0.0"), Crate("rustc_trans", "0.0.0")]; + +/// Whitelist of crates rustc is allowed to depend on. Avoid adding to the list if possible. +static WHITELIST: &'static [Crate] = &[ +// Crate("ar", "0.3.1"), +// Crate("arena", "0.0.0"), +// Crate("backtrace", "0.3.5"), +// Crate("backtrace-sys", "0.1.16"), +// Crate("bitflags", "1.0.1"), +// Crate("build_helper", "0.1.0"), +// Crate("byteorder", "1.2.1"), +// Crate("cc", "1.0.4"), +// Crate("cfg-if", "0.1.2"), +// Crate("cmake", "0.1.29"), +// Crate("filetime", "0.1.15"), +// Crate("flate2", "1.0.1"), +// Crate("fmt_macros", "0.0.0"), +// Crate("fuchsia-zircon", "0.3.3"), +// Crate("fuchsia-zircon-sys", "0.3.3"), +// Crate("graphviz", "0.0.0"), +// Crate("jobserver", "0.1.9"), +// Crate("kernel32-sys", "0.2.2"), +// Crate("lazy_static", "0.2.11"), +// Crate("libc", "0.2.36"), +// Crate("log", "0.4.1"), +// Crate("log_settings", "0.1.1"), +// Crate("miniz-sys", "0.1.10"), +// Crate("num_cpus", "1.8.0"), +// Crate("owning_ref", "0.3.3"), +// Crate("parking_lot", "0.5.3"), +// Crate("parking_lot_core", "0.2.9"), +// Crate("rand", "0.3.20"), +// Crate("redox_syscall", "0.1.37"), +// Crate("rustc", "0.0.0"), +// Crate("rustc-demangle", "0.1.5"), +// Crate("rustc_allocator", "0.0.0"), +// Crate("rustc_apfloat", "0.0.0"), +// Crate("rustc_back", "0.0.0"), +// Crate("rustc_binaryen", "0.0.0"), +// Crate("rustc_const_eval", "0.0.0"), +// Crate("rustc_const_math", "0.0.0"), +// Crate("rustc_cratesio_shim", "0.0.0"), +// Crate("rustc_data_structures", "0.0.0"), +// Crate("rustc_errors", "0.0.0"), +// Crate("rustc_incremental", "0.0.0"), +// Crate("rustc_llvm", "0.0.0"), +// Crate("rustc_mir", "0.0.0"), +// Crate("rustc_platform_intrinsics", "0.0.0"), +// Crate("rustc_trans", "0.0.0"), +// Crate("rustc_trans_utils", "0.0.0"), +// Crate("serialize", "0.0.0"), +// Crate("smallvec", "0.6.0"), +// Crate("stable_deref_trait", "1.0.0"), +// Crate("syntax", "0.0.0"), +// Crate("syntax_pos", "0.0.0"), +// Crate("tempdir", "0.3.5"), +// Crate("unicode-width", "0.1.4"), +// Crate("winapi", "0.2.8"), +// Crate("winapi", "0.3.4"), +// Crate("winapi-build", "0.1.1"), +// Crate("winapi-i686-pc-windows-gnu", "0.4.0"), +// Crate("winapi-x86_64-pc-windows-gnu", "0.4.0"), ]; // Some types for Serde to deserialize the output of `cargo metadata` to... #[derive(Deserialize)] struct Output { - packages: Vec, + resolve: Resolve, // Not used, but needed to not confuse serde :P - #[allow(dead_code)] resolve: Resolve, -} - -#[derive(Deserialize)] -struct Package { - name: String, - version: String, - - // Not used, but needed to not confuse serde :P - #[allow(dead_code)] id: String, - #[allow(dead_code)] source: Option, - #[allow(dead_code)] manifest_path: String, + #[allow(dead_code)] packages: Vec, } // Not used, but needed to not confuse serde :P #[allow(dead_code)] +#[derive(Deserialize)] +struct Package { + name: String, + version: String, + id: String, + source: Option, + manifest_path: String, +} + #[derive(Deserialize)] struct Resolve { nodes: Vec, } -// Not used, but needed to not confuse serde :P -#[allow(dead_code)] #[derive(Deserialize)] struct ResolveNode { id: String, dependencies: Vec, } +/// A unique identifier for a crate +#[derive(Copy, Clone, PartialOrd, Ord, PartialEq, Eq, Debug, Hash)] +struct Crate<'a>(&'a str, &'a str); // (name, version) + +impl<'a> Crate<'a> { + pub fn from_str(s: &'a str) -> Self { + let mut parts = s.split(" "); + let name = parts.next().unwrap(); + let version = parts.next().unwrap(); + + Crate(name, version) + } + + pub fn id_str(&self) -> String { + format!("{} {}", self.0, self.1) + } +} + /// Checks the dependency at the given path. Changes `bad` to `true` if a check failed. /// /// Specifically, this checks that the license is correct. @@ -423,25 +192,27 @@ pub fn check(path: &Path, bad: &mut bool) { assert!(saw_dir, "no vendored source"); } -/// Checks the dependency at the given path. Changes `bad` to `true` if a check failed. +/// Checks the dependency of WHITELIST_CRATES at the given path. Changes `bad` to `true` if a check +/// failed. /// -/// Specifically, this checks that the dependencies are on the whitelist. +/// Specifically, this checks that the dependencies are on the WHITELIST. pub fn check_whitelist(path: &Path, cargo: &Path, bad: &mut bool) { - // Check dependencies - let deps: HashSet<_> = get_deps(&path, &cargo) - .into_iter() - .map(|Package { name, version, .. }| (name, version)) - .collect(); - let whitelist: HashSet<(String, String)> = WHITELIST - .iter() - .map(|&(n, v)| (n.to_owned(), v.to_owned())) - .collect(); + // Get dependencies from cargo metadata + let resolve = get_deps(path, cargo); - // Dependencies not in the whitelist - let mut unapproved: Vec<_> = deps.difference(&whitelist).collect(); + // Get the whitelist into a convenient form + let whitelist: HashSet<_> = WHITELIST.iter().cloned().collect(); + + // Check dependencies + let mut unapproved = Vec::new(); + for &krate in WHITELIST_CRATES.iter() { + let mut bad = check_crate_whitelist(&whitelist, &resolve, krate); + unapproved.append(&mut bad); + } // For ease of reading - unapproved.sort(); + unapproved.sort_unstable(); + unapproved.dedup(); if unapproved.len() > 0 { println!("Dependencies not on the whitelist:"); @@ -492,7 +263,7 @@ fn extract_license(line: &str) -> String { } /// Get the dependencies of the crate at the given path using `cargo metadata`. -fn get_deps(path: &Path, cargo: &Path) -> Vec { +fn get_deps(path: &Path, cargo: &Path) -> Resolve { // Run `cargo metadata` to get the set of dependencies let output = Command::new(cargo) .arg("metadata") @@ -506,5 +277,41 @@ fn get_deps(path: &Path, cargo: &Path) -> Vec { let output = String::from_utf8_lossy(&output); let output: Output = serde_json::from_str(&output).unwrap(); - output.packages + output.resolve +} + +/// Checks the dependencies of the given crate from the given cargo metadata to see if they are on +/// the whitelist. Returns a list of illegal dependencies. +fn check_crate_whitelist<'a>( + whitelist: &'a HashSet, + resolve: &'a Resolve, + krate: Crate<'a>, +) -> Vec> { + // Will contain bad deps + let mut unapproved = Vec::new(); + + // If this dependency is not on the WHITELIST, add to bad set + if !whitelist.contains(&krate) { + unapproved.push(krate); + } + + // Do a DFS in the crate graph (it's a DAG, so we know we have no cycles!) + let to_check = resolve + .nodes + .iter() + .find(|n| n.id.starts_with(&krate.id_str())) + .expect("crate does not exist"); + + for dep in to_check.dependencies.iter() { + let krate = Crate::from_str(dep); + let mut bad = check_crate_whitelist(whitelist, resolve, krate); + + unapproved.append(&mut bad); + } + + // Remove duplicates + unapproved.sort_unstable(); + unapproved.dedup(); + + unapproved } From e3a374ac7d1c166e963981aff3b59c37eb7270a6 Mon Sep 17 00:00:00 2001 From: Mark Mansi Date: Tue, 27 Feb 2018 12:02:54 -0600 Subject: [PATCH 49/68] Fix alexcrichton's comments --- src/tools/tidy/src/deps.rs | 172 +++++++++++++++++-------------------- 1 file changed, 77 insertions(+), 95 deletions(-) diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index 0d351c9e7350..97cb8ed45b91 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -10,7 +10,7 @@ //! Check license of third-party deps by inspecting src/vendor -use std::collections::HashSet; +use std::collections::{BTreeSet, HashSet}; use std::fs::File; use std::io::Read; use std::path::Path; @@ -49,69 +49,65 @@ static EXCEPTIONS: &'static [&'static str] = &[ ]; /// Which crates to check against the whitelist? -static WHITELIST_CRATES: &'static [Crate] = - &[Crate("rustc", "0.0.0"), Crate("rustc_trans", "0.0.0")]; +static WHITELIST_CRATES: &'static [Crate] = &[Crate("rustc"), Crate("rustc_trans")]; /// Whitelist of crates rustc is allowed to depend on. Avoid adding to the list if possible. static WHITELIST: &'static [Crate] = &[ -// Crate("ar", "0.3.1"), -// Crate("arena", "0.0.0"), -// Crate("backtrace", "0.3.5"), -// Crate("backtrace-sys", "0.1.16"), -// Crate("bitflags", "1.0.1"), -// Crate("build_helper", "0.1.0"), -// Crate("byteorder", "1.2.1"), -// Crate("cc", "1.0.4"), -// Crate("cfg-if", "0.1.2"), -// Crate("cmake", "0.1.29"), -// Crate("filetime", "0.1.15"), -// Crate("flate2", "1.0.1"), -// Crate("fmt_macros", "0.0.0"), -// Crate("fuchsia-zircon", "0.3.3"), -// Crate("fuchsia-zircon-sys", "0.3.3"), -// Crate("graphviz", "0.0.0"), -// Crate("jobserver", "0.1.9"), -// Crate("kernel32-sys", "0.2.2"), -// Crate("lazy_static", "0.2.11"), -// Crate("libc", "0.2.36"), -// Crate("log", "0.4.1"), -// Crate("log_settings", "0.1.1"), -// Crate("miniz-sys", "0.1.10"), -// Crate("num_cpus", "1.8.0"), -// Crate("owning_ref", "0.3.3"), -// Crate("parking_lot", "0.5.3"), -// Crate("parking_lot_core", "0.2.9"), -// Crate("rand", "0.3.20"), -// Crate("redox_syscall", "0.1.37"), -// Crate("rustc", "0.0.0"), -// Crate("rustc-demangle", "0.1.5"), -// Crate("rustc_allocator", "0.0.0"), -// Crate("rustc_apfloat", "0.0.0"), -// Crate("rustc_back", "0.0.0"), -// Crate("rustc_binaryen", "0.0.0"), -// Crate("rustc_const_eval", "0.0.0"), -// Crate("rustc_const_math", "0.0.0"), -// Crate("rustc_cratesio_shim", "0.0.0"), -// Crate("rustc_data_structures", "0.0.0"), -// Crate("rustc_errors", "0.0.0"), -// Crate("rustc_incremental", "0.0.0"), -// Crate("rustc_llvm", "0.0.0"), -// Crate("rustc_mir", "0.0.0"), -// Crate("rustc_platform_intrinsics", "0.0.0"), -// Crate("rustc_trans", "0.0.0"), -// Crate("rustc_trans_utils", "0.0.0"), -// Crate("serialize", "0.0.0"), -// Crate("smallvec", "0.6.0"), -// Crate("stable_deref_trait", "1.0.0"), -// Crate("syntax", "0.0.0"), -// Crate("syntax_pos", "0.0.0"), -// Crate("tempdir", "0.3.5"), -// Crate("unicode-width", "0.1.4"), -// Crate("winapi", "0.2.8"), -// Crate("winapi", "0.3.4"), -// Crate("winapi-build", "0.1.1"), -// Crate("winapi-i686-pc-windows-gnu", "0.4.0"), -// Crate("winapi-x86_64-pc-windows-gnu", "0.4.0"), +// Crate("ar "), +// Crate("arena "), +// Crate("backtrace "), +// Crate("backtrace-sys "), +// Crate("bitflags "), +// Crate("build_helper "), +// Crate("byteorder "), +// Crate("cc "), +// Crate("cfg-if "), +// Crate("cmake "), +// Crate("filetime "), +// Crate("flate2 "), +// Crate("fmt_macros "), +// Crate("fuchsia-zircon "), +// Crate("fuchsia-zircon-sys "), +// Crate("graphviz "), +// Crate("jobserver "), +// Crate("kernel32-sys "), +// Crate("lazy_static "), +// Crate("libc "), +// Crate("log "), +// Crate("log_settings "), +// Crate("miniz-sys "), +// Crate("num_cpus "), +// Crate("owning_ref "), +// Crate("parking_lot "), +// Crate("parking_lot_core "), +// Crate("rand "), +// Crate("redox_syscall "), +// Crate("rustc "), +// Crate("rustc-demangle "), +// Crate("rustc_allocator "), +// Crate("rustc_apfloat "), +// Crate("rustc_back "), +// Crate("rustc_binaryen "), +// Crate("rustc_const_eval "), +// Crate("rustc_const_math "), +// Crate("rustc_cratesio_shim "), +// Crate("rustc_data_structures "), +// Crate("rustc_errors "), +// Crate("rustc_incremental "), +// Crate("rustc_llvm "), +// Crate("rustc_mir "), +// Crate("rustc_platform_intrinsics "), +// Crate("rustc_trans "), +// Crate("rustc_trans_utils "), +// Crate("serialize "), +// Crate("smallvec "), +// Crate("stable_deref_trait "), +// Crate("syntax "), +// Crate("syntax_pos "), +// Crate("tempdir "), +// Crate("unicode-width "), +// Crate("winapi "), +// Crate("winapi-build"), ]; // Some types for Serde to deserialize the output of `cargo metadata` to... @@ -119,20 +115,6 @@ static WHITELIST: &'static [Crate] = &[ #[derive(Deserialize)] struct Output { resolve: Resolve, - - // Not used, but needed to not confuse serde :P - #[allow(dead_code)] packages: Vec, -} - -// Not used, but needed to not confuse serde :P -#[allow(dead_code)] -#[derive(Deserialize)] -struct Package { - name: String, - version: String, - id: String, - source: Option, - manifest_path: String, } #[derive(Deserialize)] @@ -148,19 +130,18 @@ struct ResolveNode { /// A unique identifier for a crate #[derive(Copy, Clone, PartialOrd, Ord, PartialEq, Eq, Debug, Hash)] -struct Crate<'a>(&'a str, &'a str); // (name, version) +struct Crate<'a>(&'a str); // (name,) impl<'a> Crate<'a> { pub fn from_str(s: &'a str) -> Self { let mut parts = s.split(" "); let name = parts.next().unwrap(); - let version = parts.next().unwrap(); - Crate(name, version) + Crate(name) } pub fn id_str(&self) -> String { - format!("{} {}", self.0, self.1) + format!("{} ", self.0) } } @@ -204,20 +185,17 @@ pub fn check_whitelist(path: &Path, cargo: &Path, bad: &mut bool) { let whitelist: HashSet<_> = WHITELIST.iter().cloned().collect(); // Check dependencies - let mut unapproved = Vec::new(); + let mut visited = BTreeSet::new(); + let mut unapproved = BTreeSet::new(); for &krate in WHITELIST_CRATES.iter() { - let mut bad = check_crate_whitelist(&whitelist, &resolve, krate); + let mut bad = check_crate_whitelist(&whitelist, &resolve, &mut visited, krate); unapproved.append(&mut bad); } - // For ease of reading - unapproved.sort_unstable(); - unapproved.dedup(); - if unapproved.len() > 0 { println!("Dependencies not on the whitelist:"); for dep in unapproved { - println!("* {} {}", dep.0, dep.1); // name version + println!("* {}", dep.id_str()); } *bad = true; } @@ -282,17 +260,25 @@ fn get_deps(path: &Path, cargo: &Path) -> Resolve { /// Checks the dependencies of the given crate from the given cargo metadata to see if they are on /// the whitelist. Returns a list of illegal dependencies. -fn check_crate_whitelist<'a>( +fn check_crate_whitelist<'a, 'b>( whitelist: &'a HashSet, resolve: &'a Resolve, + visited: &'b mut BTreeSet>, krate: Crate<'a>, -) -> Vec> { +) -> BTreeSet> { // Will contain bad deps - let mut unapproved = Vec::new(); + let mut unapproved = BTreeSet::new(); + + // Check if we have already visited this crate + if visited.contains(&krate) { + return unapproved; + } + + visited.insert(krate); // If this dependency is not on the WHITELIST, add to bad set if !whitelist.contains(&krate) { - unapproved.push(krate); + unapproved.insert(krate); } // Do a DFS in the crate graph (it's a DAG, so we know we have no cycles!) @@ -304,14 +290,10 @@ fn check_crate_whitelist<'a>( for dep in to_check.dependencies.iter() { let krate = Crate::from_str(dep); - let mut bad = check_crate_whitelist(whitelist, resolve, krate); + let mut bad = check_crate_whitelist(whitelist, resolve, visited, krate); unapproved.append(&mut bad); } - // Remove duplicates - unapproved.sort_unstable(); - unapproved.dedup(); - unapproved } From f89abd63ca10662439692dd085a52b5757bc3259 Mon Sep 17 00:00:00 2001 From: Mark Mansi Date: Tue, 27 Feb 2018 12:47:49 -0600 Subject: [PATCH 50/68] uncomment whitelist --- src/tools/tidy/src/deps.rs | 110 ++++++++++++++++++------------------- 1 file changed, 55 insertions(+), 55 deletions(-) diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index 97cb8ed45b91..cd089b70d779 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -53,61 +53,61 @@ static WHITELIST_CRATES: &'static [Crate] = &[Crate("rustc"), Crate("rustc_trans /// Whitelist of crates rustc is allowed to depend on. Avoid adding to the list if possible. static WHITELIST: &'static [Crate] = &[ -// Crate("ar "), -// Crate("arena "), -// Crate("backtrace "), -// Crate("backtrace-sys "), -// Crate("bitflags "), -// Crate("build_helper "), -// Crate("byteorder "), -// Crate("cc "), -// Crate("cfg-if "), -// Crate("cmake "), -// Crate("filetime "), -// Crate("flate2 "), -// Crate("fmt_macros "), -// Crate("fuchsia-zircon "), -// Crate("fuchsia-zircon-sys "), -// Crate("graphviz "), -// Crate("jobserver "), -// Crate("kernel32-sys "), -// Crate("lazy_static "), -// Crate("libc "), -// Crate("log "), -// Crate("log_settings "), -// Crate("miniz-sys "), -// Crate("num_cpus "), -// Crate("owning_ref "), -// Crate("parking_lot "), -// Crate("parking_lot_core "), -// Crate("rand "), -// Crate("redox_syscall "), -// Crate("rustc "), -// Crate("rustc-demangle "), -// Crate("rustc_allocator "), -// Crate("rustc_apfloat "), -// Crate("rustc_back "), -// Crate("rustc_binaryen "), -// Crate("rustc_const_eval "), -// Crate("rustc_const_math "), -// Crate("rustc_cratesio_shim "), -// Crate("rustc_data_structures "), -// Crate("rustc_errors "), -// Crate("rustc_incremental "), -// Crate("rustc_llvm "), -// Crate("rustc_mir "), -// Crate("rustc_platform_intrinsics "), -// Crate("rustc_trans "), -// Crate("rustc_trans_utils "), -// Crate("serialize "), -// Crate("smallvec "), -// Crate("stable_deref_trait "), -// Crate("syntax "), -// Crate("syntax_pos "), -// Crate("tempdir "), -// Crate("unicode-width "), -// Crate("winapi "), -// Crate("winapi-build"), + Crate("ar "), + Crate("arena "), + Crate("backtrace "), + Crate("backtrace-sys "), + Crate("bitflags "), + Crate("build_helper "), + Crate("byteorder "), + Crate("cc "), + Crate("cfg-if "), + Crate("cmake "), + Crate("filetime "), + Crate("flate2 "), + Crate("fmt_macros "), + Crate("fuchsia-zircon "), + Crate("fuchsia-zircon-sys "), + Crate("graphviz "), + Crate("jobserver "), + Crate("kernel32-sys "), + Crate("lazy_static "), + Crate("libc "), + Crate("log "), + Crate("log_settings "), + Crate("miniz-sys "), + Crate("num_cpus "), + Crate("owning_ref "), + Crate("parking_lot "), + Crate("parking_lot_core "), + Crate("rand "), + Crate("redox_syscall "), + Crate("rustc "), + Crate("rustc-demangle "), + Crate("rustc_allocator "), + Crate("rustc_apfloat "), + Crate("rustc_back "), + Crate("rustc_binaryen "), + Crate("rustc_const_eval "), + Crate("rustc_const_math "), + Crate("rustc_cratesio_shim "), + Crate("rustc_data_structures "), + Crate("rustc_errors "), + Crate("rustc_incremental "), + Crate("rustc_llvm "), + Crate("rustc_mir "), + Crate("rustc_platform_intrinsics "), + Crate("rustc_trans "), + Crate("rustc_trans_utils "), + Crate("serialize "), + Crate("smallvec "), + Crate("stable_deref_trait "), + Crate("syntax "), + Crate("syntax_pos "), + Crate("tempdir "), + Crate("unicode-width "), + Crate("winapi "), + Crate("winapi-build"), ]; // Some types for Serde to deserialize the output of `cargo metadata` to... From 489f2f1206fbae4da67bdcbae70cd896f0537a46 Mon Sep 17 00:00:00 2001 From: Mark Mansi Date: Tue, 27 Feb 2018 12:50:34 -0600 Subject: [PATCH 51/68] Remove spurious whitespace --- src/tools/tidy/src/deps.rs | 108 ++++++++++++++++++------------------- 1 file changed, 54 insertions(+), 54 deletions(-) diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index cd089b70d779..8cfba21eb6d8 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -53,60 +53,60 @@ static WHITELIST_CRATES: &'static [Crate] = &[Crate("rustc"), Crate("rustc_trans /// Whitelist of crates rustc is allowed to depend on. Avoid adding to the list if possible. static WHITELIST: &'static [Crate] = &[ - Crate("ar "), - Crate("arena "), - Crate("backtrace "), - Crate("backtrace-sys "), - Crate("bitflags "), - Crate("build_helper "), - Crate("byteorder "), - Crate("cc "), - Crate("cfg-if "), - Crate("cmake "), - Crate("filetime "), - Crate("flate2 "), - Crate("fmt_macros "), - Crate("fuchsia-zircon "), - Crate("fuchsia-zircon-sys "), - Crate("graphviz "), - Crate("jobserver "), - Crate("kernel32-sys "), - Crate("lazy_static "), - Crate("libc "), - Crate("log "), - Crate("log_settings "), - Crate("miniz-sys "), - Crate("num_cpus "), - Crate("owning_ref "), - Crate("parking_lot "), - Crate("parking_lot_core "), - Crate("rand "), - Crate("redox_syscall "), - Crate("rustc "), - Crate("rustc-demangle "), - Crate("rustc_allocator "), - Crate("rustc_apfloat "), - Crate("rustc_back "), - Crate("rustc_binaryen "), - Crate("rustc_const_eval "), - Crate("rustc_const_math "), - Crate("rustc_cratesio_shim "), - Crate("rustc_data_structures "), - Crate("rustc_errors "), - Crate("rustc_incremental "), - Crate("rustc_llvm "), - Crate("rustc_mir "), - Crate("rustc_platform_intrinsics "), - Crate("rustc_trans "), - Crate("rustc_trans_utils "), - Crate("serialize "), - Crate("smallvec "), - Crate("stable_deref_trait "), - Crate("syntax "), - Crate("syntax_pos "), - Crate("tempdir "), - Crate("unicode-width "), - Crate("winapi "), + Crate("ar"), + Crate("arena"), + Crate("backtrace"), + Crate("backtrace-sys"), + Crate("bitflags"), + Crate("build_helper"), + Crate("byteorder"), + Crate("cc"), + Crate("cfg-if"), + Crate("cmake"), + Crate("filetime"), + Crate("flate2"), + Crate("fmt_macros"), + Crate("fuchsia-zircon"), + Crate("fuchsia-zircon-sys"), + Crate("graphviz"), + Crate("jobserver"), + Crate("kernel32-sys"), + Crate("lazy_static"), + Crate("libc"), + Crate("log"), + Crate("log_settings"), + Crate("miniz-sys"), + Crate("num_cpus"), + Crate("owning_ref"), + Crate("parking_lot"), + Crate("parking_lot_core"), + Crate("rand"), + Crate("redox_syscall"), + Crate("rustc"), + Crate("rustc-demangle"), + Crate("rustc_allocator"), + Crate("rustc_apfloat"), + Crate("rustc_back"), + Crate("rustc_binaryen"), + Crate("rustc_const_eval"), + Crate("rustc_const_math"), + Crate("rustc_cratesio_shim"), + Crate("rustc_data_structures"), + Crate("rustc_errors"), + Crate("rustc_incremental"), + Crate("rustc_llvm"), + Crate("rustc_mir"), + Crate("rustc_platform_intrinsics"), + Crate("rustc_trans"), + Crate("rustc_trans_utils"), + Crate("serialize"), + Crate("smallvec"), + Crate("stable_deref_trait"), + Crate("syntax"), + Crate("syntax_pos"), + Crate("tempdir"), + Crate("unicode-width"), + Crate("winapi"), Crate("winapi-build"), ]; From 0fc5daebfb4218312f0f2ee28de7c6bcd40b632c Mon Sep 17 00:00:00 2001 From: Mark Mansi Date: Tue, 27 Feb 2018 15:56:16 -0600 Subject: [PATCH 52/68] Add a few missing deps --- src/tools/tidy/src/deps.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index 8cfba21eb6d8..d63926ee3bd7 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -108,6 +108,9 @@ static WHITELIST: &'static [Crate] = &[ Crate("unicode-width"), Crate("winapi"), Crate("winapi-build"), + Crate("proc_macro"), + Crate("winapi-i686-pc-windows-gnu"), + Crate("winapi-x86_64-pc-windows-gnu"), ]; // Some types for Serde to deserialize the output of `cargo metadata` to... From 18f0533c4cf5e320df1f2e8724f98f550ca65130 Mon Sep 17 00:00:00 2001 From: Mark Mansi Date: Tue, 27 Feb 2018 18:33:55 -0600 Subject: [PATCH 53/68] different versions may have different deps --- src/tools/tidy/src/deps.rs | 150 +++++++++++++++++++++---------------- 1 file changed, 84 insertions(+), 66 deletions(-) diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index d63926ee3bd7..f0801b806ec6 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -49,68 +49,70 @@ static EXCEPTIONS: &'static [&'static str] = &[ ]; /// Which crates to check against the whitelist? -static WHITELIST_CRATES: &'static [Crate] = &[Crate("rustc"), Crate("rustc_trans")]; +static WHITELIST_CRATES: &'static [CrateVersion] = &[ + CrateVersion("rustc", "0.0.0"), + CrateVersion("rustc_trans", "0.0.0"), +]; /// Whitelist of crates rustc is allowed to depend on. Avoid adding to the list if possible. static WHITELIST: &'static [Crate] = &[ - Crate("ar"), - Crate("arena"), - Crate("backtrace"), - Crate("backtrace-sys"), - Crate("bitflags"), - Crate("build_helper"), - Crate("byteorder"), - Crate("cc"), - Crate("cfg-if"), - Crate("cmake"), - Crate("filetime"), - Crate("flate2"), - Crate("fmt_macros"), - Crate("fuchsia-zircon"), - Crate("fuchsia-zircon-sys"), - Crate("graphviz"), - Crate("jobserver"), - Crate("kernel32-sys"), - Crate("lazy_static"), - Crate("libc"), - Crate("log"), - Crate("log_settings"), - Crate("miniz-sys"), - Crate("num_cpus"), - Crate("owning_ref"), - Crate("parking_lot"), - Crate("parking_lot_core"), - Crate("rand"), - Crate("redox_syscall"), - Crate("rustc"), - Crate("rustc-demangle"), - Crate("rustc_allocator"), - Crate("rustc_apfloat"), - Crate("rustc_back"), - Crate("rustc_binaryen"), - Crate("rustc_const_eval"), - Crate("rustc_const_math"), - Crate("rustc_cratesio_shim"), - Crate("rustc_data_structures"), - Crate("rustc_errors"), - Crate("rustc_incremental"), - Crate("rustc_llvm"), - Crate("rustc_mir"), - Crate("rustc_platform_intrinsics"), - Crate("rustc_trans"), - Crate("rustc_trans_utils"), - Crate("serialize"), - Crate("smallvec"), - Crate("stable_deref_trait"), - Crate("syntax"), - Crate("syntax_pos"), - Crate("tempdir"), - Crate("unicode-width"), - Crate("winapi"), - Crate("winapi-build"), - Crate("proc_macro"), - Crate("winapi-i686-pc-windows-gnu"), - Crate("winapi-x86_64-pc-windows-gnu"), +// Crate("ar"), +// Crate("arena"), +// Crate("backtrace"), +// Crate("backtrace-sys"), +// Crate("bitflags"), +// Crate("build_helper"), +// Crate("byteorder"), +// Crate("cc"), +// Crate("cfg-if"), +// Crate("cmake"), +// Crate("filetime"), +// Crate("flate2"), +// Crate("fmt_macros"), +// Crate("fuchsia-zircon"), +// Crate("fuchsia-zircon-sys"), +// Crate("graphviz"), +// Crate("jobserver"), +// Crate("kernel32-sys"), +// Crate("lazy_static"), +// Crate("libc"), +// Crate("log"), +// Crate("log_settings"), +// Crate("miniz-sys"), +// Crate("num_cpus"), +// Crate("owning_ref"), +// Crate("parking_lot"), +// Crate("parking_lot_core"), +// Crate("rand"), +// Crate("redox_syscall"), +// Crate("rustc"), +// Crate("rustc-demangle"), +// Crate("rustc_allocator"), +// Crate("rustc_apfloat"), +// Crate("rustc_back"), +// Crate("rustc_binaryen"), +// Crate("rustc_const_eval"), +// Crate("rustc_const_math"), +// Crate("rustc_cratesio_shim"), +// Crate("rustc_data_structures"), +// Crate("rustc_errors"), +// Crate("rustc_incremental"), +// Crate("rustc_llvm"), +// Crate("rustc_mir"), +// Crate("rustc_platform_intrinsics"), +// Crate("rustc_trans"), +// Crate("rustc_trans_utils"), +// Crate("serialize"), +// Crate("smallvec"), +// Crate("stable_deref_trait"), +// Crate("syntax"), +// Crate("syntax_pos"), +// Crate("tempdir"), +// Crate("unicode-width"), +// Crate("winapi"), +// Crate("winapi-build"), +// Crate("winapi-i686-pc-windows-gnu"), +// Crate("winapi-x86_64-pc-windows-gnu"), ]; // Some types for Serde to deserialize the output of `cargo metadata` to... @@ -135,16 +137,32 @@ struct ResolveNode { #[derive(Copy, Clone, PartialOrd, Ord, PartialEq, Eq, Debug, Hash)] struct Crate<'a>(&'a str); // (name,) +#[derive(Copy, Clone, PartialOrd, Ord, PartialEq, Eq, Debug, Hash)] +struct CrateVersion<'a>(&'a str, &'a str); // (name, version) + impl<'a> Crate<'a> { + pub fn id_str(&self) -> String { + format!("{} ", self.0) + } +} + +impl<'a> CrateVersion<'a> { pub fn from_str(s: &'a str) -> Self { let mut parts = s.split(" "); let name = parts.next().unwrap(); + let version = parts.next().unwrap(); - Crate(name) + CrateVersion(name, version) } pub fn id_str(&self) -> String { - format!("{} ", self.0) + format!("{} {}", self.0, self.1) + } +} + +impl<'a> From> for Crate<'a> { + fn from(cv: CrateVersion<'a>) -> Crate<'a> { + Crate(cv.0) } } @@ -266,8 +284,8 @@ fn get_deps(path: &Path, cargo: &Path) -> Resolve { fn check_crate_whitelist<'a, 'b>( whitelist: &'a HashSet, resolve: &'a Resolve, - visited: &'b mut BTreeSet>, - krate: Crate<'a>, + visited: &'b mut BTreeSet>, + krate: CrateVersion<'a>, ) -> BTreeSet> { // Will contain bad deps let mut unapproved = BTreeSet::new(); @@ -280,8 +298,8 @@ fn check_crate_whitelist<'a, 'b>( visited.insert(krate); // If this dependency is not on the WHITELIST, add to bad set - if !whitelist.contains(&krate) { - unapproved.insert(krate); + if !whitelist.contains(&krate.into()) { + unapproved.insert(krate.into()); } // Do a DFS in the crate graph (it's a DAG, so we know we have no cycles!) @@ -292,7 +310,7 @@ fn check_crate_whitelist<'a, 'b>( .expect("crate does not exist"); for dep in to_check.dependencies.iter() { - let krate = Crate::from_str(dep); + let krate = CrateVersion::from_str(dep); let mut bad = check_crate_whitelist(whitelist, resolve, visited, krate); unapproved.append(&mut bad); From 1fca9e0430bba507d21b5373063d850ffe6d550b Mon Sep 17 00:00:00 2001 From: Mark Mansi Date: Wed, 28 Feb 2018 14:12:15 -0600 Subject: [PATCH 54/68] Don't check in-tree deps --- src/tools/tidy/src/deps.rs | 51 +++++++++----------------------------- 1 file changed, 12 insertions(+), 39 deletions(-) diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index f0801b806ec6..f22f8ac8efc7 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -56,61 +56,27 @@ static WHITELIST_CRATES: &'static [CrateVersion] = &[ /// Whitelist of crates rustc is allowed to depend on. Avoid adding to the list if possible. static WHITELIST: &'static [Crate] = &[ -// Crate("ar"), -// Crate("arena"), // Crate("backtrace"), // Crate("backtrace-sys"), // Crate("bitflags"), -// Crate("build_helper"), // Crate("byteorder"), // Crate("cc"), // Crate("cfg-if"), -// Crate("cmake"), -// Crate("filetime"), // Crate("flate2"), -// Crate("fmt_macros"), // Crate("fuchsia-zircon"), // Crate("fuchsia-zircon-sys"), -// Crate("graphviz"), // Crate("jobserver"), -// Crate("kernel32-sys"), // Crate("lazy_static"), // Crate("libc"), // Crate("log"), -// Crate("log_settings"), // Crate("miniz-sys"), // Crate("num_cpus"), -// Crate("owning_ref"), -// Crate("parking_lot"), -// Crate("parking_lot_core"), // Crate("rand"), -// Crate("redox_syscall"), // Crate("rustc"), // Crate("rustc-demangle"), -// Crate("rustc_allocator"), -// Crate("rustc_apfloat"), -// Crate("rustc_back"), -// Crate("rustc_binaryen"), -// Crate("rustc_const_eval"), -// Crate("rustc_const_math"), -// Crate("rustc_cratesio_shim"), -// Crate("rustc_data_structures"), -// Crate("rustc_errors"), -// Crate("rustc_incremental"), -// Crate("rustc_llvm"), -// Crate("rustc_mir"), -// Crate("rustc_platform_intrinsics"), // Crate("rustc_trans"), -// Crate("rustc_trans_utils"), -// Crate("serialize"), -// Crate("smallvec"), -// Crate("stable_deref_trait"), -// Crate("syntax"), -// Crate("syntax_pos"), // Crate("tempdir"), -// Crate("unicode-width"), // Crate("winapi"), -// Crate("winapi-build"), // Crate("winapi-i686-pc-windows-gnu"), // Crate("winapi-x86_64-pc-windows-gnu"), ]; @@ -147,12 +113,16 @@ impl<'a> Crate<'a> { } impl<'a> CrateVersion<'a> { - pub fn from_str(s: &'a str) -> Self { + /// Returns the struct and whether or not the dep is in-tree + pub fn from_str(s: &'a str) -> (Self, bool) { let mut parts = s.split(" "); let name = parts.next().unwrap(); let version = parts.next().unwrap(); + let path = parts.next().unwrap(); - CrateVersion(name, version) + let is_path_dep = path.starts_with("(path+"); + + (CrateVersion(name, version), is_path_dep) } pub fn id_str(&self) -> String { @@ -310,10 +280,13 @@ fn check_crate_whitelist<'a, 'b>( .expect("crate does not exist"); for dep in to_check.dependencies.iter() { - let krate = CrateVersion::from_str(dep); - let mut bad = check_crate_whitelist(whitelist, resolve, visited, krate); + let (krate, is_path_dep) = CrateVersion::from_str(dep); - unapproved.append(&mut bad); + // We don't check in-tree deps + if !is_path_dep { + let mut bad = check_crate_whitelist(whitelist, resolve, visited, krate); + unapproved.append(&mut bad); + } } unapproved From 6180a3f7da1fa8693344e96049f7400cd0d04088 Mon Sep 17 00:00:00 2001 From: Mark Mansi Date: Wed, 28 Feb 2018 14:25:34 -0600 Subject: [PATCH 55/68] enable whitelist --- src/tools/tidy/src/deps.rs | 46 +++++++++++++++++++------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index f22f8ac8efc7..4a76e2aaa164 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -56,29 +56,29 @@ static WHITELIST_CRATES: &'static [CrateVersion] = &[ /// Whitelist of crates rustc is allowed to depend on. Avoid adding to the list if possible. static WHITELIST: &'static [Crate] = &[ -// Crate("backtrace"), -// Crate("backtrace-sys"), -// Crate("bitflags"), -// Crate("byteorder"), -// Crate("cc"), -// Crate("cfg-if"), -// Crate("flate2"), -// Crate("fuchsia-zircon"), -// Crate("fuchsia-zircon-sys"), -// Crate("jobserver"), -// Crate("lazy_static"), -// Crate("libc"), -// Crate("log"), -// Crate("miniz-sys"), -// Crate("num_cpus"), -// Crate("rand"), -// Crate("rustc"), -// Crate("rustc-demangle"), -// Crate("rustc_trans"), -// Crate("tempdir"), -// Crate("winapi"), -// Crate("winapi-i686-pc-windows-gnu"), -// Crate("winapi-x86_64-pc-windows-gnu"), + Crate("backtrace"), + Crate("backtrace-sys"), + Crate("bitflags"), + Crate("byteorder"), + Crate("cc"), + Crate("cfg-if"), + Crate("flate2"), + Crate("fuchsia-zircon"), + Crate("fuchsia-zircon-sys"), + Crate("jobserver"), + Crate("lazy_static"), + Crate("libc"), + Crate("log"), + Crate("miniz-sys"), + Crate("num_cpus"), + Crate("rand"), + Crate("rustc"), + Crate("rustc-demangle"), + Crate("rustc_trans"), + Crate("tempdir"), + Crate("winapi"), + Crate("winapi-i686-pc-windows-gnu"), + Crate("winapi-x86_64-pc-windows-gnu"), ]; // Some types for Serde to deserialize the output of `cargo metadata` to... From bb01f3126d374f1448cfa3e19f2a1ca3bec8e8ce Mon Sep 17 00:00:00 2001 From: Mark Mansi Date: Wed, 28 Feb 2018 16:28:30 -0600 Subject: [PATCH 56/68] Do check the deps of path deps --- src/tools/tidy/src/deps.rs | 76 ++++++++++++++++++++++---------------- 1 file changed, 44 insertions(+), 32 deletions(-) diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index 4a76e2aaa164..0f3b09c29780 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -56,29 +56,40 @@ static WHITELIST_CRATES: &'static [CrateVersion] = &[ /// Whitelist of crates rustc is allowed to depend on. Avoid adding to the list if possible. static WHITELIST: &'static [Crate] = &[ - Crate("backtrace"), - Crate("backtrace-sys"), - Crate("bitflags"), - Crate("byteorder"), - Crate("cc"), - Crate("cfg-if"), - Crate("flate2"), - Crate("fuchsia-zircon"), - Crate("fuchsia-zircon-sys"), - Crate("jobserver"), - Crate("lazy_static"), - Crate("libc"), - Crate("log"), - Crate("miniz-sys"), - Crate("num_cpus"), - Crate("rand"), - Crate("rustc"), - Crate("rustc-demangle"), - Crate("rustc_trans"), - Crate("tempdir"), - Crate("winapi"), - Crate("winapi-i686-pc-windows-gnu"), - Crate("winapi-x86_64-pc-windows-gnu"), +// Crate("ar"), +// Crate("backtrace"), +// Crate("backtrace-sys"), +// Crate("bitflags"), +// Crate("byteorder"), +// Crate("cc"), +// Crate("cfg-if"), +// Crate("cmake"), +// Crate("filetime"), +// Crate("flate2"), +// Crate("fuchsia-zircon"), +// Crate("fuchsia-zircon-sys"), +// Crate("jobserver"), +// Crate("kernel32-sys"), +// Crate("lazy_static"), +// Crate("libc"), +// Crate("log"), +// Crate("log_settings"), +// Crate("miniz-sys"), +// Crate("num_cpus"), +// Crate("owning_ref"), +// Crate("parking_lot"), +// Crate("parking_lot_core"), +// Crate("rand"), +// Crate("redox_syscall"), +// Crate("rustc-demangle"), +// Crate("smallvec"), +// Crate("stable_deref_trait"), +// Crate("tempdir"), +// Crate("unicode-width"), +// Crate("winapi"), +// Crate("winapi-build"), +// Crate("winapi-i686-pc-windows-gnu"), +// Crate("winapi-x86_64-pc-windows-gnu"), ]; // Some types for Serde to deserialize the output of `cargo metadata` to... @@ -179,7 +190,7 @@ pub fn check_whitelist(path: &Path, cargo: &Path, bad: &mut bool) { let mut visited = BTreeSet::new(); let mut unapproved = BTreeSet::new(); for &krate in WHITELIST_CRATES.iter() { - let mut bad = check_crate_whitelist(&whitelist, &resolve, &mut visited, krate); + let mut bad = check_crate_whitelist(&whitelist, &resolve, &mut visited, krate, false); unapproved.append(&mut bad); } @@ -256,6 +267,7 @@ fn check_crate_whitelist<'a, 'b>( resolve: &'a Resolve, visited: &'b mut BTreeSet>, krate: CrateVersion<'a>, + must_be_on_whitelist: bool, ) -> BTreeSet> { // Will contain bad deps let mut unapproved = BTreeSet::new(); @@ -267,9 +279,12 @@ fn check_crate_whitelist<'a, 'b>( visited.insert(krate); - // If this dependency is not on the WHITELIST, add to bad set - if !whitelist.contains(&krate.into()) { - unapproved.insert(krate.into()); + // If this path is in-tree, we don't require it to be on the whitelist + if must_be_on_whitelist { + // If this dependency is not on the WHITELIST, add to bad set + if !whitelist.contains(&krate.into()) { + unapproved.insert(krate.into()); + } } // Do a DFS in the crate graph (it's a DAG, so we know we have no cycles!) @@ -282,11 +297,8 @@ fn check_crate_whitelist<'a, 'b>( for dep in to_check.dependencies.iter() { let (krate, is_path_dep) = CrateVersion::from_str(dep); - // We don't check in-tree deps - if !is_path_dep { - let mut bad = check_crate_whitelist(whitelist, resolve, visited, krate); - unapproved.append(&mut bad); - } + let mut bad = check_crate_whitelist(whitelist, resolve, visited, krate, !is_path_dep); + unapproved.append(&mut bad); } unapproved From 1423da8b9a62f6d9d9e90396a4c1f471ceb694d0 Mon Sep 17 00:00:00 2001 From: Who? Me?! Date: Thu, 1 Mar 2018 21:22:06 -0600 Subject: [PATCH 57/68] Uncomment whitelist --- src/tools/tidy/src/deps.rs | 68 +++++++++++++++++++------------------- 1 file changed, 34 insertions(+), 34 deletions(-) diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index 0f3b09c29780..aa46c6b7c4db 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -56,40 +56,40 @@ static WHITELIST_CRATES: &'static [CrateVersion] = &[ /// Whitelist of crates rustc is allowed to depend on. Avoid adding to the list if possible. static WHITELIST: &'static [Crate] = &[ -// Crate("ar"), -// Crate("backtrace"), -// Crate("backtrace-sys"), -// Crate("bitflags"), -// Crate("byteorder"), -// Crate("cc"), -// Crate("cfg-if"), -// Crate("cmake"), -// Crate("filetime"), -// Crate("flate2"), -// Crate("fuchsia-zircon"), -// Crate("fuchsia-zircon-sys"), -// Crate("jobserver"), -// Crate("kernel32-sys"), -// Crate("lazy_static"), -// Crate("libc"), -// Crate("log"), -// Crate("log_settings"), -// Crate("miniz-sys"), -// Crate("num_cpus"), -// Crate("owning_ref"), -// Crate("parking_lot"), -// Crate("parking_lot_core"), -// Crate("rand"), -// Crate("redox_syscall"), -// Crate("rustc-demangle"), -// Crate("smallvec"), -// Crate("stable_deref_trait"), -// Crate("tempdir"), -// Crate("unicode-width"), -// Crate("winapi"), -// Crate("winapi-build"), -// Crate("winapi-i686-pc-windows-gnu"), -// Crate("winapi-x86_64-pc-windows-gnu"), + Crate("ar"), + Crate("backtrace"), + Crate("backtrace-sys"), + Crate("bitflags"), + Crate("byteorder"), + Crate("cc"), + Crate("cfg-if"), + Crate("cmake"), + Crate("filetime"), + Crate("flate2"), + Crate("fuchsia-zircon"), + Crate("fuchsia-zircon-sys"), + Crate("jobserver"), + Crate("kernel32-sys"), + Crate("lazy_static"), + Crate("libc"), + Crate("log"), + Crate("log_settings"), + Crate("miniz-sys"), + Crate("num_cpus"), + Crate("owning_ref"), + Crate("parking_lot"), + Crate("parking_lot_core"), + Crate("rand"), + Crate("redox_syscall"), + Crate("rustc-demangle"), + Crate("smallvec"), + Crate("stable_deref_trait"), + Crate("tempdir"), + Crate("unicode-width"), + Crate("winapi"), + Crate("winapi-build"), + Crate("winapi-i686-pc-windows-gnu"), + Crate("winapi-x86_64-pc-windows-gnu"), ]; // Some types for Serde to deserialize the output of `cargo metadata` to... From e5d292013be6a0074d185e0de4c563545a4ed755 Mon Sep 17 00:00:00 2001 From: Who? Me?! Date: Fri, 2 Mar 2018 12:15:02 -0600 Subject: [PATCH 58/68] Add ena to whitelist --- src/tools/tidy/src/deps.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index aa46c6b7c4db..f40c7a72a452 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -64,6 +64,7 @@ static WHITELIST: &'static [Crate] = &[ Crate("cc"), Crate("cfg-if"), Crate("cmake"), + Crate("ena"), Crate("filetime"), Crate("flate2"), Crate("fuchsia-zircon"), From 2ec47e07ee933f9497185fc111b3501b8648aef5 Mon Sep 17 00:00:00 2001 From: Corey Farwell Date: Mon, 5 Mar 2018 20:24:05 -0500 Subject: [PATCH 59/68] Remove seemingly unused sugarise-doc-comments Python script. This Python script converts documentation comments from the `#[doc = "..."]` attribute to the `///` syntax. It was added six years ago, presumably to help with the transition when `///` was implemented and hasn't really been touched since. I don't think there's much value in keeping it around at this point. --- src/etc/sugarise-doc-comments.py | 93 -------------------------------- 1 file changed, 93 deletions(-) delete mode 100755 src/etc/sugarise-doc-comments.py diff --git a/src/etc/sugarise-doc-comments.py b/src/etc/sugarise-doc-comments.py deleted file mode 100755 index ac2223f4acef..000000000000 --- a/src/etc/sugarise-doc-comments.py +++ /dev/null @@ -1,93 +0,0 @@ -#!/usr/bin/env python -# -# Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT -# file at the top-level directory of this distribution and at -# http://rust-lang.org/COPYRIGHT. -# -# Licensed under the Apache License, Version 2.0 or the MIT license -# , at your -# option. This file may not be copied, modified, or distributed -# except according to those terms. - -# -# this script attempts to turn doc comment attributes (#[doc = "..."]) -# into sugared-doc-comments (/** ... */ and /// ...) -# -# it sugarises all .rs/.rc files underneath the working directory -# - -import sys -import os -import fnmatch -import re - - -DOC_PATTERN = '^(?P[\\t ]*)#\\[(\\s*)doc(\\s*)=' + \ - '(\\s*)"(?P(\\"|[^"])*?)"(\\s*)\\]' + \ - '(?P;)?' - -ESCAPES = [("\\'", "'"), - ('\\"', '"'), - ("\\n", "\n"), - ("\\r", "\r"), - ("\\t", "\t")] - - -def unescape(s): - for (find, repl) in ESCAPES: - s = s.replace(find, repl) - return s - - -def block_trim(s): - lns = s.splitlines() - - # remove leading/trailing whitespace-lines - while lns and not lns[0].strip(): - lns = lns[1:] - while lns and not lns[-1].strip(): - lns = lns[:-1] - - # remove leading horizontal whitespace - n = sys.maxsize - for ln in lns: - if ln.strip(): - n = min(n, len(re.search('^\s*', ln).group())) - if n != sys.maxsize: - lns = [ln[n:] for ln in lns] - - # strip trailing whitespace - lns = [ln.rstrip() for ln in lns] - - return lns - - -def replace_doc(m): - indent = m.group('indent') - text = block_trim(unescape(m.group('text'))) - - if len(text) > 1: - inner = '!' if m.group('semi') else '*' - starify = lambda s: indent + ' *' + (' ' + s if s else '') - text = '\n'.join(map(starify, text)) - repl = indent + '/*' + inner + '\n' + text + '\n' + indent + ' */' - else: - inner = '!' if m.group('semi') else '/' - repl = indent + '//' + inner + ' ' + text[0] - - return repl - - -def sugarise_file(path): - s = open(path).read() - - r = re.compile(DOC_PATTERN, re.MULTILINE | re.DOTALL) - ns = re.sub(r, replace_doc, s) - - if s != ns: - open(path, 'w').write(ns) - -for (dirpath, dirnames, filenames) in os.walk('.'): - for name in fnmatch.filter(filenames, '*.r[sc]'): - sugarise_file(os.path.join(dirpath, name)) From 24fb4b766952edbd9daf71dc74dcdc62a7511711 Mon Sep 17 00:00:00 2001 From: Amanieu d'Antras Date: Tue, 27 Feb 2018 04:34:55 +0000 Subject: [PATCH 60/68] Add reverse_bits to integer types --- src/libcore/num/mod.rs | 54 ++++++++++++++++++++++++++++ src/libcore/tests/lib.rs | 1 + src/libcore/tests/num/uint_macros.rs | 11 ++++++ 3 files changed, 66 insertions(+) diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index 59a67fff48cf..a46ac2b5f0fe 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -321,6 +321,33 @@ $EndFeature, " (self as $UnsignedT).swap_bytes() as Self } + /// Reverses the bit pattern of the integer. + /// + /// # Examples + /// + /// Please note that this example is shared between integer types. + /// Which explains why `i16` is used here. + /// + /// Basic usage: + /// + /// ``` + /// #![feature(reverse_bits)] + /// + /// let n: i16 = 0b0000000_01010101; + /// assert_eq!(n, 85); + /// + /// let m = n.reverse_bits(); + /// + /// assert_eq!(m as u16, 0b10101010_00000000); + /// assert_eq!(m, -22016); + /// ``` + #[unstable(feature = "reverse_bits", issue = "48763")] + #[cfg(not(stage0))] + #[inline] + pub fn reverse_bits(self) -> Self { + (self as $UnsignedT).reverse_bits() as Self + } + doc_comment! { concat!("Converts an integer from big endian to the target's endianness. @@ -1773,6 +1800,33 @@ assert_eq!(n.trailing_zeros(), 3);", $EndFeature, " unsafe { intrinsics::bswap(self as $ActualT) as Self } } + /// Reverses the bit pattern of the integer. + /// + /// # Examples + /// + /// Basic usage: + /// + /// Please note that this example is shared between integer types. + /// Which explains why `u16` is used here. + /// + /// ``` + /// #![feature(reverse_bits)] + /// + /// let n: u16 = 0b0000000_01010101; + /// assert_eq!(n, 85); + /// + /// let m = n.reverse_bits(); + /// + /// assert_eq!(m, 0b10101010_00000000); + /// assert_eq!(m, 43520); + /// ``` + #[unstable(feature = "reverse_bits", issue = "48763")] + #[cfg(not(stage0))] + #[inline] + pub fn reverse_bits(self) -> Self { + unsafe { intrinsics::bitreverse(self as $ActualT) as Self } + } + doc_comment! { concat!("Converts an integer from big endian to the target's endianness. diff --git a/src/libcore/tests/lib.rs b/src/libcore/tests/lib.rs index 0049ed66a102..a9c5683e0ef7 100644 --- a/src/libcore/tests/lib.rs +++ b/src/libcore/tests/lib.rs @@ -46,6 +46,7 @@ #![feature(try_trait)] #![feature(exact_chunks)] #![feature(atomic_nand)] +#![feature(reverse_bits)] extern crate core; extern crate test; diff --git a/src/libcore/tests/num/uint_macros.rs b/src/libcore/tests/num/uint_macros.rs index daa1cc3a7f4f..ca6906f73104 100644 --- a/src/libcore/tests/num/uint_macros.rs +++ b/src/libcore/tests/num/uint_macros.rs @@ -97,6 +97,17 @@ mod tests { assert_eq!(_1.swap_bytes(), _1); } + #[test] + fn test_reverse_bits() { + assert_eq!(A.reverse_bits().reverse_bits(), A); + assert_eq!(B.reverse_bits().reverse_bits(), B); + assert_eq!(C.reverse_bits().reverse_bits(), C); + + // Swapping these should make no difference + assert_eq!(_0.reverse_bits(), _0); + assert_eq!(_1.reverse_bits(), _1); + } + #[test] fn test_le() { assert_eq!($T::from_le(A.to_le()), A); From 88aec91017bf7def8401f47f3f90acd25882a2da Mon Sep 17 00:00:00 2001 From: Amanieu d'Antras Date: Wed, 28 Feb 2018 13:56:54 +0000 Subject: [PATCH 61/68] Add i128 tests for intrinsics --- src/test/run-pass/intrinsics-integer.rs | 27 ++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/src/test/run-pass/intrinsics-integer.rs b/src/test/run-pass/intrinsics-integer.rs index 6e0712f6767b..bfa3a1e128a9 100644 --- a/src/test/run-pass/intrinsics-integer.rs +++ b/src/test/run-pass/intrinsics-integer.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(intrinsics)] +#![feature(intrinsics, i128_type)] mod rusti { extern "rust-intrinsic" { @@ -30,106 +30,127 @@ pub fn main() { assert_eq!(ctpop(0u16), 0); assert_eq!(ctpop(0i16), 0); assert_eq!(ctpop(0u32), 0); assert_eq!(ctpop(0i32), 0); assert_eq!(ctpop(0u64), 0); assert_eq!(ctpop(0i64), 0); + assert_eq!(ctpop(0u128), 0); assert_eq!(ctpop(0i128), 0); assert_eq!(ctpop(1u8), 1); assert_eq!(ctpop(1i8), 1); assert_eq!(ctpop(1u16), 1); assert_eq!(ctpop(1i16), 1); assert_eq!(ctpop(1u32), 1); assert_eq!(ctpop(1i32), 1); assert_eq!(ctpop(1u64), 1); assert_eq!(ctpop(1i64), 1); + assert_eq!(ctpop(1u128), 1); assert_eq!(ctpop(1i128), 1); assert_eq!(ctpop(10u8), 2); assert_eq!(ctpop(10i8), 2); assert_eq!(ctpop(10u16), 2); assert_eq!(ctpop(10i16), 2); assert_eq!(ctpop(10u32), 2); assert_eq!(ctpop(10i32), 2); assert_eq!(ctpop(10u64), 2); assert_eq!(ctpop(10i64), 2); + assert_eq!(ctpop(10u128), 2); assert_eq!(ctpop(10i128), 2); assert_eq!(ctpop(100u8), 3); assert_eq!(ctpop(100i8), 3); assert_eq!(ctpop(100u16), 3); assert_eq!(ctpop(100i16), 3); assert_eq!(ctpop(100u32), 3); assert_eq!(ctpop(100i32), 3); assert_eq!(ctpop(100u64), 3); assert_eq!(ctpop(100i64), 3); + assert_eq!(ctpop(100u128), 3); assert_eq!(ctpop(100i128), 3); assert_eq!(ctpop(-1i8 as u8), 8); assert_eq!(ctpop(-1i8), 8); assert_eq!(ctpop(-1i16 as u16), 16); assert_eq!(ctpop(-1i16), 16); assert_eq!(ctpop(-1i32 as u32), 32); assert_eq!(ctpop(-1i32), 32); assert_eq!(ctpop(-1i64 as u64), 64); assert_eq!(ctpop(-1i64), 64); + assert_eq!(ctpop(-1i128 as u128), 128); assert_eq!(ctpop(-1i128), 128); assert_eq!(ctlz(0u8), 8); assert_eq!(ctlz(0i8), 8); assert_eq!(ctlz(0u16), 16); assert_eq!(ctlz(0i16), 16); assert_eq!(ctlz(0u32), 32); assert_eq!(ctlz(0i32), 32); assert_eq!(ctlz(0u64), 64); assert_eq!(ctlz(0i64), 64); + assert_eq!(ctlz(0u128), 128); assert_eq!(ctlz(0i128), 128); assert_eq!(ctlz(1u8), 7); assert_eq!(ctlz(1i8), 7); assert_eq!(ctlz(1u16), 15); assert_eq!(ctlz(1i16), 15); assert_eq!(ctlz(1u32), 31); assert_eq!(ctlz(1i32), 31); assert_eq!(ctlz(1u64), 63); assert_eq!(ctlz(1i64), 63); + assert_eq!(ctlz(1u128), 127); assert_eq!(ctlz(1i128), 127); assert_eq!(ctlz(10u8), 4); assert_eq!(ctlz(10i8), 4); assert_eq!(ctlz(10u16), 12); assert_eq!(ctlz(10i16), 12); assert_eq!(ctlz(10u32), 28); assert_eq!(ctlz(10i32), 28); assert_eq!(ctlz(10u64), 60); assert_eq!(ctlz(10i64), 60); + assert_eq!(ctlz(10u128), 124); assert_eq!(ctlz(10i128), 124); assert_eq!(ctlz(100u8), 1); assert_eq!(ctlz(100i8), 1); assert_eq!(ctlz(100u16), 9); assert_eq!(ctlz(100i16), 9); assert_eq!(ctlz(100u32), 25); assert_eq!(ctlz(100i32), 25); assert_eq!(ctlz(100u64), 57); assert_eq!(ctlz(100i64), 57); + assert_eq!(ctlz(100u128), 121); assert_eq!(ctlz(100i128), 121); 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(1u128), 127); assert_eq!(ctlz_nonzero(1i128), 127); 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(10u128), 124); assert_eq!(ctlz_nonzero(10i128), 124); 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!(ctlz_nonzero(100u128), 121); assert_eq!(ctlz_nonzero(100i128), 121); 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); assert_eq!(cttz(-1i64 as u64), 0); assert_eq!(cttz(-1i64), 0); + assert_eq!(cttz(-1i128 as u128), 0); assert_eq!(cttz(-1i128), 0); assert_eq!(cttz(0u8), 8); assert_eq!(cttz(0i8), 8); assert_eq!(cttz(0u16), 16); assert_eq!(cttz(0i16), 16); assert_eq!(cttz(0u32), 32); assert_eq!(cttz(0i32), 32); assert_eq!(cttz(0u64), 64); assert_eq!(cttz(0i64), 64); + assert_eq!(cttz(0u128), 128); assert_eq!(cttz(0i128), 128); assert_eq!(cttz(1u8), 0); assert_eq!(cttz(1i8), 0); assert_eq!(cttz(1u16), 0); assert_eq!(cttz(1i16), 0); assert_eq!(cttz(1u32), 0); assert_eq!(cttz(1i32), 0); assert_eq!(cttz(1u64), 0); assert_eq!(cttz(1i64), 0); + assert_eq!(cttz(1u128), 0); assert_eq!(cttz(1i128), 0); assert_eq!(cttz(10u8), 1); assert_eq!(cttz(10i8), 1); assert_eq!(cttz(10u16), 1); assert_eq!(cttz(10i16), 1); assert_eq!(cttz(10u32), 1); assert_eq!(cttz(10i32), 1); assert_eq!(cttz(10u64), 1); assert_eq!(cttz(10i64), 1); + assert_eq!(cttz(10u128), 1); assert_eq!(cttz(10i128), 1); assert_eq!(cttz(100u8), 2); assert_eq!(cttz(100i8), 2); assert_eq!(cttz(100u16), 2); assert_eq!(cttz(100i16), 2); assert_eq!(cttz(100u32), 2); assert_eq!(cttz(100i32), 2); assert_eq!(cttz(100u64), 2); assert_eq!(cttz(100i64), 2); + assert_eq!(cttz(100u128), 2); assert_eq!(cttz(100i128), 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(-1i128 as u128), 0); assert_eq!(cttz_nonzero(-1i128), 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(1u128), 0); assert_eq!(cttz_nonzero(1i128), 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(10u128), 1); assert_eq!(cttz_nonzero(10i128), 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!(cttz_nonzero(100u128), 2); assert_eq!(cttz_nonzero(100i128), 2); assert_eq!(bswap(0x0Au8), 0x0A); // no-op assert_eq!(bswap(0x0Ai8), 0x0A); // no-op @@ -139,6 +160,8 @@ pub fn main() { assert_eq!(bswap(0x0ABBCC0Di32), 0x0DCCBB0A); assert_eq!(bswap(0x0122334455667708u64), 0x0877665544332201); assert_eq!(bswap(0x0122334455667708i64), 0x0877665544332201); + assert_eq!(bswap(0x0122334455667708u128), 0x08776655443322010000000000000000); + assert_eq!(bswap(0x0122334455667708i128), 0x08776655443322010000000000000000); assert_eq!(bitreverse(0x0Au8), 0x50); assert_eq!(bitreverse(0x0Ai8), 0x50); @@ -148,5 +171,7 @@ pub fn main() { assert_eq!(bitreverse(0x0ABBCC0Ei32), 0x7033DD50); assert_eq!(bitreverse(0x0122334455667708u64), 0x10EE66AA22CC4480); assert_eq!(bitreverse(0x0122334455667708i64), 0x10EE66AA22CC4480); + assert_eq!(bitreverse(0x0122334455667708u128), 0x10EE66AA22CC44800000000000000000); + assert_eq!(bitreverse(0x0122334455667708i128), 0x10EE66AA22CC44800000000000000000); } } From e5ee01143b5a94fbc0fee8d4b3e7830946ef0a3a Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Thu, 22 Feb 2018 12:18:16 +0100 Subject: [PATCH 62/68] Rename exported_symbol_ids query to something more explicit and document what it is doing. --- src/librustc/dep_graph/dep_node.rs | 4 +-- src/librustc/ty/maps/config.rs | 6 ++--- src/librustc/ty/maps/mod.rs | 19 ++++++++++++-- src/librustc/ty/maps/plumbing.rs | 4 +-- src/librustc_metadata/creader.rs | 4 --- src/librustc_metadata/cstore.rs | 2 -- src/librustc_metadata/cstore_impl.rs | 5 +--- src/librustc_metadata/decoder.rs | 9 ++++--- src/librustc_metadata/encoder.rs | 25 +++++++++++-------- src/librustc_metadata/schema.rs | 2 +- src/librustc_mir/monomorphize/collector.rs | 4 +-- src/librustc_mir/monomorphize/partitioning.rs | 6 ++--- src/librustc_trans/back/symbol_export.rs | 13 +++++++--- src/librustc_trans/callee.rs | 2 +- src/librustc_trans/consts.rs | 2 +- src/librustc_trans/debuginfo/utils.rs | 2 +- 16 files changed, 62 insertions(+), 47 deletions(-) diff --git a/src/librustc/dep_graph/dep_node.rs b/src/librustc/dep_graph/dep_node.rs index 5f6a7c452c4c..84fdeba4ab3c 100644 --- a/src/librustc/dep_graph/dep_node.rs +++ b/src/librustc/dep_graph/dep_node.rs @@ -556,7 +556,7 @@ define_dep_nodes!( <'tcx> [] RvaluePromotableMap(DefId), [] ImplParent(DefId), [] TraitOfItem(DefId), - [] IsExportedSymbol(DefId), + [] IsReachableNonGeneric(DefId), [] IsMirAvailable(DefId), [] ItemAttrs(DefId), [] FnArgNames(DefId), @@ -574,7 +574,7 @@ define_dep_nodes!( <'tcx> [] GetPanicStrategy(CrateNum), [] IsNoBuiltins(CrateNum), [] ImplDefaultness(DefId), - [] ExportedSymbolIds(CrateNum), + [] ReachableNonGenerics(CrateNum), [] NativeLibraries(CrateNum), [] PluginRegistrarFn(CrateNum), [] DeriveRegistrarFn(CrateNum), diff --git a/src/librustc/ty/maps/config.rs b/src/librustc/ty/maps/config.rs index c91b30440e5e..cfc552bdc85c 100644 --- a/src/librustc/ty/maps/config.rs +++ b/src/librustc/ty/maps/config.rs @@ -212,9 +212,9 @@ impl<'tcx> QueryDescription<'tcx> for queries::item_attrs<'tcx> { } } -impl<'tcx> QueryDescription<'tcx> for queries::is_exported_symbol<'tcx> { +impl<'tcx> QueryDescription<'tcx> for queries::is_reachable_non_generic<'tcx> { fn describe(_: TyCtxt, _: DefId) -> String { - bug!("is_exported_symbol") + bug!("is_reachable_non_generic") } } @@ -383,7 +383,7 @@ impl<'tcx> QueryDescription<'tcx> for queries::is_sanitizer_runtime<'tcx> { } } -impl<'tcx> QueryDescription<'tcx> for queries::exported_symbol_ids<'tcx> { +impl<'tcx> QueryDescription<'tcx> for queries::reachable_non_generics<'tcx> { fn describe(_tcx: TyCtxt, _: CrateNum) -> String { format!("looking up the exported symbols of a crate") } diff --git a/src/librustc/ty/maps/mod.rs b/src/librustc/ty/maps/mod.rs index c211713db6bc..e91ccce8ffa9 100644 --- a/src/librustc/ty/maps/mod.rs +++ b/src/librustc/ty/maps/mod.rs @@ -238,7 +238,6 @@ define_maps! { <'tcx> [] fn fn_arg_names: FnArgNames(DefId) -> Vec, [] fn impl_parent: ImplParent(DefId) -> Option, [] fn trait_of_item: TraitOfItem(DefId) -> Option, - [] fn is_exported_symbol: IsExportedSymbol(DefId) -> bool, [] fn item_body_nested_bodies: ItemBodyNestedBodies(DefId) -> ExternBodyNestedBodies, [] fn const_is_rvalue_promotable_to_static: ConstIsRvaluePromotableToStatic(DefId) -> bool, [] fn rvalue_promotable_map: RvaluePromotableMap(DefId) -> Lrc, @@ -290,7 +289,23 @@ define_maps! { <'tcx> [] fn lint_levels: lint_levels_node(CrateNum) -> Lrc, [] fn impl_defaultness: ImplDefaultness(DefId) -> hir::Defaultness, - [] fn exported_symbol_ids: ExportedSymbolIds(CrateNum) -> Lrc, + + // The DefIds of all non-generic functions and statics in the given crate + // that can be reached from outside the crate. + // + // We expect this items to be available for being linked to. + // + // This query can also be called for LOCAL_CRATE. In this case it will + // compute which items will be reachable to other crates, taking into account + // the kind of crate that is currently compiled. Crates with only a + // C interface have fewer reachable things. + // + // Does not include external symbols that don't have a corresponding DefId, + // like the compiler-generated `main` function and so on. + [] fn reachable_non_generics: ReachableNonGenerics(CrateNum) -> Lrc, + [] fn is_reachable_non_generic: IsReachableNonGeneric(DefId) -> bool, + + [] fn native_libraries: NativeLibraries(CrateNum) -> Lrc>, [] fn plugin_registrar_fn: PluginRegistrarFn(CrateNum) -> Option, [] fn derive_registrar_fn: DeriveRegistrarFn(CrateNum) -> Option, diff --git a/src/librustc/ty/maps/plumbing.rs b/src/librustc/ty/maps/plumbing.rs index 3443b9b61b21..13f286d6a268 100644 --- a/src/librustc/ty/maps/plumbing.rs +++ b/src/librustc/ty/maps/plumbing.rs @@ -851,7 +851,7 @@ pub fn force_from_dep_node<'a, 'gcx, 'lcx>(tcx: TyCtxt<'a, 'gcx, 'lcx>, DepKind::RvaluePromotableMap => { force!(rvalue_promotable_map, def_id!()); } DepKind::ImplParent => { force!(impl_parent, def_id!()); } DepKind::TraitOfItem => { force!(trait_of_item, def_id!()); } - DepKind::IsExportedSymbol => { force!(is_exported_symbol, def_id!()); } + DepKind::IsReachableNonGeneric => { force!(is_reachable_non_generic, def_id!()); } DepKind::IsMirAvailable => { force!(is_mir_available, def_id!()); } DepKind::ItemAttrs => { force!(item_attrs, def_id!()); } DepKind::FnArgNames => { force!(fn_arg_names, def_id!()); } @@ -868,7 +868,7 @@ pub fn force_from_dep_node<'a, 'gcx, 'lcx>(tcx: TyCtxt<'a, 'gcx, 'lcx>, DepKind::GetPanicStrategy => { force!(panic_strategy, krate!()); } DepKind::IsNoBuiltins => { force!(is_no_builtins, krate!()); } DepKind::ImplDefaultness => { force!(impl_defaultness, def_id!()); } - DepKind::ExportedSymbolIds => { force!(exported_symbol_ids, krate!()); } + DepKind::ReachableNonGenerics => { force!(reachable_non_generics, krate!()); } DepKind::NativeLibraries => { force!(native_libraries, krate!()); } DepKind::PluginRegistrarFn => { force!(plugin_registrar_fn, krate!()); } DepKind::DeriveRegistrarFn => { force!(derive_registrar_fn, krate!()); } diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs index 876e7e8dc31a..789ecd0f6136 100644 --- a/src/librustc_metadata/creader.rs +++ b/src/librustc_metadata/creader.rs @@ -225,9 +225,6 @@ impl<'a> CrateLoader<'a> { crate_root.def_path_table.decode((&metadata, self.sess)) }); - let exported_symbols = crate_root.exported_symbols - .decode((&metadata, self.sess)) - .collect(); let trait_impls = crate_root .impls .decode((&metadata, self.sess)) @@ -238,7 +235,6 @@ impl<'a> CrateLoader<'a> { name, extern_crate: Cell::new(None), def_path_table: Lrc::new(def_path_table), - exported_symbols, trait_impls, proc_macros: crate_root.macro_derive_registrar.map(|_| { self.load_derive_macros(&crate_root, dylib.clone().map(|p| p.0), span) diff --git a/src/librustc_metadata/cstore.rs b/src/librustc_metadata/cstore.rs index 8b59eec01905..2e95c23b4aed 100644 --- a/src/librustc_metadata/cstore.rs +++ b/src/librustc_metadata/cstore.rs @@ -78,8 +78,6 @@ pub struct CrateMetadata { /// compilation support. pub def_path_table: Lrc, - pub exported_symbols: FxHashSet, - pub trait_impls: FxHashMap<(u32, DefIndex), schema::LazySeq>, pub dep_kind: Cell, diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index 7b8194d9eab2..20fc45696a95 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -160,9 +160,6 @@ provide! { <'tcx> tcx, def_id, other, cdata, 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 => { - cdata.exported_symbols.contains(&def_id.index) - } item_body_nested_bodies => { cdata.item_body_nested_bodies(def_id.index) } const_is_rvalue_promotable_to_static => { cdata.const_is_rvalue_promotable_to_static(def_id.index) @@ -179,7 +176,7 @@ provide! { <'tcx> tcx, def_id, other, cdata, extern_crate => { Lrc::new(cdata.extern_crate.get()) } is_no_builtins => { cdata.is_no_builtins(tcx.sess) } impl_defaultness => { cdata.get_impl_defaultness(def_id.index) } - exported_symbol_ids => { Lrc::new(cdata.get_exported_symbols()) } + reachable_non_generics => { Lrc::new(cdata.reachable_non_generics()) } native_libraries => { Lrc::new(cdata.get_native_libraries(tcx.sess)) } plugin_registrar_fn => { cdata.root.plugin_registrar_fn.map(|index| { diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index 0c6a286e2276..2831b63bbac5 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -1006,10 +1006,11 @@ impl<'a, 'tcx> CrateMetadata { arg_names.decode(self).collect() } - pub fn get_exported_symbols(&self) -> DefIdSet { - self.exported_symbols - .iter() - .map(|&index| self.local_def_id(index)) + pub fn reachable_non_generics(&self) -> DefIdSet { + self.root + .reachable_non_generics + .decode(self) + .map(|index| self.local_def_id(index)) .collect() } diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index d3f046c55441..7198f7ccf35e 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -53,7 +53,7 @@ pub struct EncodeContext<'a, 'tcx: 'a> { opaque: opaque::Encoder<'a>, pub tcx: TyCtxt<'a, 'tcx, 'tcx>, link_meta: &'a LinkMeta, - exported_symbols: &'a NodeSet, + reachable_non_generics: &'a NodeSet, lazy_state: LazyState, type_shorthands: FxHashMap, usize>, @@ -395,10 +395,10 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { // Encode exported symbols info. i = self.position(); - let exported_symbols = self.tracked( - IsolatedEncoder::encode_exported_symbols, - self.exported_symbols); - let exported_symbols_bytes = self.position() - i; + let reachable_non_generics = self.tracked( + IsolatedEncoder::encode_reachable_non_generics, + self.reachable_non_generics); + let reachable_non_generics_bytes = self.position() - i; // Encode and index the items. i = self.position(); @@ -442,7 +442,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { codemap, def_path_table, impls, - exported_symbols, + reachable_non_generics, index, }); @@ -462,7 +462,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { println!(" native bytes: {}", native_lib_bytes); println!(" codemap bytes: {}", codemap_bytes); println!(" impl bytes: {}", impl_bytes); - println!(" exp. symbols bytes: {}", exported_symbols_bytes); + println!(" exp. symbols bytes: {}", reachable_non_generics_bytes); println!(" def-path table bytes: {}", def_path_table_bytes); println!(" item bytes: {}", item_bytes); println!(" index bytes: {}", index_bytes); @@ -1388,9 +1388,12 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { // middle::reachable module but filters out items that either don't have a // symbol associated with them (they weren't translated) or if they're an FFI // definition (as that's not defined in this crate). - fn encode_exported_symbols(&mut self, exported_symbols: &NodeSet) -> LazySeq { + fn encode_reachable_non_generics(&mut self, + reachable_non_generics: &NodeSet) + -> LazySeq { let tcx = self.tcx; - self.lazy_seq(exported_symbols.iter().map(|&id| tcx.hir.local_def_id(id).index)) + self.lazy_seq(reachable_non_generics.iter() + .map(|&id| tcx.hir.local_def_id(id).index)) } fn encode_dylib_dependency_formats(&mut self, _: ()) -> LazySeq> { @@ -1664,7 +1667,7 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for ImplVisitor<'a, 'tcx> { pub fn encode_metadata<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, link_meta: &LinkMeta, - exported_symbols: &NodeSet) + reachable_non_generics: &NodeSet) -> EncodedMetadata { let mut cursor = Cursor::new(vec![]); @@ -1678,7 +1681,7 @@ pub fn encode_metadata<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, opaque: opaque::Encoder::new(&mut cursor), tcx, link_meta, - exported_symbols, + reachable_non_generics, lazy_state: LazyState::NoNode, type_shorthands: Default::default(), predicate_shorthands: Default::default(), diff --git a/src/librustc_metadata/schema.rs b/src/librustc_metadata/schema.rs index c542f65dcecf..3e7d31513a22 100644 --- a/src/librustc_metadata/schema.rs +++ b/src/librustc_metadata/schema.rs @@ -202,7 +202,7 @@ pub struct CrateRoot { pub codemap: LazySeq, pub def_path_table: Lazy, pub impls: LazySeq, - pub exported_symbols: LazySeq, + pub reachable_non_generics: LazySeq, pub index: LazySeq, } diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs index eb4ba21489c3..10c2f9f758f1 100644 --- a/src/librustc_mir/monomorphize/collector.rs +++ b/src/librustc_mir/monomorphize/collector.rs @@ -736,7 +736,7 @@ fn should_monomorphize_locally<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, instance: } Some(_) => true, None => { - if tcx.is_exported_symbol(def_id) || + if tcx.is_reachable_non_generic(def_id) || tcx.is_foreign_item(def_id) { // We can link to the item in question, no instance needed @@ -984,7 +984,7 @@ impl<'b, 'a, 'v> RootCollector<'b, 'a, 'v> { } MonoItemCollectionMode::Lazy => { self.entry_fn == Some(def_id) || - self.tcx.is_exported_symbol(def_id) || + self.tcx.is_reachable_non_generic(def_id) || attr::contains_name(&self.tcx.get_attrs(def_id), "rustc_std_internal_symbol") } diff --git a/src/librustc_mir/monomorphize/partitioning.rs b/src/librustc_mir/monomorphize/partitioning.rs index 2b558e71483c..d65c1e03298a 100644 --- a/src/librustc_mir/monomorphize/partitioning.rs +++ b/src/librustc_mir/monomorphize/partitioning.rs @@ -363,7 +363,7 @@ fn place_root_translation_items<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>, can_be_internalized = false; Visibility::Hidden } else if def_id.is_local() { - if tcx.is_exported_symbol(def_id) { + if tcx.is_reachable_non_generic(def_id) { can_be_internalized = false; default_visibility(def_id) } else { @@ -385,7 +385,7 @@ fn place_root_translation_items<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>, (Linkage::External, visibility) } MonoItem::Static(def_id) => { - let visibility = if tcx.is_exported_symbol(def_id) { + let visibility = if tcx.is_reachable_non_generic(def_id) { can_be_internalized = false; default_visibility(def_id) } else { @@ -395,7 +395,7 @@ fn place_root_translation_items<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } MonoItem::GlobalAsm(node_id) => { let def_id = tcx.hir.local_def_id(node_id); - let visibility = if tcx.is_exported_symbol(def_id) { + let visibility = if tcx.is_reachable_non_generic(def_id) { can_be_internalized = false; default_visibility(def_id) } else { diff --git a/src/librustc_trans/back/symbol_export.rs b/src/librustc_trans/back/symbol_export.rs index 55ef4e7ed3ae..57da02eaa523 100644 --- a/src/librustc_trans/back/symbol_export.rs +++ b/src/librustc_trans/back/symbol_export.rs @@ -61,7 +61,7 @@ pub fn crates_export_threshold(crate_types: &[config::CrateType]) } pub fn provide(providers: &mut Providers) { - providers.exported_symbol_ids = |tcx, cnum| { + providers.reachable_non_generics = |tcx, cnum| { let export_threshold = threshold(tcx); Lrc::new(tcx.exported_symbols(cnum) .iter() @@ -77,8 +77,8 @@ pub fn provide(providers: &mut Providers) { .collect()) }; - providers.is_exported_symbol = |tcx, id| { - tcx.exported_symbol_ids(id.krate).contains(&id) + providers.is_reachable_non_generic = |tcx, id| { + tcx.reachable_non_generics(id.krate).contains(&id) }; providers.exported_symbols = |tcx, cnum| { @@ -156,7 +156,7 @@ pub fn provide_extern(providers: &mut Providers) { tcx.is_panic_runtime(cnum) || tcx.is_compiler_builtins(cnum); let mut crate_exports: Vec<_> = tcx - .exported_symbol_ids(cnum) + .reachable_non_generics(cnum) .iter() .map(|&def_id| { let name = tcx.symbol_name(Instance::mono(tcx, def_id)); @@ -190,6 +190,11 @@ pub fn provide_extern(providers: &mut Providers) { Arc::new(crate_exports) }; + + providers.is_reachable_non_generic = |tcx, id| { + tcx.reachable_non_generics(id.krate).contains(&id) + }; + providers.symbol_export_level = export_level; } diff --git a/src/librustc_trans/callee.rs b/src/librustc_trans/callee.rs index 8c40aa6a2acb..54cc561e8041 100644 --- a/src/librustc_trans/callee.rs +++ b/src/librustc_trans/callee.rs @@ -151,7 +151,7 @@ pub fn get_fn<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>, if cx.tcx.is_translated_item(instance_def_id) { if instance_def_id.is_local() { - if !cx.tcx.is_exported_symbol(instance_def_id) { + if !cx.tcx.is_reachable_non_generic(instance_def_id) { llvm::LLVMRustSetVisibility(llfn, llvm::Visibility::Hidden); } } else { diff --git a/src/librustc_trans/consts.rs b/src/librustc_trans/consts.rs index 1608c4a87bf5..fd9cb8c5a6be 100644 --- a/src/librustc_trans/consts.rs +++ b/src/librustc_trans/consts.rs @@ -134,7 +134,7 @@ pub fn get_static(cx: &CodegenCx, def_id: DefId) -> ValueRef { let g = declare::define_global(cx, &sym[..], llty).unwrap(); - if !cx.tcx.is_exported_symbol(def_id) { + if !cx.tcx.is_reachable_non_generic(def_id) { unsafe { llvm::LLVMRustSetVisibility(g, llvm::Visibility::Hidden); } diff --git a/src/librustc_trans/debuginfo/utils.rs b/src/librustc_trans/debuginfo/utils.rs index 9559cd4d9ea2..0a3f06b55f1e 100644 --- a/src/librustc_trans/debuginfo/utils.rs +++ b/src/librustc_trans/debuginfo/utils.rs @@ -32,7 +32,7 @@ pub fn is_node_local_to_unit(cx: &CodegenCx, def_id: DefId) -> bool // visible). It might better to use the `exported_items` set from // `driver::CrateAnalysis` in the future, but (atm) this set is not // available in the translation pass. - !cx.tcx.is_exported_symbol(def_id) + !cx.tcx.is_reachable_non_generic(def_id) } #[allow(non_snake_case)] From 33d5da1ee400e4b1b85a6a3f0c552ce68c665500 Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Fri, 23 Feb 2018 16:25:03 +0100 Subject: [PATCH 63/68] Clean up handling of symbol export information. --- src/librustc/middle/cstore.rs | 7 +- src/librustc/ty/context.rs | 6 +- src/librustc_metadata/cstore_impl.rs | 7 +- src/librustc_metadata/encoder.rs | 19 +- src/librustc_trans/back/symbol_export.rs | 331 ++++++++++++++--------- src/librustc_trans/base.rs | 12 +- src/librustc_trans_utils/lib.rs | 55 +--- src/librustc_trans_utils/trans_crate.rs | 3 +- 8 files changed, 231 insertions(+), 209 deletions(-) diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs index bdb5ad525a75..5dbe2ef516cf 100644 --- a/src/librustc/middle/cstore.rs +++ b/src/librustc/middle/cstore.rs @@ -32,7 +32,6 @@ use ich; use ty::{self, TyCtxt}; use session::{Session, CrateDisambiguator}; use session::search_paths::PathKind; -use util::nodemap::NodeSet; use std::any::Any; use std::collections::BTreeMap; @@ -258,8 +257,7 @@ pub trait CrateStore { // utility functions fn encode_metadata<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, - link_meta: &LinkMeta, - reachable: &NodeSet) + link_meta: &LinkMeta) -> EncodedMetadata; fn metadata_encoding_version(&self) -> &[u8]; } @@ -342,8 +340,7 @@ impl CrateStore for DummyCrateStore { fn extern_mod_stmt_cnum_untracked(&self, emod_id: ast::NodeId) -> Option { None } fn encode_metadata<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, - link_meta: &LinkMeta, - reachable: &NodeSet) + link_meta: &LinkMeta) -> EncodedMetadata { bug!("encode_metadata") } diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index a7f065d57aee..aac6b3dc08a7 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -46,7 +46,7 @@ use ty::layout::{LayoutDetails, TargetDataLayout}; use ty::maps; use ty::steal::Steal; use ty::BindingMode; -use util::nodemap::{NodeMap, NodeSet, DefIdSet, ItemLocalMap}; +use util::nodemap::{NodeMap, DefIdSet, ItemLocalMap}; use util::nodemap::{FxHashMap, FxHashSet}; use rustc_data_structures::accumulate_vec::AccumulateVec; use rustc_data_structures::stable_hasher::{HashStable, hash_stable_hashmap, @@ -1417,10 +1417,10 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> { - pub fn encode_metadata(self, link_meta: &LinkMeta, reachable: &NodeSet) + pub fn encode_metadata(self, link_meta: &LinkMeta) -> EncodedMetadata { - self.cstore.encode_metadata(self, link_meta, reachable) + self.cstore.encode_metadata(self, link_meta) } } diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index 20fc45696a95..00862816d57b 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -27,7 +27,7 @@ use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE, CRATE_DEF_INDEX}; use rustc::hir::map::{DefKey, DefPath, DefPathHash}; use rustc::hir::map::blocks::FnLikeNode; use rustc::hir::map::definitions::DefPathTable; -use rustc::util::nodemap::{NodeSet, DefIdMap}; +use rustc::util::nodemap::DefIdMap; use std::any::Any; use rustc_data_structures::sync::Lrc; @@ -517,11 +517,10 @@ impl CrateStore for cstore::CStore { fn encode_metadata<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, - link_meta: &LinkMeta, - reachable: &NodeSet) + link_meta: &LinkMeta) -> EncodedMetadata { - encoder::encode_metadata(tcx, link_meta, reachable) + encoder::encode_metadata(tcx, link_meta) } fn metadata_encoding_version(&self) -> &[u8] diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index 7198f7ccf35e..c649cf62dc5d 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -27,7 +27,7 @@ use rustc::ty::{self, Ty, TyCtxt, ReprOptions}; use rustc::ty::codec::{self as ty_codec, TyEncoder}; use rustc::session::config::{self, CrateTypeProcMacro}; -use rustc::util::nodemap::{FxHashMap, NodeSet}; +use rustc::util::nodemap::{FxHashMap, DefIdSet}; use rustc_data_structures::stable_hasher::StableHasher; use rustc_serialize::{Encodable, Encoder, SpecializedEncoder, opaque}; @@ -53,7 +53,6 @@ pub struct EncodeContext<'a, 'tcx: 'a> { opaque: opaque::Encoder<'a>, pub tcx: TyCtxt<'a, 'tcx, 'tcx>, link_meta: &'a LinkMeta, - reachable_non_generics: &'a NodeSet, lazy_state: LazyState, type_shorthands: FxHashMap, usize>, @@ -395,9 +394,10 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { // Encode exported symbols info. i = self.position(); + let reachable_non_generics = self.tcx.reachable_non_generics(LOCAL_CRATE); let reachable_non_generics = self.tracked( IsolatedEncoder::encode_reachable_non_generics, - self.reachable_non_generics); + &reachable_non_generics); let reachable_non_generics_bytes = self.position() - i; // Encode and index the items. @@ -1389,11 +1389,12 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { // symbol associated with them (they weren't translated) or if they're an FFI // definition (as that's not defined in this crate). fn encode_reachable_non_generics(&mut self, - reachable_non_generics: &NodeSet) + reachable_non_generics: &DefIdSet) -> LazySeq { - let tcx = self.tcx; - self.lazy_seq(reachable_non_generics.iter() - .map(|&id| tcx.hir.local_def_id(id).index)) + self.lazy_seq(reachable_non_generics.iter().map(|def_id| { + debug_assert!(def_id.is_local()); + def_id.index + })) } fn encode_dylib_dependency_formats(&mut self, _: ()) -> LazySeq> { @@ -1666,8 +1667,7 @@ impl<'a, 'tcx, 'v> ItemLikeVisitor<'v> for ImplVisitor<'a, 'tcx> { // generated regardless of trailing bytes that end up in it. pub fn encode_metadata<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - link_meta: &LinkMeta, - reachable_non_generics: &NodeSet) + link_meta: &LinkMeta) -> EncodedMetadata { let mut cursor = Cursor::new(vec![]); @@ -1681,7 +1681,6 @@ pub fn encode_metadata<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, opaque: opaque::Encoder::new(&mut cursor), tcx, link_meta, - reachable_non_generics, lazy_state: LazyState::NoNode, type_shorthands: Default::default(), predicate_shorthands: Default::default(), diff --git a/src/librustc_trans/back/symbol_export.rs b/src/librustc_trans/back/symbol_export.rs index 57da02eaa523..74f7a6e8d9cd 100644 --- a/src/librustc_trans/back/symbol_export.rs +++ b/src/librustc_trans/back/symbol_export.rs @@ -11,15 +11,15 @@ use rustc_data_structures::sync::Lrc; use std::sync::Arc; -use base; use monomorphize::Instance; +use rustc::hir; use rustc::hir::def_id::CrateNum; use rustc::hir::def_id::{DefId, LOCAL_CRATE}; use rustc::middle::exported_symbols::SymbolExportLevel; use rustc::session::config; use rustc::ty::TyCtxt; use rustc::ty::maps::Providers; -use rustc::util::nodemap::FxHashMap; +use rustc::util::nodemap::{FxHashMap, DefIdSet}; use rustc_allocator::ALLOCATOR_METHODS; use syntax::attr; @@ -60,145 +60,228 @@ pub fn crates_export_threshold(crate_types: &[config::CrateType]) } } -pub fn provide(providers: &mut Providers) { - providers.reachable_non_generics = |tcx, cnum| { - let export_threshold = threshold(tcx); - Lrc::new(tcx.exported_symbols(cnum) - .iter() - .filter_map(|&(_, id, level)| { - id.and_then(|id| { - if level.is_below_threshold(export_threshold) { - Some(id) +fn reachable_non_generics_provider<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, + cnum: CrateNum) + -> Lrc +{ + assert_eq!(cnum, LOCAL_CRATE); + + if !tcx.sess.opts.output_types.should_trans() { + return Lrc::new(DefIdSet()) + } + + let export_threshold = threshold(tcx); + + // We already collect all potentially reachable non-generic items for + // `exported_symbols`. Now we just filter them down to what is actually + // exported for the given crate we are compiling. + let reachable_non_generics = tcx + .exported_symbols(LOCAL_CRATE) + .iter() + .filter_map(|&(_, opt_def_id, level)| { + if let Some(def_id) = opt_def_id { + if level.is_below_threshold(export_threshold) { + return Some(def_id) + } + } + + None + }) + .collect(); + + Lrc::new(reachable_non_generics) +} + +fn is_reachable_non_generic_provider<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, + def_id: DefId) + -> bool { + tcx.reachable_non_generics(def_id.krate).contains(&def_id) +} + +fn exported_symbols_provider_local<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, + cnum: CrateNum) + -> Arc, + SymbolExportLevel)>> +{ + assert_eq!(cnum, LOCAL_CRATE); + + if !tcx.sess.opts.output_types.should_trans() { + return Arc::new(vec![]) + } + + let mut reachable_non_generics: DefIdSet = tcx.reachable_set(LOCAL_CRATE).0 + .iter() + .filter_map(|&node_id| { + // We want to ignore some FFI functions that are not exposed from + // this crate. Reachable FFI functions can be lumped into two + // categories: + // + // 1. Those that are included statically via a static library + // 2. Those included otherwise (e.g. dynamically or via a framework) + // + // Although our LLVM module is not literally emitting code for the + // statically included symbols, it's an export of our library which + // needs to be passed on to the linker and encoded in the metadata. + // + // As a result, if this id is an FFI item (foreign item) then we only + // let it through if it's included statically. + match tcx.hir.get(node_id) { + hir::map::NodeForeignItem(..) => { + let def_id = tcx.hir.local_def_id(node_id); + if tcx.is_statically_included_foreign_item(def_id) { + Some(def_id) } else { None } - }) - }) - .collect()) - }; + } - providers.is_reachable_non_generic = |tcx, id| { - tcx.reachable_non_generics(id.krate).contains(&id) - }; + // Only consider nodes that actually have exported symbols. + hir::map::NodeItem(&hir::Item { + node: hir::ItemStatic(..), + .. + }) | + hir::map::NodeItem(&hir::Item { + node: hir::ItemFn(..), .. + }) | + hir::map::NodeImplItem(&hir::ImplItem { + node: hir::ImplItemKind::Method(..), + .. + }) => { + let def_id = tcx.hir.local_def_id(node_id); + let generics = tcx.generics_of(def_id); + if (generics.parent_types == 0 && generics.types.is_empty()) && + // Functions marked with #[inline] are only ever translated + // with "internal" linkage and are never exported. + !Instance::mono(tcx, def_id).def.requires_local(tcx) { + Some(def_id) + } else { + None + } + } - providers.exported_symbols = |tcx, cnum| { - assert_eq!(cnum, LOCAL_CRATE); - let local_exported_symbols = base::find_exported_symbols(tcx); - - let mut local_crate: Vec<_> = local_exported_symbols - .iter() - .map(|&node_id| { - tcx.hir.local_def_id(node_id) - }) - .map(|def_id| { - let name = tcx.symbol_name(Instance::mono(tcx, def_id)); - let export_level = export_level(tcx, def_id); - debug!("EXPORTED SYMBOL (local): {} ({:?})", name, export_level); - (str::to_owned(&name), Some(def_id), export_level) - }) - .collect(); - - if let Some(_) = *tcx.sess.entry_fn.borrow() { - local_crate.push(("main".to_string(), - None, - SymbolExportLevel::C)); - } - - if tcx.sess.allocator_kind.get().is_some() { - for method in ALLOCATOR_METHODS { - local_crate.push((format!("__rust_{}", method.name), - None, - SymbolExportLevel::Rust)); + _ => None } + }) + .collect(); + + if let Some(id) = tcx.sess.derive_registrar_fn.get() { + reachable_non_generics.insert(tcx.hir.local_def_id(id)); + } + + if let Some(id) = tcx.sess.plugin_registrar_fn.get() { + reachable_non_generics.insert(tcx.hir.local_def_id(id)); + } + + let mut symbols: Vec<_> = reachable_non_generics + .iter() + .map(|&def_id| { + let name = tcx.symbol_name(Instance::mono(tcx, def_id)); + let export_level = tcx.symbol_export_level(def_id); + debug!("EXPORTED SYMBOL (local): {} ({:?})", name, export_level); + (str::to_owned(&name), Some(def_id), export_level) + }) + .collect(); + + if let Some(_) = *tcx.sess.entry_fn.borrow() { + symbols.push(("main".to_string(), None, SymbolExportLevel::C)); + } + + if tcx.sess.allocator_kind.get().is_some() { + for method in ALLOCATOR_METHODS { + symbols.push((format!("__rust_{}", method.name), + None, + SymbolExportLevel::Rust)); } + } - if let Some(id) = tcx.sess.derive_registrar_fn.get() { - let def_id = tcx.hir.local_def_id(id); - let disambiguator = tcx.sess.local_crate_disambiguator(); - let registrar = tcx.sess.generate_derive_registrar_symbol(disambiguator); - local_crate.push((registrar, Some(def_id), SymbolExportLevel::C)); - } + if tcx.sess.crate_types.borrow().contains(&config::CrateTypeDylib) { + symbols.push((metadata_symbol_name(tcx), + None, + SymbolExportLevel::Rust)); + } - if tcx.sess.crate_types.borrow().contains(&config::CrateTypeDylib) { - local_crate.push((metadata_symbol_name(tcx), - None, - SymbolExportLevel::Rust)); - } + // Sort so we get a stable incr. comp. hash. + symbols.sort_unstable_by(|&(ref name1, ..), &(ref name2, ..)| { + name1.cmp(name2) + }); - // Sort so we get a stable incr. comp. hash. - local_crate.sort_unstable_by(|&(ref name1, ..), &(ref name2, ..)| { - name1.cmp(name2) - }); + Arc::new(symbols) +} - Arc::new(local_crate) - }; +pub fn provide(providers: &mut Providers) { + providers.reachable_non_generics = reachable_non_generics_provider; + providers.is_reachable_non_generic = is_reachable_non_generic_provider; + providers.exported_symbols = exported_symbols_provider_local; + providers.symbol_export_level = symbol_export_level_provider; +} - providers.symbol_export_level = export_level; +fn exported_symbols_provider_extern<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, + cnum: CrateNum) + -> Arc, + SymbolExportLevel)>> +{ + // If this crate is a plugin and/or a custom derive crate, then + // we're not even going to link those in so we skip those crates. + if tcx.plugin_registrar_fn(cnum).is_some() || + tcx.derive_registrar_fn(cnum).is_some() { + return Arc::new(Vec::new()) + } + + // Check to see if this crate is a "special runtime crate". These + // crates, implementation details of the standard library, typically + // have a bunch of `pub extern` and `#[no_mangle]` functions as the + // ABI between them. We don't want their symbols to have a `C` + // export level, however, as they're just implementation details. + // Down below we'll hardwire all of the symbols to the `Rust` export + // level instead. + let special_runtime_crate = + tcx.is_panic_runtime(cnum) || tcx.is_compiler_builtins(cnum); + + let mut crate_exports: Vec<_> = tcx + .reachable_non_generics(cnum) + .iter() + .map(|&def_id| { + let name = tcx.symbol_name(Instance::mono(tcx, def_id)); + let export_level = if special_runtime_crate { + // We can probably do better here by just ensuring that + // it has hidden visibility rather than public + // visibility, as this is primarily here to ensure it's + // not stripped during LTO. + // + // In general though we won't link right if these + // symbols are stripped, and LTO currently strips them. + if &*name == "rust_eh_personality" || + &*name == "rust_eh_register_frames" || + &*name == "rust_eh_unregister_frames" { + SymbolExportLevel::C + } else { + SymbolExportLevel::Rust + } + } else { + tcx.symbol_export_level(def_id) + }; + debug!("EXPORTED SYMBOL (re-export): {} ({:?})", name, export_level); + (str::to_owned(&name), Some(def_id), export_level) + }) + .collect(); + + // Sort so we get a stable incr. comp. hash. + crate_exports.sort_unstable_by(|&(ref name1, ..), &(ref name2, ..)| { + name1.cmp(name2) + }); + + Arc::new(crate_exports) } pub fn provide_extern(providers: &mut Providers) { - providers.exported_symbols = |tcx, cnum| { - // If this crate is a plugin and/or a custom derive crate, then - // we're not even going to link those in so we skip those crates. - if tcx.plugin_registrar_fn(cnum).is_some() || - tcx.derive_registrar_fn(cnum).is_some() { - return Arc::new(Vec::new()) - } - - // Check to see if this crate is a "special runtime crate". These - // crates, implementation details of the standard library, typically - // have a bunch of `pub extern` and `#[no_mangle]` functions as the - // ABI between them. We don't want their symbols to have a `C` - // export level, however, as they're just implementation details. - // Down below we'll hardwire all of the symbols to the `Rust` export - // level instead. - let special_runtime_crate = - tcx.is_panic_runtime(cnum) || tcx.is_compiler_builtins(cnum); - - let mut crate_exports: Vec<_> = tcx - .reachable_non_generics(cnum) - .iter() - .map(|&def_id| { - let name = tcx.symbol_name(Instance::mono(tcx, def_id)); - let export_level = if special_runtime_crate { - // We can probably do better here by just ensuring that - // it has hidden visibility rather than public - // visibility, as this is primarily here to ensure it's - // not stripped during LTO. - // - // In general though we won't link right if these - // symbols are stripped, and LTO currently strips them. - if &*name == "rust_eh_personality" || - &*name == "rust_eh_register_frames" || - &*name == "rust_eh_unregister_frames" { - SymbolExportLevel::C - } else { - SymbolExportLevel::Rust - } - } else { - export_level(tcx, def_id) - }; - debug!("EXPORTED SYMBOL (re-export): {} ({:?})", name, export_level); - (str::to_owned(&name), Some(def_id), export_level) - }) - .collect(); - - // Sort so we get a stable incr. comp. hash. - crate_exports.sort_unstable_by(|&(ref name1, ..), &(ref name2, ..)| { - name1.cmp(name2) - }); - - Arc::new(crate_exports) - }; - - providers.is_reachable_non_generic = |tcx, id| { - tcx.reachable_non_generics(id.krate).contains(&id) - }; - - providers.symbol_export_level = export_level; + providers.exported_symbols = exported_symbols_provider_extern; + providers.is_reachable_non_generic = is_reachable_non_generic_provider; + providers.symbol_export_level = symbol_export_level_provider; } -fn export_level(tcx: TyCtxt, sym_def_id: DefId) -> SymbolExportLevel { +fn symbol_export_level_provider(tcx: TyCtxt, sym_def_id: DefId) -> SymbolExportLevel { // We export anything that's not mangled at the "C" layer as it probably has // to do with ABI concerns. We do not, however, apply such treatment to // special symbols in the standard library for various plumbing between diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs index c0785f539371..b559cc963257 100644 --- a/src/librustc_trans/base.rs +++ b/src/librustc_trans/base.rs @@ -70,7 +70,7 @@ use time_graph; use trans_item::{MonoItem, BaseMonoItemExt, MonoItemExt, DefPathBasedNames}; use type_::Type; use type_of::LayoutLlvmExt; -use rustc::util::nodemap::{NodeSet, FxHashMap, FxHashSet, DefIdSet}; +use rustc::util::nodemap::{FxHashMap, FxHashSet, DefIdSet}; use CrateInfo; use std::any::Any; @@ -89,7 +89,7 @@ use syntax::ast; use mir::operand::OperandValue; -pub use rustc_trans_utils::{find_exported_symbols, check_for_rustc_errors_attr}; +pub use rustc_trans_utils::check_for_rustc_errors_attr; pub use rustc_mir::monomorphize::item::linkage_by_name; pub struct StatRecorder<'a, 'tcx: 'a> { @@ -606,8 +606,7 @@ fn contains_null(s: &str) -> bool { fn write_metadata<'a, 'gcx>(tcx: TyCtxt<'a, 'gcx, 'gcx>, llmod_id: &str, - link_meta: &LinkMeta, - exported_symbols: &NodeSet) + link_meta: &LinkMeta) -> (ContextRef, ModuleRef, EncodedMetadata) { use std::io::Write; use flate2::Compression; @@ -643,7 +642,7 @@ fn write_metadata<'a, 'gcx>(tcx: TyCtxt<'a, 'gcx, 'gcx>, EncodedMetadata::new()); } - let metadata = tcx.encode_metadata(link_meta, exported_symbols); + let metadata = tcx.encode_metadata(link_meta); if kind == MetadataKind::Uncompressed { return (metadata_llcx, metadata_llmod, metadata); } @@ -718,13 +717,12 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let crate_hash = tcx.crate_hash(LOCAL_CRATE); let link_meta = link::build_link_meta(crate_hash); - let exported_symbol_node_ids = find_exported_symbols(tcx); // Translate the metadata. let llmod_id = "metadata"; let (metadata_llcx, metadata_llmod, metadata) = time(tcx.sess.time_passes(), "write metadata", || { - write_metadata(tcx, llmod_id, &link_meta, &exported_symbol_node_ids) + write_metadata(tcx, llmod_id, &link_meta) }); let metadata_module = ModuleTranslation { diff --git a/src/librustc_trans_utils/lib.rs b/src/librustc_trans_utils/lib.rs index bfecb2019836..d636a5f2e64b 100644 --- a/src/librustc_trans_utils/lib.rs +++ b/src/librustc_trans_utils/lib.rs @@ -44,11 +44,7 @@ extern crate rustc_data_structures; pub extern crate rustc as __rustc; -use rustc::ty::{TyCtxt, Instance}; -use rustc::hir; -use rustc::hir::def_id::LOCAL_CRATE; -use rustc::hir::map as hir_map; -use rustc::util::nodemap::NodeSet; +use rustc::ty::TyCtxt; pub mod diagnostics; pub mod link; @@ -70,53 +66,4 @@ pub fn check_for_rustc_errors_attr(tcx: TyCtxt) { } } -/// The context provided lists a set of reachable ids as calculated by -/// middle::reachable, but this contains far more ids and symbols than we're -/// actually exposing from the object file. This function will filter the set in -/// the context to the set of ids which correspond to symbols that are exposed -/// from the object file being generated. -/// -/// This list is later used by linkers to determine the set of symbols needed to -/// be exposed from a dynamic library and it's also encoded into the metadata. -pub fn find_exported_symbols<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> NodeSet { - tcx.reachable_set(LOCAL_CRATE).0.iter().cloned().filter(|&id| { - // Next, we want to ignore some FFI functions that are not exposed from - // this crate. Reachable FFI functions can be lumped into two - // categories: - // - // 1. Those that are included statically via a static library - // 2. Those included otherwise (e.g. dynamically or via a framework) - // - // Although our LLVM module is not literally emitting code for the - // statically included symbols, it's an export of our library which - // needs to be passed on to the linker and encoded in the metadata. - // - // As a result, if this id is an FFI item (foreign item) then we only - // let it through if it's included statically. - match tcx.hir.get(id) { - hir_map::NodeForeignItem(..) => { - let def_id = tcx.hir.local_def_id(id); - tcx.is_statically_included_foreign_item(def_id) - } - - // Only consider nodes that actually have exported symbols. - hir_map::NodeItem(&hir::Item { - node: hir::ItemStatic(..), .. }) | - hir_map::NodeItem(&hir::Item { - node: hir::ItemFn(..), .. }) | - hir_map::NodeImplItem(&hir::ImplItem { - node: hir::ImplItemKind::Method(..), .. }) => { - let def_id = tcx.hir.local_def_id(id); - let generics = tcx.generics_of(def_id); - (generics.parent_types == 0 && generics.types.is_empty()) && - // Functions marked with #[inline] are only ever translated - // with "internal" linkage and are never exported. - !Instance::mono(tcx, def_id).def.requires_local(tcx) - } - - _ => false - } - }).collect() -} - __build_diagnostic_array! { librustc_trans_utils, DIAGNOSTICS } diff --git a/src/librustc_trans_utils/trans_crate.rs b/src/librustc_trans_utils/trans_crate.rs index 419371ba3e33..7b2cbe140aeb 100644 --- a/src/librustc_trans_utils/trans_crate.rs +++ b/src/librustc_trans_utils/trans_crate.rs @@ -247,8 +247,7 @@ impl TransCrate for MetadataOnlyTransCrate { tcx.sess.abort_if_errors(); let link_meta = build_link_meta(tcx.crate_hash(LOCAL_CRATE)); - let exported_symbols = ::find_exported_symbols(tcx); - let metadata = tcx.encode_metadata(&link_meta, &exported_symbols); + let metadata = tcx.encode_metadata(&link_meta); box OngoingCrateTranslation { metadata: metadata, From aec6c85b0c6281d938bdd80e98fa9473d8b27780 Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Tue, 27 Feb 2018 17:52:07 +0100 Subject: [PATCH 64/68] Compute symbol names more lazily. --- src/librustc/middle/exported_symbols.rs | 53 ++++++++++++++++++++ src/librustc/ty/maps/mod.rs | 4 +- src/librustc/ty/mod.rs | 16 +++++- src/librustc_trans/back/linker.rs | 8 +-- src/librustc_trans/back/lto.rs | 2 +- src/librustc_trans/back/symbol_export.rs | 63 ++++++++++++++---------- src/librustc_trans/back/write.rs | 37 +++++++++----- 7 files changed, 135 insertions(+), 48 deletions(-) diff --git a/src/librustc/middle/exported_symbols.rs b/src/librustc/middle/exported_symbols.rs index d650dbe88b5c..c9b3acdd836e 100644 --- a/src/librustc/middle/exported_symbols.rs +++ b/src/librustc/middle/exported_symbols.rs @@ -8,6 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use hir::def_id::DefId; +use std::cmp; +use ty; + /// The SymbolExportLevel of a symbols specifies from which kinds of crates /// the symbol will be exported. `C` symbols will be exported from any /// kind of crate, including cdylibs which export very few things. @@ -34,3 +38,52 @@ impl SymbolExportLevel { } } } + +#[derive(Eq, PartialEq, Debug, Copy, Clone)] +pub enum ExportedSymbol { + NonGeneric(DefId), + NoDefId(ty::SymbolName), +} + +impl ExportedSymbol { + pub fn symbol_name(&self, tcx: ty::TyCtxt) -> ty::SymbolName { + match *self { + ExportedSymbol::NonGeneric(def_id) => { + tcx.symbol_name(ty::Instance::mono(tcx, def_id)) + } + ExportedSymbol::NoDefId(symbol_name) => { + symbol_name + } + } + } + + pub fn compare_stable(&self, tcx: ty::TyCtxt, other: &ExportedSymbol) -> cmp::Ordering { + match *self { + ExportedSymbol::NonGeneric(self_def_id) => { + match *other { + ExportedSymbol::NonGeneric(other_def_id) => { + tcx.def_path_hash(self_def_id).cmp(&tcx.def_path_hash(other_def_id)) + } + ExportedSymbol::NoDefId(_) => { + cmp::Ordering::Less + } + } + } + ExportedSymbol::NoDefId(self_symbol_name) => { + match *other { + ExportedSymbol::NonGeneric(_) => { + cmp::Ordering::Greater + } + ExportedSymbol::NoDefId(ref other_symbol_name) => { + self_symbol_name.cmp(other_symbol_name) + } + } + } + } + } +} + +impl_stable_hash_for!(enum self::ExportedSymbol { + NonGeneric(def_id), + NoDefId(symbol_name) +}); diff --git a/src/librustc/ty/maps/mod.rs b/src/librustc/ty/maps/mod.rs index e91ccce8ffa9..2ef97b2673d6 100644 --- a/src/librustc/ty/maps/mod.rs +++ b/src/librustc/ty/maps/mod.rs @@ -26,7 +26,7 @@ use middle::region; use middle::resolve_lifetime::{ResolveLifetimes, Region, ObjectLifetimeDefault}; use middle::stability::{self, DeprecationEntry}; use middle::lang_items::{LanguageItems, LangItem}; -use middle::exported_symbols::SymbolExportLevel; +use middle::exported_symbols::{SymbolExportLevel, ExportedSymbol}; use mir::mono::{CodegenUnit, Stats}; use mir; use session::{CompileResult, CrateDisambiguator}; @@ -358,7 +358,7 @@ define_maps! { <'tcx> [] fn all_crate_nums: all_crate_nums_node(CrateNum) -> Lrc>, [] fn exported_symbols: ExportedSymbols(CrateNum) - -> Arc, SymbolExportLevel)>>, + -> Arc>, [] fn collect_and_partition_translation_items: collect_and_partition_translation_items_node(CrateNum) -> (Arc, Arc>>>), diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index f6f4e1ceb156..a7c55880e2e1 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -2806,7 +2806,7 @@ impl<'tcx> DtorckConstraint<'tcx> { } } -#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, RustcEncodable, RustcDecodable)] +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, RustcEncodable, RustcDecodable)] pub struct SymbolName { // FIXME: we don't rely on interning or equality here - better have // this be a `&'tcx str`. @@ -2817,6 +2817,14 @@ impl_stable_hash_for!(struct self::SymbolName { name }); +impl SymbolName { + pub fn new(name: &str) -> SymbolName { + SymbolName { + name: Symbol::intern(name).as_str() + } + } +} + impl Deref for SymbolName { type Target = str; @@ -2828,3 +2836,9 @@ impl fmt::Display for SymbolName { fmt::Display::fmt(&self.name, fmt) } } + +impl fmt::Debug for SymbolName { + fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { + fmt::Display::fmt(&self.name, fmt) + } +} diff --git a/src/librustc_trans/back/linker.rs b/src/librustc_trans/back/linker.rs index a3ff39a47a29..3fe667f15437 100644 --- a/src/librustc_trans/back/linker.rs +++ b/src/librustc_trans/back/linker.rs @@ -768,9 +768,9 @@ fn exported_symbols(tcx: TyCtxt, crate_type: CrateType) -> Vec { let mut symbols = Vec::new(); let export_threshold = symbol_export::crates_export_threshold(&[crate_type]); - for &(ref name, _, level) in tcx.exported_symbols(LOCAL_CRATE).iter() { + for &(symbol, level) in tcx.exported_symbols(LOCAL_CRATE).iter() { if level.is_below_threshold(export_threshold) { - symbols.push(name.clone()); + symbols.push(symbol.symbol_name(tcx).to_string()); } } @@ -782,9 +782,9 @@ fn exported_symbols(tcx: TyCtxt, crate_type: CrateType) -> Vec { // For each dependency that we are linking to statically ... if *dep_format == Linkage::Static { // ... we add its symbol list to our export list. - for &(ref name, _, level) in tcx.exported_symbols(cnum).iter() { + for &(symbol, level) in tcx.exported_symbols(cnum).iter() { if level.is_below_threshold(export_threshold) { - symbols.push(name.clone()); + symbols.push(symbol.symbol_name(tcx).to_string()); } } } diff --git a/src/librustc_trans/back/lto.rs b/src/librustc_trans/back/lto.rs index 3f9e9191cf03..f79651cef3ec 100644 --- a/src/librustc_trans/back/lto.rs +++ b/src/librustc_trans/back/lto.rs @@ -113,7 +113,7 @@ pub(crate) fn run(cgcx: &CodegenContext, Lto::No => panic!("didn't request LTO but we're doing LTO"), }; - let symbol_filter = &|&(ref name, _, level): &(String, _, SymbolExportLevel)| { + let symbol_filter = &|&(ref name, level): &(String, SymbolExportLevel)| { if level.is_below_threshold(export_threshold) { let mut bytes = Vec::with_capacity(name.len() + 1); bytes.extend(name.bytes()); diff --git a/src/librustc_trans/back/symbol_export.rs b/src/librustc_trans/back/symbol_export.rs index 74f7a6e8d9cd..4e3a37104886 100644 --- a/src/librustc_trans/back/symbol_export.rs +++ b/src/librustc_trans/back/symbol_export.rs @@ -15,9 +15,9 @@ use monomorphize::Instance; use rustc::hir; use rustc::hir::def_id::CrateNum; use rustc::hir::def_id::{DefId, LOCAL_CRATE}; -use rustc::middle::exported_symbols::SymbolExportLevel; +use rustc::middle::exported_symbols::{SymbolExportLevel, ExportedSymbol}; use rustc::session::config; -use rustc::ty::TyCtxt; +use rustc::ty::{TyCtxt, SymbolName}; use rustc::ty::maps::Providers; use rustc::util::nodemap::{FxHashMap, DefIdSet}; use rustc_allocator::ALLOCATOR_METHODS; @@ -25,7 +25,7 @@ use syntax::attr; pub type ExportedSymbols = FxHashMap< CrateNum, - Arc, SymbolExportLevel)>>, + Arc>, >; pub fn threshold(tcx: TyCtxt) -> SymbolExportLevel { @@ -78,9 +78,10 @@ fn reachable_non_generics_provider<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let reachable_non_generics = tcx .exported_symbols(LOCAL_CRATE) .iter() - .filter_map(|&(_, opt_def_id, level)| { - if let Some(def_id) = opt_def_id { - if level.is_below_threshold(export_threshold) { + .filter_map(|&(exported_symbol, _)| { + if let ExportedSymbol::NonGeneric(def_id) = exported_symbol { + if tcx.symbol_export_level(def_id) + .is_below_threshold(export_threshold) { return Some(def_id) } } @@ -100,8 +101,7 @@ fn is_reachable_non_generic_provider<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, fn exported_symbols_provider_local<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, cnum: CrateNum) - -> Arc, + -> Arc> { assert_eq!(cnum, LOCAL_CRATE); @@ -176,34 +176,40 @@ fn exported_symbols_provider_local<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let mut symbols: Vec<_> = reachable_non_generics .iter() .map(|&def_id| { - let name = tcx.symbol_name(Instance::mono(tcx, def_id)); let export_level = tcx.symbol_export_level(def_id); - debug!("EXPORTED SYMBOL (local): {} ({:?})", name, export_level); - (str::to_owned(&name), Some(def_id), export_level) + debug!("EXPORTED SYMBOL (local): {} ({:?})", + tcx.symbol_name(Instance::mono(tcx, def_id)), + export_level); + (ExportedSymbol::NonGeneric(def_id), export_level) }) .collect(); if let Some(_) = *tcx.sess.entry_fn.borrow() { - symbols.push(("main".to_string(), None, SymbolExportLevel::C)); + let symbol_name = "main".to_string(); + let exported_symbol = ExportedSymbol::NoDefId(SymbolName::new(&symbol_name)); + + symbols.push((exported_symbol, SymbolExportLevel::C)); } if tcx.sess.allocator_kind.get().is_some() { for method in ALLOCATOR_METHODS { - symbols.push((format!("__rust_{}", method.name), - None, - SymbolExportLevel::Rust)); + let symbol_name = format!("__rust_{}", method.name); + let exported_symbol = ExportedSymbol::NoDefId(SymbolName::new(&symbol_name)); + + symbols.push((exported_symbol, SymbolExportLevel::Rust)); } } if tcx.sess.crate_types.borrow().contains(&config::CrateTypeDylib) { - symbols.push((metadata_symbol_name(tcx), - None, - SymbolExportLevel::Rust)); + let symbol_name = metadata_symbol_name(tcx); + let exported_symbol = ExportedSymbol::NoDefId(SymbolName::new(&symbol_name)); + + symbols.push((exported_symbol, SymbolExportLevel::Rust)); } // Sort so we get a stable incr. comp. hash. - symbols.sort_unstable_by(|&(ref name1, ..), &(ref name2, ..)| { - name1.cmp(name2) + symbols.sort_unstable_by(|&(ref symbol1, ..), &(ref symbol2, ..)| { + symbol1.compare_stable(tcx, symbol2) }); Arc::new(symbols) @@ -218,8 +224,7 @@ pub fn provide(providers: &mut Providers) { fn exported_symbols_provider_extern<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, cnum: CrateNum) - -> Arc, + -> Arc> { // If this crate is a plugin and/or a custom derive crate, then @@ -243,8 +248,8 @@ fn exported_symbols_provider_extern<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, .reachable_non_generics(cnum) .iter() .map(|&def_id| { - let name = tcx.symbol_name(Instance::mono(tcx, def_id)); let export_level = if special_runtime_crate { + let name = tcx.symbol_name(Instance::mono(tcx, def_id)); // We can probably do better here by just ensuring that // it has hidden visibility rather than public // visibility, as this is primarily here to ensure it's @@ -262,14 +267,18 @@ fn exported_symbols_provider_extern<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } else { tcx.symbol_export_level(def_id) }; - debug!("EXPORTED SYMBOL (re-export): {} ({:?})", name, export_level); - (str::to_owned(&name), Some(def_id), export_level) + + debug!("EXPORTED SYMBOL (re-export): {} ({:?})", + tcx.symbol_name(Instance::mono(tcx, def_id)), + export_level); + + (ExportedSymbol::NonGeneric(def_id), export_level) }) .collect(); // Sort so we get a stable incr. comp. hash. - crate_exports.sort_unstable_by(|&(ref name1, ..), &(ref name2, ..)| { - name1.cmp(name2) + crate_exports.sort_unstable_by(|&(ref symbol1, ..), &(ref symbol2, ..)| { + symbol1.compare_stable(tcx, symbol2) }); Arc::new(crate_exports) diff --git a/src/librustc_trans/back/write.rs b/src/librustc_trans/back/write.rs index 78b26a37485e..c0561ff0c173 100644 --- a/src/librustc_trans/back/write.rs +++ b/src/librustc_trans/back/write.rs @@ -1332,20 +1332,31 @@ fn start_executing_work(tcx: TyCtxt, let coordinator_send = tcx.tx_to_llvm_workers.clone(); let sess = tcx.sess; - let exported_symbols = match sess.lto() { - Lto::No => None, - Lto::ThinLocal => { - let mut exported_symbols = FxHashMap(); - exported_symbols.insert(LOCAL_CRATE, tcx.exported_symbols(LOCAL_CRATE)); - Some(Arc::new(exported_symbols)) - } - Lto::Yes | Lto::Fat | Lto::Thin => { - let mut exported_symbols = FxHashMap(); - exported_symbols.insert(LOCAL_CRATE, tcx.exported_symbols(LOCAL_CRATE)); - for &cnum in tcx.crates().iter() { - exported_symbols.insert(cnum, tcx.exported_symbols(cnum)); + // Compute the set of symbols we need to retain when doing LTO (if we need to) + let exported_symbols = { + let mut exported_symbols = FxHashMap(); + + let copy_symbols = |cnum| { + let symbols = tcx.exported_symbols(cnum) + .iter() + .map(|&(s, lvl)| (s.symbol_name(tcx).to_string(), lvl)) + .collect(); + Arc::new(symbols) + }; + + match sess.lto() { + Lto::No => None, + Lto::ThinLocal => { + exported_symbols.insert(LOCAL_CRATE, copy_symbols(LOCAL_CRATE)); + Some(Arc::new(exported_symbols)) + } + Lto::Yes | Lto::Fat | Lto::Thin => { + exported_symbols.insert(LOCAL_CRATE, copy_symbols(LOCAL_CRATE)); + for &cnum in tcx.crates().iter() { + exported_symbols.insert(cnum, copy_symbols(cnum)); + } + Some(Arc::new(exported_symbols)) } - Some(Arc::new(exported_symbols)) } }; From 8bc005c8bb26f8d84066a096780c765ba431d721 Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Tue, 27 Feb 2018 19:28:21 +0100 Subject: [PATCH 65/68] Don't recompute SymbolExportLevel for upstream crates. --- src/librustc/middle/exported_symbols.rs | 4 +- src/librustc/ty/context.rs | 8 ++ src/librustc_metadata/cstore_impl.rs | 32 +++++++- src/librustc_metadata/decoder.rs | 7 +- src/librustc_metadata/encoder.rs | 28 ++++--- src/librustc_metadata/schema.rs | 4 +- src/librustc_trans/back/symbol_export.rs | 98 ++++++++---------------- 7 files changed, 91 insertions(+), 90 deletions(-) diff --git a/src/librustc/middle/exported_symbols.rs b/src/librustc/middle/exported_symbols.rs index c9b3acdd836e..fb971dd2515c 100644 --- a/src/librustc/middle/exported_symbols.rs +++ b/src/librustc/middle/exported_symbols.rs @@ -17,7 +17,7 @@ use ty; /// kind of crate, including cdylibs which export very few things. /// `Rust` will only be exported if the crate produced is a Rust /// dylib. -#[derive(Eq, PartialEq, Debug, Copy, Clone)] +#[derive(Eq, PartialEq, Debug, Copy, Clone, RustcEncodable, RustcDecodable)] pub enum SymbolExportLevel { C, Rust, @@ -39,7 +39,7 @@ impl SymbolExportLevel { } } -#[derive(Eq, PartialEq, Debug, Copy, Clone)] +#[derive(Eq, PartialEq, Debug, Copy, Clone, RustcEncodable, RustcDecodable)] pub enum ExportedSymbol { NonGeneric(DefId), NoDefId(ty::SymbolName), diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index aac6b3dc08a7..47a3580e8676 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -2460,4 +2460,12 @@ pub fn provide(providers: &mut ty::maps::Providers) { assert_eq!(cnum, LOCAL_CRATE); Lrc::new(tcx.sess.features_untracked().clone()) }; + providers.is_panic_runtime = |tcx, cnum| { + assert_eq!(cnum, LOCAL_CRATE); + attr::contains_name(tcx.hir.krate_attrs(), "panic_runtime") + }; + providers.is_compiler_builtins = |tcx, cnum| { + assert_eq!(cnum, LOCAL_CRATE); + attr::contains_name(tcx.hir.krate_attrs(), "compiler_builtins") + }; } diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index 00862816d57b..0a2270571f3f 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -18,6 +18,7 @@ use rustc::ty::maps::QueryConfig; use rustc::middle::cstore::{CrateStore, DepKind, MetadataLoader, LinkMeta, LoadedMacro, EncodedMetadata, NativeLibraryKind}; +use rustc::middle::exported_symbols::ExportedSymbol; use rustc::middle::stability::DeprecationEntry; use rustc::hir::def; use rustc::session::{CrateDisambiguator, Session}; @@ -31,6 +32,7 @@ use rustc::util::nodemap::DefIdMap; use std::any::Any; use rustc_data_structures::sync::Lrc; +use std::sync::Arc; use syntax::ast; use syntax::attr; @@ -176,7 +178,21 @@ provide! { <'tcx> tcx, def_id, other, cdata, extern_crate => { Lrc::new(cdata.extern_crate.get()) } is_no_builtins => { cdata.is_no_builtins(tcx.sess) } impl_defaultness => { cdata.get_impl_defaultness(def_id.index) } - reachable_non_generics => { Lrc::new(cdata.reachable_non_generics()) } + reachable_non_generics => { + let reachable_non_generics = tcx + .exported_symbols(cdata.cnum) + .iter() + .filter_map(|&(exported_symbol, _)| { + if let ExportedSymbol::NonGeneric(def_id) = exported_symbol { + return Some(def_id) + } else { + None + } + }) + .collect(); + + Lrc::new(reachable_non_generics) + } native_libraries => { Lrc::new(cdata.get_native_libraries(tcx.sess)) } plugin_registrar_fn => { cdata.root.plugin_registrar_fn.map(|index| { @@ -235,6 +251,20 @@ provide! { <'tcx> tcx, def_id, other, cdata, has_copy_closures => { cdata.has_copy_closures(tcx.sess) } has_clone_closures => { cdata.has_clone_closures(tcx.sess) } + + exported_symbols => { + let cnum = cdata.cnum; + assert!(cnum != LOCAL_CRATE); + + // If this crate is a plugin and/or a custom derive crate, then + // we're not even going to link those in so we skip those crates. + if cdata.root.plugin_registrar_fn.is_some() || + cdata.root.macro_derive_registrar.is_some() { + return Arc::new(Vec::new()) + } + + Arc::new(cdata.exported_symbols()) + } } pub fn provide<'tcx>(providers: &mut Providers<'tcx>) { diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index 2831b63bbac5..60a0d4e03b54 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -18,6 +18,7 @@ use rustc::hir::map::{DefKey, DefPath, DefPathData, DefPathHash}; use rustc::hir; use rustc::middle::cstore::{LinkagePreference, ExternConstBody, ExternBodyNestedBodies}; +use rustc::middle::exported_symbols::{ExportedSymbol, SymbolExportLevel}; use rustc::hir::def::{self, Def, CtorKind}; use rustc::hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX, LOCAL_CRATE}; @@ -27,7 +28,6 @@ use rustc::mir; use rustc::session::Session; use rustc::ty::{self, Ty, TyCtxt}; use rustc::ty::codec::TyDecoder; -use rustc::util::nodemap::DefIdSet; use rustc::mir::Mir; use std::cell::Ref; @@ -1006,11 +1006,10 @@ impl<'a, 'tcx> CrateMetadata { arg_names.decode(self).collect() } - pub fn reachable_non_generics(&self) -> DefIdSet { + pub fn exported_symbols(&self) -> Vec<(ExportedSymbol, SymbolExportLevel)> { self.root - .reachable_non_generics + .exported_symbols .decode(self) - .map(|index| self.local_def_id(index)) .collect() } diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index c649cf62dc5d..1c54b7aa1333 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -20,6 +20,7 @@ use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefIndex, DefId, LOCAL_CRATE use rustc::hir::map::definitions::DefPathTable; use rustc::ich::Fingerprint; use rustc::middle::dependency_format::Linkage; +use rustc::middle::exported_symbols::{ExportedSymbol, SymbolExportLevel}; use rustc::middle::lang_items; use rustc::mir; use rustc::traits::specialization_graph; @@ -27,7 +28,7 @@ use rustc::ty::{self, Ty, TyCtxt, ReprOptions}; use rustc::ty::codec::{self as ty_codec, TyEncoder}; use rustc::session::config::{self, CrateTypeProcMacro}; -use rustc::util::nodemap::{FxHashMap, DefIdSet}; +use rustc::util::nodemap::FxHashMap; use rustc_data_structures::stable_hasher::StableHasher; use rustc_serialize::{Encodable, Encoder, SpecializedEncoder, opaque}; @@ -394,11 +395,11 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { // Encode exported symbols info. i = self.position(); - let reachable_non_generics = self.tcx.reachable_non_generics(LOCAL_CRATE); - let reachable_non_generics = self.tracked( - IsolatedEncoder::encode_reachable_non_generics, - &reachable_non_generics); - let reachable_non_generics_bytes = self.position() - i; + let exported_symbols = self.tcx.exported_symbols(LOCAL_CRATE); + let exported_symbols = self.tracked( + IsolatedEncoder::encode_exported_symbols, + &exported_symbols); + let exported_symbols_bytes = self.position() - i; // Encode and index the items. i = self.position(); @@ -442,7 +443,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { codemap, def_path_table, impls, - reachable_non_generics, + exported_symbols, index, }); @@ -462,7 +463,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { println!(" native bytes: {}", native_lib_bytes); println!(" codemap bytes: {}", codemap_bytes); println!(" impl bytes: {}", impl_bytes); - println!(" exp. symbols bytes: {}", reachable_non_generics_bytes); + println!(" exp. symbols bytes: {}", exported_symbols_bytes); println!(" def-path table bytes: {}", def_path_table_bytes); println!(" item bytes: {}", item_bytes); println!(" index bytes: {}", index_bytes); @@ -1388,13 +1389,10 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { // middle::reachable module but filters out items that either don't have a // symbol associated with them (they weren't translated) or if they're an FFI // definition (as that's not defined in this crate). - fn encode_reachable_non_generics(&mut self, - reachable_non_generics: &DefIdSet) - -> LazySeq { - self.lazy_seq(reachable_non_generics.iter().map(|def_id| { - debug_assert!(def_id.is_local()); - def_id.index - })) + fn encode_exported_symbols(&mut self, + exported_symbols: &[(ExportedSymbol, SymbolExportLevel)]) + -> LazySeq<(ExportedSymbol, SymbolExportLevel)> { + self.lazy_seq(exported_symbols.iter().cloned()) } fn encode_dylib_dependency_formats(&mut self, _: ()) -> LazySeq> { diff --git a/src/librustc_metadata/schema.rs b/src/librustc_metadata/schema.rs index 3e7d31513a22..ce94e4f912f4 100644 --- a/src/librustc_metadata/schema.rs +++ b/src/librustc_metadata/schema.rs @@ -16,6 +16,7 @@ use rustc::hir::def::{self, CtorKind}; use rustc::hir::def_id::{DefIndex, DefId, CrateNum}; use rustc::ich::StableHashingContext; use rustc::middle::cstore::{DepKind, LinkagePreference, NativeLibrary}; +use rustc::middle::exported_symbols::{ExportedSymbol, SymbolExportLevel}; use rustc::middle::lang_items; use rustc::mir; use rustc::session::CrateDisambiguator; @@ -202,7 +203,8 @@ pub struct CrateRoot { pub codemap: LazySeq, pub def_path_table: Lazy, pub impls: LazySeq, - pub reachable_non_generics: LazySeq, + pub exported_symbols: LazySeq<(ExportedSymbol, SymbolExportLevel)>, + pub index: LazySeq, } diff --git a/src/librustc_trans/back/symbol_export.rs b/src/librustc_trans/back/symbol_export.rs index 4e3a37104886..0873c1632f58 100644 --- a/src/librustc_trans/back/symbol_export.rs +++ b/src/librustc_trans/back/symbol_export.rs @@ -78,10 +78,9 @@ fn reachable_non_generics_provider<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let reachable_non_generics = tcx .exported_symbols(LOCAL_CRATE) .iter() - .filter_map(|&(exported_symbol, _)| { + .filter_map(|&(exported_symbol, level)| { if let ExportedSymbol::NonGeneric(def_id) = exported_symbol { - if tcx.symbol_export_level(def_id) - .is_below_threshold(export_threshold) { + if level.is_below_threshold(export_threshold) { return Some(def_id) } } @@ -110,6 +109,16 @@ fn exported_symbols_provider_local<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, return Arc::new(vec![]) } + // Check to see if this crate is a "special runtime crate". These + // crates, implementation details of the standard library, typically + // have a bunch of `pub extern` and `#[no_mangle]` functions as the + // ABI between them. We don't want their symbols to have a `C` + // export level, however, as they're just implementation details. + // Down below we'll hardwire all of the symbols to the `Rust` export + // level instead. + let special_runtime_crate = tcx.is_panic_runtime(LOCAL_CRATE) || + tcx.is_compiler_builtins(LOCAL_CRATE); + let mut reachable_non_generics: DefIdSet = tcx.reachable_set(LOCAL_CRATE).0 .iter() .filter_map(|&node_id| { @@ -176,7 +185,25 @@ fn exported_symbols_provider_local<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let mut symbols: Vec<_> = reachable_non_generics .iter() .map(|&def_id| { - let export_level = tcx.symbol_export_level(def_id); + let export_level = if special_runtime_crate { + let name = tcx.symbol_name(Instance::mono(tcx, def_id)); + // We can probably do better here by just ensuring that + // it has hidden visibility rather than public + // visibility, as this is primarily here to ensure it's + // not stripped during LTO. + // + // In general though we won't link right if these + // symbols are stripped, and LTO currently strips them. + if &*name == "rust_eh_personality" || + &*name == "rust_eh_register_frames" || + &*name == "rust_eh_unregister_frames" { + SymbolExportLevel::C + } else { + SymbolExportLevel::Rust + } + } else { + tcx.symbol_export_level(def_id) + }; debug!("EXPORTED SYMBOL (local): {} ({:?})", tcx.symbol_name(Instance::mono(tcx, def_id)), export_level); @@ -222,70 +249,7 @@ pub fn provide(providers: &mut Providers) { providers.symbol_export_level = symbol_export_level_provider; } -fn exported_symbols_provider_extern<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, - cnum: CrateNum) - -> Arc> -{ - // If this crate is a plugin and/or a custom derive crate, then - // we're not even going to link those in so we skip those crates. - if tcx.plugin_registrar_fn(cnum).is_some() || - tcx.derive_registrar_fn(cnum).is_some() { - return Arc::new(Vec::new()) - } - - // Check to see if this crate is a "special runtime crate". These - // crates, implementation details of the standard library, typically - // have a bunch of `pub extern` and `#[no_mangle]` functions as the - // ABI between them. We don't want their symbols to have a `C` - // export level, however, as they're just implementation details. - // Down below we'll hardwire all of the symbols to the `Rust` export - // level instead. - let special_runtime_crate = - tcx.is_panic_runtime(cnum) || tcx.is_compiler_builtins(cnum); - - let mut crate_exports: Vec<_> = tcx - .reachable_non_generics(cnum) - .iter() - .map(|&def_id| { - let export_level = if special_runtime_crate { - let name = tcx.symbol_name(Instance::mono(tcx, def_id)); - // We can probably do better here by just ensuring that - // it has hidden visibility rather than public - // visibility, as this is primarily here to ensure it's - // not stripped during LTO. - // - // In general though we won't link right if these - // symbols are stripped, and LTO currently strips them. - if &*name == "rust_eh_personality" || - &*name == "rust_eh_register_frames" || - &*name == "rust_eh_unregister_frames" { - SymbolExportLevel::C - } else { - SymbolExportLevel::Rust - } - } else { - tcx.symbol_export_level(def_id) - }; - - debug!("EXPORTED SYMBOL (re-export): {} ({:?})", - tcx.symbol_name(Instance::mono(tcx, def_id)), - export_level); - - (ExportedSymbol::NonGeneric(def_id), export_level) - }) - .collect(); - - // Sort so we get a stable incr. comp. hash. - crate_exports.sort_unstable_by(|&(ref symbol1, ..), &(ref symbol2, ..)| { - symbol1.compare_stable(tcx, symbol2) - }); - - Arc::new(crate_exports) -} - pub fn provide_extern(providers: &mut Providers) { - providers.exported_symbols = exported_symbols_provider_extern; providers.is_reachable_non_generic = is_reachable_non_generic_provider; providers.symbol_export_level = symbol_export_level_provider; } From 9f6d55463889bd019913e71c8a235beed8f29f45 Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Wed, 28 Feb 2018 17:40:25 +0100 Subject: [PATCH 66/68] Fix export level of plugin and procmacro registrars. --- src/librustc_metadata/cstore_impl.rs | 7 +++---- src/librustc_trans/back/symbol_export.rs | 20 +++++++++++--------- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index 0a2270571f3f..0b50f5c44962 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -256,10 +256,9 @@ provide! { <'tcx> tcx, def_id, other, cdata, let cnum = cdata.cnum; assert!(cnum != LOCAL_CRATE); - // If this crate is a plugin and/or a custom derive crate, then - // we're not even going to link those in so we skip those crates. - if cdata.root.plugin_registrar_fn.is_some() || - cdata.root.macro_derive_registrar.is_some() { + // If this crate is a custom derive crate, then we're not even going to + // link those in so we skip those crates. + if cdata.root.macro_derive_registrar.is_some() { return Arc::new(Vec::new()) } diff --git a/src/librustc_trans/back/symbol_export.rs b/src/librustc_trans/back/symbol_export.rs index 0873c1632f58..7d7665749a73 100644 --- a/src/librustc_trans/back/symbol_export.rs +++ b/src/librustc_trans/back/symbol_export.rs @@ -119,7 +119,7 @@ fn exported_symbols_provider_local<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, let special_runtime_crate = tcx.is_panic_runtime(LOCAL_CRATE) || tcx.is_compiler_builtins(LOCAL_CRATE); - let mut reachable_non_generics: DefIdSet = tcx.reachable_set(LOCAL_CRATE).0 + let reachable_non_generics: DefIdSet = tcx.reachable_set(LOCAL_CRATE).0 .iter() .filter_map(|&node_id| { // We want to ignore some FFI functions that are not exposed from @@ -174,14 +174,6 @@ fn exported_symbols_provider_local<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, }) .collect(); - if let Some(id) = tcx.sess.derive_registrar_fn.get() { - reachable_non_generics.insert(tcx.hir.local_def_id(id)); - } - - if let Some(id) = tcx.sess.plugin_registrar_fn.get() { - reachable_non_generics.insert(tcx.hir.local_def_id(id)); - } - let mut symbols: Vec<_> = reachable_non_generics .iter() .map(|&def_id| { @@ -211,6 +203,16 @@ fn exported_symbols_provider_local<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, }) .collect(); + if let Some(id) = tcx.sess.derive_registrar_fn.get() { + let def_id = tcx.hir.local_def_id(id); + symbols.push((ExportedSymbol::NonGeneric(def_id), SymbolExportLevel::C)); + } + + if let Some(id) = tcx.sess.plugin_registrar_fn.get() { + let def_id = tcx.hir.local_def_id(id); + symbols.push((ExportedSymbol::NonGeneric(def_id), SymbolExportLevel::C)); + } + if let Some(_) = *tcx.sess.entry_fn.borrow() { let symbol_name = "main".to_string(); let exported_symbol = ExportedSymbol::NoDefId(SymbolName::new(&symbol_name)); From f5ab4d4cdd1a8eda860628e97b619da8c10ac7b3 Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Mon, 5 Mar 2018 17:41:11 +0100 Subject: [PATCH 67/68] Don't show crate metadata symbol as exported symbol to downstream crates. --- src/librustc/middle/exported_symbols.rs | 8 +++++++- src/librustc_metadata/encoder.rs | 22 +++++++++++++++++++--- src/librustc_trans/back/symbol_export.rs | 8 +------- src/librustc_trans/base.rs | 4 ++-- 4 files changed, 29 insertions(+), 13 deletions(-) diff --git a/src/librustc/middle/exported_symbols.rs b/src/librustc/middle/exported_symbols.rs index fb971dd2515c..b1418792490f 100644 --- a/src/librustc/middle/exported_symbols.rs +++ b/src/librustc/middle/exported_symbols.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use hir::def_id::DefId; +use hir::def_id::{DefId, LOCAL_CRATE}; use std::cmp; use ty; @@ -87,3 +87,9 @@ impl_stable_hash_for!(enum self::ExportedSymbol { NonGeneric(def_id), NoDefId(symbol_name) }); + +pub fn metadata_symbol_name(tcx: ty::TyCtxt) -> String { + format!("rust_metadata_{}_{}", + tcx.original_crate_name(LOCAL_CRATE), + tcx.crate_disambiguator(LOCAL_CRATE).to_fingerprint().to_hex()) +} diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index 1c54b7aa1333..d19ab8945914 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -20,11 +20,12 @@ use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefIndex, DefId, LOCAL_CRATE use rustc::hir::map::definitions::DefPathTable; use rustc::ich::Fingerprint; use rustc::middle::dependency_format::Linkage; -use rustc::middle::exported_symbols::{ExportedSymbol, SymbolExportLevel}; +use rustc::middle::exported_symbols::{ExportedSymbol, SymbolExportLevel, + metadata_symbol_name}; use rustc::middle::lang_items; use rustc::mir; use rustc::traits::specialization_graph; -use rustc::ty::{self, Ty, TyCtxt, ReprOptions}; +use rustc::ty::{self, Ty, TyCtxt, ReprOptions, SymbolName}; use rustc::ty::codec::{self as ty_codec, TyEncoder}; use rustc::session::config::{self, CrateTypeProcMacro}; @@ -1392,7 +1393,22 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { fn encode_exported_symbols(&mut self, exported_symbols: &[(ExportedSymbol, SymbolExportLevel)]) -> LazySeq<(ExportedSymbol, SymbolExportLevel)> { - self.lazy_seq(exported_symbols.iter().cloned()) + + // The metadata symbol name is special. It should not show up in + // downstream crates. + let metadata_symbol_name = SymbolName::new(&metadata_symbol_name(self.tcx)); + + self.lazy_seq(exported_symbols + .iter() + .filter(|&&(ref exported_symbol, _)| { + match *exported_symbol { + ExportedSymbol::NoDefId(symbol_name) => { + symbol_name != metadata_symbol_name + }, + _ => true, + } + }) + .cloned()) } fn encode_dylib_dependency_formats(&mut self, _: ()) -> LazySeq> { diff --git a/src/librustc_trans/back/symbol_export.rs b/src/librustc_trans/back/symbol_export.rs index 7d7665749a73..739ae768ca29 100644 --- a/src/librustc_trans/back/symbol_export.rs +++ b/src/librustc_trans/back/symbol_export.rs @@ -15,7 +15,7 @@ use monomorphize::Instance; use rustc::hir; use rustc::hir::def_id::CrateNum; use rustc::hir::def_id::{DefId, LOCAL_CRATE}; -use rustc::middle::exported_symbols::{SymbolExportLevel, ExportedSymbol}; +use rustc::middle::exported_symbols::{SymbolExportLevel, ExportedSymbol, metadata_symbol_name}; use rustc::session::config; use rustc::ty::{TyCtxt, SymbolName}; use rustc::ty::maps::Providers; @@ -32,12 +32,6 @@ pub fn threshold(tcx: TyCtxt) -> SymbolExportLevel { crates_export_threshold(&tcx.sess.crate_types.borrow()) } -pub fn metadata_symbol_name(tcx: TyCtxt) -> String { - format!("rust_metadata_{}_{}", - tcx.crate_name(LOCAL_CRATE), - tcx.crate_disambiguator(LOCAL_CRATE).to_fingerprint().to_hex()) -} - fn crate_export_threshold(crate_type: config::CrateType) -> SymbolExportLevel { match crate_type { config::CrateTypeExecutable | diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs index b559cc963257..beb7a091bdcf 100644 --- a/src/librustc_trans/base.rs +++ b/src/librustc_trans/base.rs @@ -30,7 +30,6 @@ use super::ModuleKind; use abi; use back::link; -use back::symbol_export; use back::write::{self, OngoingCrateTranslation, create_target_machine}; use llvm::{ContextRef, ModuleRef, ValueRef, Vector, get_param}; use llvm; @@ -45,6 +44,7 @@ use rustc::ty::maps::Providers; use rustc::dep_graph::{DepNode, DepConstructor}; use rustc::ty::subst::Kind; use rustc::middle::cstore::{self, LinkMeta, LinkagePreference}; +use rustc::middle::exported_symbols; use rustc::util::common::{time, print_time_passes_entry}; use rustc::session::config::{self, NoDebugInfo}; use rustc::session::Session; @@ -654,7 +654,7 @@ fn write_metadata<'a, 'gcx>(tcx: TyCtxt<'a, 'gcx, 'gcx>, let llmeta = C_bytes_in_context(metadata_llcx, &compressed); let llconst = C_struct_in_context(metadata_llcx, &[llmeta], false); - let name = symbol_export::metadata_symbol_name(tcx); + let name = exported_symbols::metadata_symbol_name(tcx); let buf = CString::new(name).unwrap(); let llglobal = unsafe { llvm::LLVMAddGlobal(metadata_llmod, val_ty(llconst).to_ref(), buf.as_ptr()) From a0c626227eeb98f864f67c42845b76f126bc519a Mon Sep 17 00:00:00 2001 From: 1011X <1011XXXXX@gmail.com> Date: Tue, 6 Mar 2018 16:33:38 -0500 Subject: [PATCH 68/68] FusedIterator will be stabilized --- src/libcore/ascii.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcore/ascii.rs b/src/libcore/ascii.rs index f409536d1b0e..2c4bccebceb9 100644 --- a/src/libcore/ascii.rs +++ b/src/libcore/ascii.rs @@ -136,7 +136,7 @@ impl DoubleEndedIterator for EscapeDefault { } #[stable(feature = "rust1", since = "1.0.0")] impl ExactSizeIterator for EscapeDefault {} -#[unstable(feature = "fused", issue = "35602")] +#[stable(feature = "fused", since = "1.26.0")] impl FusedIterator for EscapeDefault {} #[stable(feature = "std_debug", since = "1.16.0")]