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]