1
Fork 0

Use FxIndexSet to avoid sorting fake borrows

This fixes #96449, but I haven't yet been able to
make the reproducer work using `#[cfg]` attributes,
so we can't use the 'revision' infra to write a test

The previous implementation relied on sorting by `PlaceRef`.
This requires sorting by a `DefId`, which uses untracked state
(see #93315)
This commit is contained in:
Aaron Hill 2022-05-09 22:27:47 -04:00
parent cb12198715
commit aa0cc9c1e2
No known key found for this signature in database
GPG key ID: B4087E510E98B164
2 changed files with 13 additions and 15 deletions

View file

@ -11,7 +11,7 @@ use crate::build::ForGuard::{self, OutsideGuard, RefWithinGuard};
use crate::build::{BlockAnd, BlockAndExtension, Builder}; use crate::build::{BlockAnd, BlockAndExtension, Builder};
use crate::build::{GuardFrame, GuardFrameLocal, LocalsForNode}; use crate::build::{GuardFrame, GuardFrameLocal, LocalsForNode};
use rustc_data_structures::{ use rustc_data_structures::{
fx::{FxHashSet, FxIndexMap}, fx::{FxIndexMap, FxIndexSet},
stack::ensure_sufficient_stack, stack::ensure_sufficient_stack,
}; };
use rustc_hir::HirId; use rustc_hir::HirId;
@ -264,7 +264,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
// The set of places that we are creating fake borrows of. If there are // The set of places that we are creating fake borrows of. If there are
// no match guards then we don't need any fake borrows, so don't track // no match guards then we don't need any fake borrows, so don't track
// them. // them.
let mut fake_borrows = match_has_guard.then(FxHashSet::default); let mut fake_borrows = match_has_guard.then(FxIndexSet::default);
let mut otherwise = None; let mut otherwise = None;
@ -1053,7 +1053,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
start_block: BasicBlock, start_block: BasicBlock,
otherwise_block: &mut Option<BasicBlock>, otherwise_block: &mut Option<BasicBlock>,
candidates: &mut [&mut Candidate<'pat, 'tcx>], candidates: &mut [&mut Candidate<'pat, 'tcx>],
fake_borrows: &mut Option<FxHashSet<Place<'tcx>>>, fake_borrows: &mut Option<FxIndexSet<Place<'tcx>>>,
) { ) {
debug!( debug!(
"matched_candidate(span={:?}, candidates={:?}, start_block={:?}, otherwise_block={:?})", "matched_candidate(span={:?}, candidates={:?}, start_block={:?}, otherwise_block={:?})",
@ -1105,7 +1105,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
start_block: BasicBlock, start_block: BasicBlock,
otherwise_block: &mut Option<BasicBlock>, otherwise_block: &mut Option<BasicBlock>,
candidates: &mut [&mut Candidate<'_, 'tcx>], candidates: &mut [&mut Candidate<'_, 'tcx>],
fake_borrows: &mut Option<FxHashSet<Place<'tcx>>>, fake_borrows: &mut Option<FxIndexSet<Place<'tcx>>>,
) { ) {
// The candidates are sorted by priority. Check to see whether the // The candidates are sorted by priority. Check to see whether the
// higher priority candidates (and hence at the front of the slice) // higher priority candidates (and hence at the front of the slice)
@ -1184,7 +1184,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
&mut self, &mut self,
matched_candidates: &mut [&mut Candidate<'_, 'tcx>], matched_candidates: &mut [&mut Candidate<'_, 'tcx>],
start_block: BasicBlock, start_block: BasicBlock,
fake_borrows: &mut Option<FxHashSet<Place<'tcx>>>, fake_borrows: &mut Option<FxIndexSet<Place<'tcx>>>,
) -> Option<BasicBlock> { ) -> Option<BasicBlock> {
debug_assert!( debug_assert!(
!matched_candidates.is_empty(), !matched_candidates.is_empty(),
@ -1322,7 +1322,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
candidates: &mut [&mut Candidate<'_, 'tcx>], candidates: &mut [&mut Candidate<'_, 'tcx>],
block: BasicBlock, block: BasicBlock,
otherwise_block: &mut Option<BasicBlock>, otherwise_block: &mut Option<BasicBlock>,
fake_borrows: &mut Option<FxHashSet<Place<'tcx>>>, fake_borrows: &mut Option<FxIndexSet<Place<'tcx>>>,
) { ) {
let (first_candidate, remaining_candidates) = candidates.split_first_mut().unwrap(); let (first_candidate, remaining_candidates) = candidates.split_first_mut().unwrap();
@ -1385,7 +1385,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
pats: &'pat [Pat<'tcx>], pats: &'pat [Pat<'tcx>],
or_span: Span, or_span: Span,
place: PlaceBuilder<'tcx>, place: PlaceBuilder<'tcx>,
fake_borrows: &mut Option<FxHashSet<Place<'tcx>>>, fake_borrows: &mut Option<FxIndexSet<Place<'tcx>>>,
) { ) {
debug!("test_or_pattern:\ncandidate={:#?}\npats={:#?}", candidate, pats); debug!("test_or_pattern:\ncandidate={:#?}\npats={:#?}", candidate, pats);
let mut or_candidates: Vec<_> = pats let mut or_candidates: Vec<_> = pats
@ -1572,7 +1572,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
mut candidates: &'b mut [&'c mut Candidate<'pat, 'tcx>], mut candidates: &'b mut [&'c mut Candidate<'pat, 'tcx>],
block: BasicBlock, block: BasicBlock,
otherwise_block: &mut Option<BasicBlock>, otherwise_block: &mut Option<BasicBlock>,
fake_borrows: &mut Option<FxHashSet<Place<'tcx>>>, fake_borrows: &mut Option<FxIndexSet<Place<'tcx>>>,
) { ) {
// extract the match-pair from the highest priority candidate // extract the match-pair from the highest priority candidate
let match_pair = &candidates.first().unwrap().match_pairs[0]; let match_pair = &candidates.first().unwrap().match_pairs[0];
@ -1715,7 +1715,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
/// by a MIR pass run after borrow checking. /// by a MIR pass run after borrow checking.
fn calculate_fake_borrows<'b>( fn calculate_fake_borrows<'b>(
&mut self, &mut self,
fake_borrows: &'b FxHashSet<Place<'tcx>>, fake_borrows: &'b FxIndexSet<Place<'tcx>>,
temp_span: Span, temp_span: Span,
) -> Vec<(Place<'tcx>, Local)> { ) -> Vec<(Place<'tcx>, Local)> {
let tcx = self.tcx; let tcx = self.tcx;
@ -1741,8 +1741,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
all_fake_borrows.push(place.as_ref()); all_fake_borrows.push(place.as_ref());
} }
// Deduplicate and ensure a deterministic order.
all_fake_borrows.sort();
all_fake_borrows.dedup(); all_fake_borrows.dedup();
debug!("add_fake_borrows all_fake_borrows = {:?}", all_fake_borrows); debug!("add_fake_borrows all_fake_borrows = {:?}", all_fake_borrows);

