Auto merge of #64598 - Centril:rollup-htmf39p, r=Centril
Rollup of 5 pull requests
Successful merges:
- #63630 (Update installed compiler dependencies)
- #64536 (Update Cargo)
- #64554 (Polonius: more `ui` test suite fixes)
- #64566 (A more generic interface for dataflow analysis)
- #64591 (Fix a minor grammar nit, update UI tests)
Failed merges:
r? @ghost
diff --git a/Cargo.lock b/Cargo.lock
index 326f3b1..f52e973 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -270,6 +270,7 @@
"atty",
"bytesize",
"cargo-test-macro",
+ "cargo-test-support",
"clap",
"core-foundation",
"crates-io",
@@ -286,8 +287,9 @@
"git2",
"git2-curl",
"glob",
- "hex",
+ "hex 0.4.0",
"home",
+ "humantime",
"ignore",
"im-rc",
"jobserver",
@@ -328,6 +330,23 @@
version = "0.1.0"
[[package]]
+name = "cargo-test-support"
+version = "0.1.0"
+dependencies = [
+ "cargo",
+ "cargo-test-macro",
+ "filetime",
+ "flate2",
+ "git2",
+ "glob",
+ "lazy_static 1.3.0",
+ "remove_dir_all",
+ "serde_json",
+ "tar",
+ "url 2.1.0",
+]
+
+[[package]]
name = "cargo_metadata"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -698,7 +717,7 @@
checksum = "09de9ee0fc255ace04c7fa0763c9395a945c37c8292bb554f8d48361d1dcf1b4"
dependencies = [
"commoncrypto",
- "hex",
+ "hex 0.3.2",
"openssl",
"winapi 0.3.6",
]
@@ -1261,6 +1280,12 @@
checksum = "805026a5d0141ffc30abb3be3173848ad46a1b1664fe632428479619a3644d77"
[[package]]
+name = "hex"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "023b39be39e3a2da62a94feb433e91e8bcd37676fbc8bea371daf52b7a769a3e"
+
+[[package]]
name = "home"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2062,7 +2087,7 @@
"directories",
"env_logger",
"getrandom",
- "hex",
+ "hex 0.3.2",
"log",
"num-traits",
"rand 0.7.0",
@@ -3257,6 +3282,7 @@
"serde",
"serde_json",
"smallvec",
+ "url 2.1.0",
"winapi 0.3.6",
]
diff --git a/README.md b/README.md
index 4c2e4ee..96d7e93 100644
--- a/README.md
+++ b/README.md
@@ -26,7 +26,7 @@
### Building on *nix
1. Make sure you have installed the dependencies:
- * `g++` 4.7 or later or `clang++` 3.x or later
+ * `g++` 5.1 or later or `clang++` 3.5 or later
* `python` 2.7 (but not 3.x)
* GNU `make` 3.81 or later
* `cmake` 3.4.3 or later
@@ -151,6 +151,17 @@
> python x.py build
```
+### Building rustc with older host toolchains
+It is still possible to build Rust with the older toolchain versions listed below, but only if the
+LLVM_TEMPORARILY_ALLOW_OLD_TOOLCHAIN option is set to true in the config.toml file.
+
+* Clang 3.1
+* Apple Clang 3.1
+* GCC 4.8
+* Visual Studio 2015 (Update 3)
+
+Toolchain versions older than what is listed above cannot be used to build rustc.
+
#### Specifying an ABI
Each specific ABI can also be used from either environment (for example, using
diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs
index 217c887..a54bc05 100644
--- a/src/librustc/traits/select.rs
+++ b/src/librustc/traits/select.rs
@@ -134,7 +134,7 @@
String::new()
};
format!(
- "upstream crates may add new impl of trait `{}`{} \
+ "upstream crates may add a new impl of trait `{}`{} \
in future versions",
trait_desc, self_desc
)
diff --git a/src/librustc_mir/dataflow/generic.rs b/src/librustc_mir/dataflow/generic.rs
new file mode 100644
index 0000000..886044c
--- /dev/null
+++ b/src/librustc_mir/dataflow/generic.rs
@@ -0,0 +1,512 @@
+//! Dataflow analysis with arbitrary transfer functions.
+//!
+//! This module is a work in progress. You should instead use `BitDenotation` in
+//! `librustc_mir/dataflow/mod.rs` and encode your transfer function as a [gen/kill set][gk]. In
+//! doing so, your analysis will run faster and you will be able to generate graphviz diagrams for
+//! debugging with no extra effort. The interface in this module is intended only for dataflow
+//! problems that cannot be expressed using gen/kill sets.
+//!
+//! FIXME(ecstaticmorse): In the long term, the plan is to preserve the existing `BitDenotation`
+//! interface, but make `Engine` and `ResultsCursor` the canonical way to perform and inspect a
+//! dataflow analysis. This requires porting the graphviz debugging logic to this module, deciding
+//! on a way to handle the `before` methods in `BitDenotation` and creating an adapter so that
+//! gen-kill problems can still be evaluated efficiently. See the discussion in [#64566][] for more
+//! information.
+//!
+//! [gk]: https://en.wikipedia.org/wiki/Data-flow_analysis#Bit_vector_problems
+//! [#64566]: https://github.com/rust-lang/rust/pull/64566
+
+use std::cmp::Ordering;
+use std::ops;
+
+use rustc::mir::{self, traversal, BasicBlock, Location};
+use rustc_data_structures::bit_set::BitSet;
+use rustc_data_structures::indexed_vec::{Idx, IndexVec};
+use rustc_data_structures::work_queue::WorkQueue;
+
+use crate::dataflow::BottomValue;
+
+/// A specific kind of dataflow analysis.
+///
+/// To run a dataflow analysis, one must set the initial state of the `START_BLOCK` via
+/// `initialize_start_block` and define a transfer function for each statement or terminator via
+/// the various `effect` methods. The entry set for all other basic blocks is initialized to
+/// `Self::BOTTOM_VALUE`. The dataflow `Engine` then iteratively updates the various entry sets for
+/// each block with the cumulative effects of the transfer functions of all preceding blocks.
+///
+/// You should use an `Engine` to actually run an analysis, and a `ResultsCursor` to inspect the
+/// results of that analysis like so:
+///
+/// ```ignore(cross-crate-imports)
+/// fn do_my_analysis(body: &mir::Body<'tcx>, dead_unwinds: &BitSet<BasicBlock>) {
+/// // `MyAnalysis` implements `Analysis`.
+/// let analysis = MyAnalysis::new();
+///
+/// let results = Engine::new(body, dead_unwinds, analysis).iterate_to_fixpoint();
+/// let mut cursor = ResultsCursor::new(body, results);
+///
+/// for (_, statement_index) in body.block_data[START_BLOCK].statements.iter_enumerated() {
+/// cursor.seek_after(Location { block: START_BLOCK, statement_index });
+/// let state = cursor.get();
+/// println!("{:?}", state);
+/// }
+/// }
+/// ```
+pub trait Analysis<'tcx>: BottomValue {
+ /// The index type used to access the dataflow state.
+ type Idx: Idx;
+
+ /// A name, used for debugging, that describes this dataflow analysis.
+ ///
+ /// The name should be suitable as part of a filename, so avoid whitespace, slashes or periods
+ /// and try to keep it short.
+ const NAME: &'static str;
+
+ /// The size of each bitvector allocated for each block.
+ fn bits_per_block(&self, body: &mir::Body<'tcx>) -> usize;
+
+ /// Mutates the entry set of the `START_BLOCK` to contain the initial state for dataflow
+ /// analysis.
+ fn initialize_start_block(&self, body: &mir::Body<'tcx>, state: &mut BitSet<Self::Idx>);
+
+ /// Updates the current dataflow state with the effect of evaluating a statement.
+ fn apply_statement_effect(
+ &self,
+ state: &mut BitSet<Self::Idx>,
+ statement: &mir::Statement<'tcx>,
+ location: Location,
+ );
+
+ /// Updates the current dataflow state with the effect of evaluating a statement.
+ ///
+ /// Note that the effect of a successful return from a `Call` terminator should **not** be
+ /// acounted for in this function. That should go in `apply_call_return_effect`. For example,
+ /// in the `InitializedPlaces` analyses, the return place is not marked as initialized here.
+ fn apply_terminator_effect(
+ &self,
+ state: &mut BitSet<Self::Idx>,
+ terminator: &mir::Terminator<'tcx>,
+ location: Location,
+ );
+
+ /// Updates the current dataflow state with the effect of a successful return from a `Call`
+ /// terminator.
+ ///
+ /// This is separated from `apply_terminator_effect` to properly track state across
+ /// unwind edges for `Call`s.
+ fn apply_call_return_effect(
+ &self,
+ state: &mut BitSet<Self::Idx>,
+ block: BasicBlock,
+ func: &mir::Operand<'tcx>,
+ args: &[mir::Operand<'tcx>],
+ return_place: &mir::Place<'tcx>,
+ );
+
+ /// Applies the cumulative effect of an entire basic block to the dataflow state (except for
+ /// `call_return_effect`, which is handled in the `Engine`).
+ ///
+ /// The default implementation calls `statement_effect` for every statement in the block before
+ /// finally calling `terminator_effect`. However, some dataflow analyses are able to coalesce
+ /// transfer functions for an entire block and apply them at once. Such analyses should
+ /// override `block_effect`.
+ fn apply_whole_block_effect(
+ &self,
+ state: &mut BitSet<Self::Idx>,
+ block: BasicBlock,
+ block_data: &mir::BasicBlockData<'tcx>,
+ ) {
+ for (statement_index, stmt) in block_data.statements.iter().enumerate() {
+ let location = Location { block, statement_index };
+ self.apply_statement_effect(state, stmt, location);
+ }
+
+ let location = Location { block, statement_index: block_data.statements.len() };
+ self.apply_terminator_effect(state, block_data.terminator(), location);
+ }
+
+ /// Applies the cumulative effect of a sequence of statements (and possibly a terminator)
+ /// within a single basic block.
+ ///
+ /// When called with `0..block_data.statements.len() + 1` as the statement range, this function
+ /// is equivalent to `apply_whole_block_effect`.
+ fn apply_partial_block_effect(
+ &self,
+ state: &mut BitSet<Self::Idx>,
+ block: BasicBlock,
+ block_data: &mir::BasicBlockData<'tcx>,
+ mut range: ops::Range<usize>,
+ ) {
+ if range.is_empty() {
+ return;
+ }
+
+ // The final location might be a terminator, so iterate through all statements until the
+ // final one, then check to see whether the final one is a statement or terminator.
+ //
+ // This can't cause the range to wrap-around since we check that the range contains at
+ // least one element above.
+ range.end -= 1;
+ let final_location = Location { block, statement_index: range.end };
+
+ for statement_index in range {
+ let location = Location { block, statement_index };
+ let stmt = &block_data.statements[statement_index];
+ self.apply_statement_effect(state, stmt, location);
+ }
+
+ if final_location.statement_index == block_data.statements.len() {
+ let terminator = block_data.terminator();
+ self.apply_terminator_effect(state, terminator, final_location);
+ } else {
+ let stmt = &block_data.statements[final_location.statement_index];
+ self.apply_statement_effect(state, stmt, final_location);
+ }
+ }
+}
+
+#[derive(Clone, Copy, Debug)]
+enum CursorPosition {
+ AtBlockStart(BasicBlock),
+ After(Location),
+}
+
+impl CursorPosition {
+ fn block(&self) -> BasicBlock {
+ match *self {
+ Self::AtBlockStart(block) => block,
+ Self::After(Location { block, .. }) => block,
+ }
+ }
+}
+
+/// Inspect the results of dataflow analysis.
+///
+/// This cursor has linear performance when visiting statements in a block in order. Visiting
+/// statements within a block in reverse order is `O(n^2)`, where `n` is the number of statements
+/// in that block.
+pub struct ResultsCursor<'mir, 'tcx, A>
+where
+ A: Analysis<'tcx>,
+{
+ body: &'mir mir::Body<'tcx>,
+ results: Results<'tcx, A>,
+ state: BitSet<A::Idx>,
+
+ pos: CursorPosition,
+
+ /// Whether the effects of `apply_call_return_effect` are currently stored in `state`.
+ ///
+ /// This flag ensures that multiple calls to `seek_after_assume_call_returns` with the same
+ /// target only result in one invocation of `apply_call_return_effect`.
+ is_call_return_effect_applied: bool,
+}
+
+impl<'mir, 'tcx, A> ResultsCursor<'mir, 'tcx, A>
+where
+ A: Analysis<'tcx>,
+{
+ /// Returns a new cursor for `results` that points to the start of the `START_BLOCK`.
+ pub fn new(body: &'mir mir::Body<'tcx>, results: Results<'tcx, A>) -> Self {
+ ResultsCursor {
+ body,
+ pos: CursorPosition::AtBlockStart(mir::START_BLOCK),
+ is_call_return_effect_applied: false,
+ state: results.entry_sets[mir::START_BLOCK].clone(),
+ results,
+ }
+ }
+
+ /// Resets the cursor to the start of the given `block`.
+ pub fn seek_to_block_start(&mut self, block: BasicBlock) {
+ self.state.overwrite(&self.results.entry_sets[block]);
+ self.pos = CursorPosition::AtBlockStart(block);
+ self.is_call_return_effect_applied = false;
+ }
+
+ /// Updates the cursor to hold the dataflow state immediately before `target`.
+ pub fn seek_before(&mut self, target: Location) {
+ assert!(target <= self.body.terminator_loc(target.block));
+
+ if target.statement_index == 0 {
+ self.seek_to_block_start(target.block);
+ } else {
+ self._seek_after(Location {
+ block: target.block,
+ statement_index: target.statement_index - 1,
+ });
+ }
+ }
+
+ /// Updates the cursor to hold the dataflow state at `target`.
+ ///
+ /// If `target` is a `Call` terminator, `apply_call_return_effect` will not be called. See
+ /// `seek_after_assume_call_returns` if you wish to observe the dataflow state upon a
+ /// successful return.
+ pub fn seek_after(&mut self, target: Location) {
+ assert!(target <= self.body.terminator_loc(target.block));
+
+ // This check ensures the correctness of a call to `seek_after_assume_call_returns`
+ // followed by one to `seek_after` with the same target.
+ if self.is_call_return_effect_applied {
+ self.seek_to_block_start(target.block);
+ }
+
+ self._seek_after(target);
+ }
+
+ /// Equivalent to `seek_after`, but also calls `apply_call_return_effect` if `target` is a
+ /// `Call` terminator whose callee is convergent.
+ pub fn seek_after_assume_call_returns(&mut self, target: Location) {
+ assert!(target <= self.body.terminator_loc(target.block));
+
+ self._seek_after(target);
+
+ if target != self.body.terminator_loc(target.block) {
+ return;
+ }
+
+ let term = self.body.basic_blocks()[target.block].terminator();
+ if let mir::TerminatorKind::Call {
+ destination: Some((return_place, _)),
+ func,
+ args,
+ ..
+ } = &term.kind {
+ if !self.is_call_return_effect_applied {
+ self.is_call_return_effect_applied = true;
+ self.results.analysis.apply_call_return_effect(
+ &mut self.state,
+ target.block,
+ func,
+ args,
+ return_place,
+ );
+ }
+ }
+ }
+
+ fn _seek_after(&mut self, target: Location) {
+ let Location { block: target_block, statement_index: target_index } = target;
+
+ if self.pos.block() != target_block {
+ self.seek_to_block_start(target_block);
+ }
+
+ // If we're in the same block but after the target statement, we need to reset to the start
+ // of the block.
+ if let CursorPosition::After(Location { statement_index: curr_index, .. }) = self.pos {
+ match curr_index.cmp(&target_index) {
+ Ordering::Equal => return,
+ Ordering::Less => {},
+ Ordering::Greater => self.seek_to_block_start(target_block),
+ }
+ }
+
+ // The cursor is now in the same block as the target location pointing at an earlier
+ // statement.
+ debug_assert_eq!(self.pos.block(), target_block);
+ if let CursorPosition::After(Location { statement_index, .. }) = self.pos {
+ debug_assert!(statement_index < target_index);
+ }
+
+ let first_unapplied_statement = match self.pos {
+ CursorPosition::AtBlockStart(_) => 0,
+ CursorPosition::After(Location { statement_index, .. }) => statement_index + 1,
+ };
+
+ let block_data = &self.body.basic_blocks()[target_block];
+ self.results.analysis.apply_partial_block_effect(
+ &mut self.state,
+ target_block,
+ block_data,
+ first_unapplied_statement..target_index + 1,
+ );
+
+ self.pos = CursorPosition::After(target);
+ self.is_call_return_effect_applied = false;
+ }
+
+ /// Gets the dataflow state at the current location.
+ pub fn get(&self) -> &BitSet<A::Idx> {
+ &self.state
+ }
+}
+
+/// A completed dataflow analysis.
+pub struct Results<'tcx, A>
+where
+ A: Analysis<'tcx>,
+{
+ analysis: A,
+ entry_sets: IndexVec<BasicBlock, BitSet<A::Idx>>,
+}
+
+/// All information required to iterate a dataflow analysis to fixpoint.
+pub struct Engine<'a, 'tcx, A>
+where
+ A: Analysis<'tcx>,
+{
+ analysis: A,
+ bits_per_block: usize,
+ body: &'a mir::Body<'tcx>,
+ dead_unwinds: &'a BitSet<BasicBlock>,
+ entry_sets: IndexVec<BasicBlock, BitSet<A::Idx>>,
+}
+
+impl<A> Engine<'a, 'tcx, A>
+where
+ A: Analysis<'tcx>,
+{
+ pub fn new(
+ body: &'a mir::Body<'tcx>,
+ dead_unwinds: &'a BitSet<BasicBlock>,
+ analysis: A,
+ ) -> Self {
+ let bits_per_block = analysis.bits_per_block(body);
+
+ let bottom_value_set = if A::BOTTOM_VALUE == true {
+ BitSet::new_filled(bits_per_block)
+ } else {
+ BitSet::new_empty(bits_per_block)
+ };
+
+ let mut entry_sets = IndexVec::from_elem(bottom_value_set, body.basic_blocks());
+ analysis.initialize_start_block(body, &mut entry_sets[mir::START_BLOCK]);
+
+ Engine {
+ analysis,
+ bits_per_block,
+ body,
+ dead_unwinds,
+ entry_sets,
+ }
+ }
+
+ pub fn iterate_to_fixpoint(mut self) -> Results<'tcx, A> {
+ let mut temp_state = BitSet::new_empty(self.bits_per_block);
+
+ let mut dirty_queue: WorkQueue<BasicBlock> =
+ WorkQueue::with_none(self.body.basic_blocks().len());
+
+ for (bb, _) in traversal::reverse_postorder(self.body) {
+ dirty_queue.insert(bb);
+ }
+
+ // Add blocks that are not reachable from START_BLOCK to the work queue. These blocks will
+ // be processed after the ones added above.
+ for bb in self.body.basic_blocks().indices() {
+ dirty_queue.insert(bb);
+ }
+
+ while let Some(bb) = dirty_queue.pop() {
+ let bb_data = &self.body[bb];
+ let on_entry = &self.entry_sets[bb];
+
+ temp_state.overwrite(on_entry);
+ self.analysis.apply_whole_block_effect(&mut temp_state, bb, bb_data);
+
+ self.propagate_bits_into_graph_successors_of(
+ &mut temp_state,
+ (bb, bb_data),
+ &mut dirty_queue,
+ );
+ }
+
+ Results {
+ analysis: self.analysis,
+ entry_sets: self.entry_sets,
+ }
+ }
+
+ fn propagate_bits_into_graph_successors_of(
+ &mut self,
+ in_out: &mut BitSet<A::Idx>,
+ (bb, bb_data): (BasicBlock, &'a mir::BasicBlockData<'tcx>),
+ dirty_list: &mut WorkQueue<BasicBlock>,
+ ) {
+ match bb_data.terminator().kind {
+ mir::TerminatorKind::Return
+ | mir::TerminatorKind::Resume
+ | mir::TerminatorKind::Abort
+ | mir::TerminatorKind::GeneratorDrop
+ | mir::TerminatorKind::Unreachable => {}
+
+ mir::TerminatorKind::Goto { target }
+ | mir::TerminatorKind::Assert { target, cleanup: None, .. }
+ | mir::TerminatorKind::Yield { resume: target, drop: None, .. }
+ | mir::TerminatorKind::Drop { target, location: _, unwind: None }
+ | mir::TerminatorKind::DropAndReplace { target, value: _, location: _, unwind: None } =>
+ {
+ self.propagate_bits_into_entry_set_for(in_out, target, dirty_list);
+ }
+
+ mir::TerminatorKind::Yield { resume: target, drop: Some(drop), .. } => {
+ self.propagate_bits_into_entry_set_for(in_out, target, dirty_list);
+ self.propagate_bits_into_entry_set_for(in_out, drop, dirty_list);
+ }
+
+ mir::TerminatorKind::Assert { target, cleanup: Some(unwind), .. }
+ | mir::TerminatorKind::Drop { target, location: _, unwind: Some(unwind) }
+ | mir::TerminatorKind::DropAndReplace {
+ target,
+ value: _,
+ location: _,
+ unwind: Some(unwind),
+ } => {
+ self.propagate_bits_into_entry_set_for(in_out, target, dirty_list);
+ if !self.dead_unwinds.contains(bb) {
+ self.propagate_bits_into_entry_set_for(in_out, unwind, dirty_list);
+ }
+ }
+
+ mir::TerminatorKind::SwitchInt { ref targets, .. } => {
+ for target in targets {
+ self.propagate_bits_into_entry_set_for(in_out, *target, dirty_list);
+ }
+ }
+
+ mir::TerminatorKind::Call { cleanup, ref destination, ref func, ref args, .. } => {
+ if let Some(unwind) = cleanup {
+ if !self.dead_unwinds.contains(bb) {
+ self.propagate_bits_into_entry_set_for(in_out, unwind, dirty_list);
+ }
+ }
+
+ if let Some((ref dest_place, dest_bb)) = *destination {
+ // N.B.: This must be done *last*, after all other
+ // propagation, as documented in comment above.
+ self.analysis.apply_call_return_effect(in_out, bb, func, args, dest_place);
+ self.propagate_bits_into_entry_set_for(in_out, dest_bb, dirty_list);
+ }
+ }
+
+ mir::TerminatorKind::FalseEdges { real_target, imaginary_target } => {
+ self.propagate_bits_into_entry_set_for(in_out, real_target, dirty_list);
+ self.propagate_bits_into_entry_set_for(in_out, imaginary_target, dirty_list);
+ }
+
+ mir::TerminatorKind::FalseUnwind { real_target, unwind } => {
+ self.propagate_bits_into_entry_set_for(in_out, real_target, dirty_list);
+ if let Some(unwind) = unwind {
+ if !self.dead_unwinds.contains(bb) {
+ self.propagate_bits_into_entry_set_for(in_out, unwind, dirty_list);
+ }
+ }
+ }
+ }
+ }
+
+ fn propagate_bits_into_entry_set_for(
+ &mut self,
+ in_out: &BitSet<A::Idx>,
+ bb: BasicBlock,
+ dirty_queue: &mut WorkQueue<BasicBlock>,
+ ) {
+ let entry_set = &mut self.entry_sets[bb];
+ let set_changed = self.analysis.join(entry_set, &in_out);
+ if set_changed {
+ dirty_queue.insert(bb);
+ }
+ }
+}
diff --git a/src/librustc_mir/dataflow/mod.rs b/src/librustc_mir/dataflow/mod.rs
index 319abbb..5ab4e25 100644
--- a/src/librustc_mir/dataflow/mod.rs
+++ b/src/librustc_mir/dataflow/mod.rs
@@ -30,6 +30,7 @@
mod at_location;
pub mod drop_flag_effects;
+pub mod generic;
mod graphviz;
mod impls;
pub mod move_paths;
diff --git a/src/librustc_mir/lib.rs b/src/librustc_mir/lib.rs
index 6a49ed6..9a03719 100644
--- a/src/librustc_mir/lib.rs
+++ b/src/librustc_mir/lib.rs
@@ -23,6 +23,7 @@
#![feature(try_blocks)]
#![feature(mem_take)]
#![feature(associated_type_bounds)]
+#![feature(range_is_empty)]
#![recursion_limit="256"]
diff --git a/src/test/ui/async-await/async-borrowck-escaping-closure-error.polonius.stderr b/src/test/ui/async-await/async-borrowck-escaping-closure-error.polonius.stderr
new file mode 100644
index 0000000..5f20367
--- /dev/null
+++ b/src/test/ui/async-await/async-borrowck-escaping-closure-error.polonius.stderr
@@ -0,0 +1,16 @@
+error[E0597]: `x` does not live long enough
+ --> $DIR/async-borrowck-escaping-closure-error.rs:5:24
+ |
+LL | Box::new((async || x)())
+ | -------------------^----
+ | | | |
+ | | | borrowed value does not live long enough
+ | | value captured here
+ | borrow later used here
+LL |
+LL | }
+ | - `x` dropped here while still borrowed
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/borrowck/return-local-binding-from-desugaring.polonius.stderr b/src/test/ui/borrowck/return-local-binding-from-desugaring.polonius.stderr
new file mode 100644
index 0000000..c818379
--- /dev/null
+++ b/src/test/ui/borrowck/return-local-binding-from-desugaring.polonius.stderr
@@ -0,0 +1,16 @@
+error[E0716]: temporary value dropped while borrowed
+ --> $DIR/return-local-binding-from-desugaring.rs:26:18
+ |
+LL | for ref x in xs {
+ | ^^ creates a temporary which is freed while still in use
+...
+LL | }
+ | - temporary value is freed at the end of this statement
+LL | result
+ | ------ borrow later used here
+ |
+ = note: consider using a `let` binding to create a longer lived value
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0716`.
diff --git a/src/test/ui/codemap_tests/overlapping_inherent_impls.stderr b/src/test/ui/codemap_tests/overlapping_inherent_impls.stderr
index 70c1093..8fe24ba 100644
--- a/src/test/ui/codemap_tests/overlapping_inherent_impls.stderr
+++ b/src/test/ui/codemap_tests/overlapping_inherent_impls.stderr
@@ -25,7 +25,7 @@
LL | fn baz(&self) {}
| ---------------- other definition for `baz`
|
- = note: upstream crates may add new impl of trait `std::marker::Copy` for type `std::vec::Vec<_>` in future versions
+ = note: upstream crates may add a new impl of trait `std::marker::Copy` for type `std::vec::Vec<_>` in future versions
error: aborting due to 3 previous errors
diff --git a/src/test/ui/coherence/coherence-overlap-upstream-inherent.old.stderr b/src/test/ui/coherence/coherence-overlap-upstream-inherent.old.stderr
index 928b65e..3a3e1a4 100644
--- a/src/test/ui/coherence/coherence-overlap-upstream-inherent.old.stderr
+++ b/src/test/ui/coherence/coherence-overlap-upstream-inherent.old.stderr
@@ -7,7 +7,7 @@
LL | impl A<i16> { fn dummy(&self) { } }
| ------------------- other definition for `dummy`
|
- = note: upstream crates may add new impl of trait `coherence_lib::Remote` for type `i16` in future versions
+ = note: upstream crates may add a new impl of trait `coherence_lib::Remote` for type `i16` in future versions
error: aborting due to previous error
diff --git a/src/test/ui/coherence/coherence-overlap-upstream-inherent.re.stderr b/src/test/ui/coherence/coherence-overlap-upstream-inherent.re.stderr
index 928b65e..3a3e1a4 100644
--- a/src/test/ui/coherence/coherence-overlap-upstream-inherent.re.stderr
+++ b/src/test/ui/coherence/coherence-overlap-upstream-inherent.re.stderr
@@ -7,7 +7,7 @@
LL | impl A<i16> { fn dummy(&self) { } }
| ------------------- other definition for `dummy`
|
- = note: upstream crates may add new impl of trait `coherence_lib::Remote` for type `i16` in future versions
+ = note: upstream crates may add a new impl of trait `coherence_lib::Remote` for type `i16` in future versions
error: aborting due to previous error
diff --git a/src/test/ui/coherence/coherence-overlap-upstream.old.stderr b/src/test/ui/coherence/coherence-overlap-upstream.old.stderr
index 6c3484c..bd6f59f 100644
--- a/src/test/ui/coherence/coherence-overlap-upstream.old.stderr
+++ b/src/test/ui/coherence/coherence-overlap-upstream.old.stderr
@@ -6,7 +6,7 @@
LL | impl Foo for i16 {}
| ^^^^^^^^^^^^^^^^ conflicting implementation for `i16`
|
- = note: upstream crates may add new impl of trait `coherence_lib::Remote` for type `i16` in future versions
+ = note: upstream crates may add a new impl of trait `coherence_lib::Remote` for type `i16` in future versions
error: aborting due to previous error
diff --git a/src/test/ui/coherence/coherence-overlap-upstream.re.stderr b/src/test/ui/coherence/coherence-overlap-upstream.re.stderr
index 6c3484c..bd6f59f 100644
--- a/src/test/ui/coherence/coherence-overlap-upstream.re.stderr
+++ b/src/test/ui/coherence/coherence-overlap-upstream.re.stderr
@@ -6,7 +6,7 @@
LL | impl Foo for i16 {}
| ^^^^^^^^^^^^^^^^ conflicting implementation for `i16`
|
- = note: upstream crates may add new impl of trait `coherence_lib::Remote` for type `i16` in future versions
+ = note: upstream crates may add a new impl of trait `coherence_lib::Remote` for type `i16` in future versions
error: aborting due to previous error
diff --git a/src/test/ui/coherence/coherence-projection-conflict-orphan.old.stderr b/src/test/ui/coherence/coherence-projection-conflict-orphan.old.stderr
index cde9360..728eae5 100644
--- a/src/test/ui/coherence/coherence-projection-conflict-orphan.old.stderr
+++ b/src/test/ui/coherence/coherence-projection-conflict-orphan.old.stderr
@@ -7,7 +7,7 @@
LL | impl<A:Iterator> Foo<A::Item> for A { }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `i32`
|
- = note: upstream crates may add new impl of trait `std::iter::Iterator` for type `i32` in future versions
+ = note: upstream crates may add a new impl of trait `std::iter::Iterator` for type `i32` in future versions
error: aborting due to previous error
diff --git a/src/test/ui/coherence/coherence-projection-conflict-orphan.re.stderr b/src/test/ui/coherence/coherence-projection-conflict-orphan.re.stderr
index cde9360..728eae5 100644
--- a/src/test/ui/coherence/coherence-projection-conflict-orphan.re.stderr
+++ b/src/test/ui/coherence/coherence-projection-conflict-orphan.re.stderr
@@ -7,7 +7,7 @@
LL | impl<A:Iterator> Foo<A::Item> for A { }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `i32`
|
- = note: upstream crates may add new impl of trait `std::iter::Iterator` for type `i32` in future versions
+ = note: upstream crates may add a new impl of trait `std::iter::Iterator` for type `i32` in future versions
error: aborting due to previous error
diff --git a/src/test/ui/coherence/coherence_copy_like_err_fundamental_struct_tuple.old.stderr b/src/test/ui/coherence/coherence_copy_like_err_fundamental_struct_tuple.old.stderr
index 12c7a1f..4d9f55c 100644
--- a/src/test/ui/coherence/coherence_copy_like_err_fundamental_struct_tuple.old.stderr
+++ b/src/test/ui/coherence/coherence_copy_like_err_fundamental_struct_tuple.old.stderr
@@ -7,7 +7,7 @@
LL | impl MyTrait for lib::MyFundamentalStruct<(MyType,)> { }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `lib::MyFundamentalStruct<(MyType,)>`
|
- = note: upstream crates may add new impl of trait `lib::MyCopy` for type `lib::MyFundamentalStruct<(MyType,)>` in future versions
+ = note: upstream crates may add a new impl of trait `lib::MyCopy` for type `lib::MyFundamentalStruct<(MyType,)>` in future versions
error: aborting due to previous error
diff --git a/src/test/ui/coherence/coherence_copy_like_err_fundamental_struct_tuple.re.stderr b/src/test/ui/coherence/coherence_copy_like_err_fundamental_struct_tuple.re.stderr
index 12c7a1f..4d9f55c 100644
--- a/src/test/ui/coherence/coherence_copy_like_err_fundamental_struct_tuple.re.stderr
+++ b/src/test/ui/coherence/coherence_copy_like_err_fundamental_struct_tuple.re.stderr
@@ -7,7 +7,7 @@
LL | impl MyTrait for lib::MyFundamentalStruct<(MyType,)> { }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `lib::MyFundamentalStruct<(MyType,)>`
|
- = note: upstream crates may add new impl of trait `lib::MyCopy` for type `lib::MyFundamentalStruct<(MyType,)>` in future versions
+ = note: upstream crates may add a new impl of trait `lib::MyCopy` for type `lib::MyFundamentalStruct<(MyType,)>` in future versions
error: aborting due to previous error
diff --git a/src/test/ui/coherence/coherence_copy_like_err_struct.old.stderr b/src/test/ui/coherence/coherence_copy_like_err_struct.old.stderr
index 1b6c62e..f0bcf65 100644
--- a/src/test/ui/coherence/coherence_copy_like_err_struct.old.stderr
+++ b/src/test/ui/coherence/coherence_copy_like_err_struct.old.stderr
@@ -7,7 +7,7 @@
LL | impl MyTrait for lib::MyStruct<MyType> { }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `lib::MyStruct<MyType>`
|
- = note: upstream crates may add new impl of trait `lib::MyCopy` for type `lib::MyStruct<MyType>` in future versions
+ = note: upstream crates may add a new impl of trait `lib::MyCopy` for type `lib::MyStruct<MyType>` in future versions
error: aborting due to previous error
diff --git a/src/test/ui/coherence/coherence_copy_like_err_struct.re.stderr b/src/test/ui/coherence/coherence_copy_like_err_struct.re.stderr
index 1b6c62e..f0bcf65 100644
--- a/src/test/ui/coherence/coherence_copy_like_err_struct.re.stderr
+++ b/src/test/ui/coherence/coherence_copy_like_err_struct.re.stderr
@@ -7,7 +7,7 @@
LL | impl MyTrait for lib::MyStruct<MyType> { }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `lib::MyStruct<MyType>`
|
- = note: upstream crates may add new impl of trait `lib::MyCopy` for type `lib::MyStruct<MyType>` in future versions
+ = note: upstream crates may add a new impl of trait `lib::MyCopy` for type `lib::MyStruct<MyType>` in future versions
error: aborting due to previous error
diff --git a/src/test/ui/coherence/coherence_copy_like_err_tuple.old.stderr b/src/test/ui/coherence/coherence_copy_like_err_tuple.old.stderr
index 11bd788..a40153a 100644
--- a/src/test/ui/coherence/coherence_copy_like_err_tuple.old.stderr
+++ b/src/test/ui/coherence/coherence_copy_like_err_tuple.old.stderr
@@ -7,7 +7,7 @@
LL | impl MyTrait for (MyType,) { }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(MyType,)`
|
- = note: upstream crates may add new impl of trait `lib::MyCopy` for type `(MyType,)` in future versions
+ = note: upstream crates may add a new impl of trait `lib::MyCopy` for type `(MyType,)` in future versions
error: aborting due to previous error
diff --git a/src/test/ui/coherence/coherence_copy_like_err_tuple.re.stderr b/src/test/ui/coherence/coherence_copy_like_err_tuple.re.stderr
index 11bd788..a40153a 100644
--- a/src/test/ui/coherence/coherence_copy_like_err_tuple.re.stderr
+++ b/src/test/ui/coherence/coherence_copy_like_err_tuple.re.stderr
@@ -7,7 +7,7 @@
LL | impl MyTrait for (MyType,) { }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(MyType,)`
|
- = note: upstream crates may add new impl of trait `lib::MyCopy` for type `(MyType,)` in future versions
+ = note: upstream crates may add a new impl of trait `lib::MyCopy` for type `(MyType,)` in future versions
error: aborting due to previous error
diff --git a/src/test/ui/dropck/dropck_trait_cycle_checked.polonius.stderr b/src/test/ui/dropck/dropck_trait_cycle_checked.polonius.stderr
index dbcb0fc..5e93a02 100644
--- a/src/test/ui/dropck/dropck_trait_cycle_checked.polonius.stderr
+++ b/src/test/ui/dropck/dropck_trait_cycle_checked.polonius.stderr
@@ -8,7 +8,9 @@
| -
| |
| `o2` dropped here while still borrowed
- | borrow might be used here, when `o2` is dropped and runs the destructor for type `std::boxed::Box<dyn Obj<'_>>`
+ | borrow might be used here, when `o1` is dropped and runs the destructor for type `std::boxed::Box<dyn Obj<'_>>`
+ |
+ = note: values in a scope are dropped in the opposite order they are defined
error[E0597]: `o3` does not live long enough
--> $DIR/dropck_trait_cycle_checked.rs:112:13
@@ -20,7 +22,9 @@
| -
| |
| `o3` dropped here while still borrowed
- | borrow might be used here, when `o3` is dropped and runs the destructor for type `std::boxed::Box<dyn Obj<'_>>`
+ | borrow might be used here, when `o1` is dropped and runs the destructor for type `std::boxed::Box<dyn Obj<'_>>`
+ |
+ = note: values in a scope are dropped in the opposite order they are defined
error[E0597]: `o2` does not live long enough
--> $DIR/dropck_trait_cycle_checked.rs:113:13
@@ -38,7 +42,7 @@
--> $DIR/dropck_trait_cycle_checked.rs:114:13
|
LL | let (o1, o2, o3): (Box<dyn Obj>, Box<dyn Obj>, Box<dyn Obj>) = (O::new(), O::new(), O::new());
- | -------- cast requires that `o3` is borrowed for `'static`
+ | -------- cast requires that `o3` is borrowed for `'static`
...
LL | o2.set1(&o3);
| ^^^ borrowed value does not live long enough
@@ -62,7 +66,7 @@
--> $DIR/dropck_trait_cycle_checked.rs:116:13
|
LL | let (o1, o2, o3): (Box<dyn Obj>, Box<dyn Obj>, Box<dyn Obj>) = (O::new(), O::new(), O::new());
- | -------- cast requires that `o2` is borrowed for `'static`
+ | -------- cast requires that `o2` is borrowed for `'static`
...
LL | o3.set1(&o2);
| ^^^ borrowed value does not live long enough
diff --git a/src/test/ui/issues/issue-48728.stderr b/src/test/ui/issues/issue-48728.stderr
index 99a9bf9..84c10d8 100644
--- a/src/test/ui/issues/issue-48728.stderr
+++ b/src/test/ui/issues/issue-48728.stderr
@@ -7,7 +7,7 @@
LL | impl<T: Clone + ?Sized> Clone for Node<[T]> {
| ------------------------------------------- first implementation here
|
- = note: upstream crates may add new impl of trait `std::clone::Clone` for type `[_]` in future versions
+ = note: upstream crates may add a new impl of trait `std::clone::Clone` for type `[_]` in future versions
error: aborting due to previous error
diff --git a/src/test/ui/json-multiple.polonius.stderr b/src/test/ui/json-multiple.polonius.stderr
new file mode 100644
index 0000000..0e4d442
--- /dev/null
+++ b/src/test/ui/json-multiple.polonius.stderr
@@ -0,0 +1 @@
+{"artifact":"$TEST_BUILD_DIR/json-multiple.polonius/libjson_multiple.rlib","emit":"link"}
diff --git a/src/test/ui/json-options.polonius.stderr b/src/test/ui/json-options.polonius.stderr
new file mode 100644
index 0000000..e21f6f8
--- /dev/null
+++ b/src/test/ui/json-options.polonius.stderr
@@ -0,0 +1 @@
+{"artifact":"$TEST_BUILD_DIR/json-options.polonius/libjson_options.rlib","emit":"link"}
diff --git a/src/test/ui/specialization/issue-52050.stderr b/src/test/ui/specialization/issue-52050.stderr
index dcb34f3..36f96b0 100644
--- a/src/test/ui/specialization/issue-52050.stderr
+++ b/src/test/ui/specialization/issue-52050.stderr
@@ -11,7 +11,7 @@
LL | impl IntoPyDictPointer for ()
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `()`
|
- = note: upstream crates may add new impl of trait `std::iter::Iterator` for type `()` in future versions
+ = note: upstream crates may add a new impl of trait `std::iter::Iterator` for type `()` in future versions
error: aborting due to previous error
diff --git a/src/tools/cargo b/src/tools/cargo
index 9655d70..3596cb8 160000
--- a/src/tools/cargo
+++ b/src/tools/cargo
@@ -1 +1 @@
-Subproject commit 9655d70af8a6dddac238e3afa2fec75088c9226f
+Subproject commit 3596cb86b2e87dd9b9c1bb90d4a9d73ec2c1512f
diff --git a/src/tools/rustc-workspace-hack/Cargo.toml b/src/tools/rustc-workspace-hack/Cargo.toml
index 930279c..980c975 100644
--- a/src/tools/rustc-workspace-hack/Cargo.toml
+++ b/src/tools/rustc-workspace-hack/Cargo.toml
@@ -62,6 +62,7 @@
serde = { version = "1.0.82", features = ['derive'] }
serde_json = { version = "1.0.31", features = ["raw_value"] }
smallvec = { version = "0.6", features = ['union', 'may_dangle'] }
+url = { version = "2.0", features = ['serde'] }
[target.'cfg(not(windows))'.dependencies]