View file

@ -7,8 +7,8 @@
let mut _0: i32; // return place in scope 0 at $DIR/remove_fake_borrows.rs:6:46: 6:49 let mut _0: i32; // return place in scope 0 at $DIR/remove_fake_borrows.rs:6:46: 6:49
let mut _3: isize; // in scope 0 at $DIR/remove_fake_borrows.rs:8:9: 8:16 let mut _3: isize; // in scope 0 at $DIR/remove_fake_borrows.rs:8:9: 8:16
let mut _4: &std::option::Option<&&i32>; // in scope 0 at $DIR/remove_fake_borrows.rs:7:11: 7:12 let mut _4: &std::option::Option<&&i32>; // in scope 0 at $DIR/remove_fake_borrows.rs:7:11: 7:12
let mut _5: &&&i32; // in scope 0 at $DIR/remove_fake_borrows.rs:7:11: 7:12 let mut _5: &&i32; // in scope 0 at $DIR/remove_fake_borrows.rs:7:11: 7:12
let mut _6: &&i32; // in scope 0 at $DIR/remove_fake_borrows.rs:7:11: 7:12 let mut _6: &&&i32; // in scope 0 at $DIR/remove_fake_borrows.rs:7:11: 7:12
let mut _7: &i32; // in scope 0 at $DIR/remove_fake_borrows.rs:7:11: 7:12 let mut _7: &i32; // in scope 0 at $DIR/remove_fake_borrows.rs:7:11: 7:12
let mut _8: bool; // in scope 0 at $DIR/remove_fake_borrows.rs:8:20: 8:21 let mut _8: bool; // in scope 0 at $DIR/remove_fake_borrows.rs:8:20: 8:21
@ -34,8 +34,8 @@
bb4: { bb4: {
- _4 = &shallow _1; // scope 0 at $DIR/remove_fake_borrows.rs:7:11: 7:12 - _4 = &shallow _1; // scope 0 at $DIR/remove_fake_borrows.rs:7:11: 7:12
- _5 = &shallow ((_1 as Some).0: &&i32); // scope 0 at $DIR/remove_fake_borrows.rs:7:11: 7:12 - _5 = &shallow (*((_1 as Some).0: &&i32)); // scope 0 at $DIR/remove_fake_borrows.rs:7:11: 7:12
- _6 = &shallow (*((_1 as Some).0: &&i32)); // scope 0 at $DIR/remove_fake_borrows.rs:7:11: 7:12 - _6 = &shallow ((_1 as Some).0: &&i32); // scope 0 at $DIR/remove_fake_borrows.rs:7:11: 7:12
- _7 = &shallow (*(*((_1 as Some).0: &&i32))); // scope 0 at $DIR/remove_fake_borrows.rs:7:11: 7:12 - _7 = &shallow (*(*((_1 as Some).0: &&i32))); // scope 0 at $DIR/remove_fake_borrows.rs:7:11: 7:12
+ nop; // scope 0 at $DIR/remove_fake_borrows.rs:7:11: 7:12 + nop; // scope 0 at $DIR/remove_fake_borrows.rs:7:11: 7:12
+ nop; // scope 0 at $DIR/remove_fake_borrows.rs:7:11: 7:12 + nop; // scope 0 at $DIR/remove_fake_borrows.rs:7:11: 7:12