Skip to content

Commit ee44706

Browse files
committed
Auto merge of #150013 - matthiaskrgr:rollup-srl9jrb, r=matthiaskrgr
Rollup of 7 pull requests Successful merges: - #149744 (test: update duplicate many_digits test to use f64 instead of f32) - #149946 (mir_build: Move and rename code for partitioning match candidates) - #149987 (Move ambient cdb discovery from compiletest to bootstrap) - #149990 (Improve amdgpu docs: Mention device-libs and xnack) - #149994 (Allow vector types for amdgpu) - #149997 (Link POSIX instead of Linux manual for Instant) - #150010 (Correct library linking for hexagon targets in run-make tests) r? `@ghost` `@rustbot` modify labels: rollup
2 parents 693f365 + fa52c96 commit ee44706

File tree

16 files changed

+460
-419
lines changed

16 files changed

+460
-419
lines changed

compiler/rustc_mir_build/src/builder/matches/buckets.rs

Lines changed: 353 additions & 0 deletions
Large diffs are not rendered by default.

compiler/rustc_mir_build/src/builder/matches/mod.rs

Lines changed: 6 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,15 @@ use tracing::{debug, instrument};
2727

2828
use crate::builder::ForGuard::{self, OutsideGuard, RefWithinGuard};
2929
use crate::builder::expr::as_place::PlaceBuilder;
30+
use crate::builder::matches::buckets::PartitionedCandidates;
3031
use crate::builder::matches::user_ty::ProjectedUserTypesNode;
3132
use crate::builder::scope::DropKind;
3233
use crate::builder::{
3334
BlockAnd, BlockAndExtension, Builder, GuardFrame, GuardFrameLocal, LocalsForNode,
3435
};
3536

3637
// helper functions, broken out by category:
38+
mod buckets;
3739
mod match_pair;
3840
mod test;
3941
mod user_ty;
@@ -1068,7 +1070,7 @@ struct Candidate<'tcx> {
10681070
/// Key mutations include:
10691071
///
10701072
/// - When a match pair is fully satisfied by a test, it is removed from the
1071-
/// list, and its subpairs are added instead (see [`Builder::sort_candidate`]).
1073+
/// list, and its subpairs are added instead (see [`Builder::choose_bucket_for_candidate`]).
10721074
/// - During or-pattern expansion, any leading or-pattern is removed, and is
10731075
/// converted into subcandidates (see [`Builder::expand_and_match_or_candidates`]).
10741076
/// - After a candidate's subcandidates have been lowered, a copy of any remaining
@@ -1253,7 +1255,7 @@ struct Ascription<'tcx> {
12531255
///
12541256
/// Created by [`MatchPairTree::for_pattern`], and then inspected primarily by:
12551257
/// - [`Builder::pick_test_for_match_pair`] (to choose a test)
1256-
/// - [`Builder::sort_candidate`] (to see how the test interacts with a match pair)
1258+
/// - [`Builder::choose_bucket_for_candidate`] (to see how the test interacts with a match pair)
12571259
///
12581260
/// Note that or-patterns are not tested directly like the other variants.
12591261
/// Instead they participate in or-pattern expansion, where they are transformed into
@@ -2172,86 +2174,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
21722174
(match_place, test)
21732175
}
21742176

2175-
/// Given a test, we partition the input candidates into several buckets.
2176-
/// If a candidate matches in exactly one of the branches of `test`
2177-
/// (and no other branches), we put it into the corresponding bucket.
2178-
/// If it could match in more than one of the branches of `test`, the test
2179-
/// doesn't usefully apply to it, and we stop partitioning candidates.
2180-
///
2181-
/// Importantly, we also **mutate** the branched candidates to remove match pairs
2182-
/// that are entailed by the outcome of the test, and add any sub-pairs of the
2183-
/// removed pairs.
2184-
///
2185-
/// This returns a pair of
2186-
/// - the candidates that weren't sorted;
2187-
/// - for each possible outcome of the test, the candidates that match in that outcome.
2188-
///
2189-
/// For example:
2190-
/// ```
2191-
/// # let (x, y, z) = (true, true, true);
2192-
/// match (x, y, z) {
2193-
/// (true , _ , true ) => true, // (0)
2194-
/// (false, false, _ ) => false, // (1)
2195-
/// (_ , true , _ ) => true, // (2)
2196-
/// (true , _ , false) => false, // (3)
2197-
/// }
2198-
/// # ;
2199-
/// ```
2200-
///
2201-
/// Assume we are testing on `x`. Conceptually, there are 2 overlapping candidate sets:
2202-
/// - If the outcome is that `x` is true, candidates {0, 2, 3} are possible
2203-
/// - If the outcome is that `x` is false, candidates {1, 2} are possible
2204-
///
2205-
/// Following our algorithm:
2206-
/// - Candidate 0 is sorted into outcome `x == true`
2207-
/// - Candidate 1 is sorted into outcome `x == false`
2208-
/// - Candidate 2 remains unsorted, because testing `x` has no effect on it
2209-
/// - Candidate 3 remains unsorted, because a previous candidate (2) was unsorted
2210-
/// - This helps preserve the illusion that candidates are tested "in order"
2211-
///
2212-
/// The sorted candidates are mutated to remove entailed match pairs:
2213-
/// - candidate 0 becomes `[z @ true]` since we know that `x` was `true`;
2214-
/// - candidate 1 becomes `[y @ false]` since we know that `x` was `false`.
2215-
fn sort_candidates<'b, 'c>(
2216-
&mut self,
2217-
match_place: Place<'tcx>,
2218-
test: &Test<'tcx>,
2219-
mut candidates: &'b mut [&'c mut Candidate<'tcx>],
2220-
) -> (
2221-
&'b mut [&'c mut Candidate<'tcx>],
2222-
FxIndexMap<TestBranch<'tcx>, Vec<&'b mut Candidate<'tcx>>>,
2223-
) {
2224-
// For each of the possible outcomes, collect vector of candidates that apply if the test
2225-
// has that particular outcome.
2226-
let mut target_candidates: FxIndexMap<_, Vec<&mut Candidate<'_>>> = Default::default();
2227-
2228-
let total_candidate_count = candidates.len();
2229-
2230-
// Sort the candidates into the appropriate vector in `target_candidates`. Note that at some
2231-
// point we may encounter a candidate where the test is not relevant; at that point, we stop
2232-
// sorting.
2233-
while let Some(candidate) = candidates.first_mut() {
2234-
let Some(branch) =
2235-
self.sort_candidate(match_place, test, candidate, &target_candidates)
2236-
else {
2237-
break;
2238-
};
2239-
let (candidate, rest) = candidates.split_first_mut().unwrap();
2240-
target_candidates.entry(branch).or_insert_with(Vec::new).push(candidate);
2241-
candidates = rest;
2242-
}
2243-
2244-
// At least the first candidate ought to be tested
2245-
assert!(
2246-
total_candidate_count > candidates.len(),
2247-
"{total_candidate_count}, {candidates:#?}"
2248-
);
2249-
debug!("tested_candidates: {}", total_candidate_count - candidates.len());
2250-
debug!("untested_candidates: {}", candidates.len());
2251-
2252-
(candidates, target_candidates)
2253-
}
2254-
22552177
/// This is the most subtle part of the match lowering algorithm. At this point, there are
22562178
/// no fully-satisfied candidates, and no or-patterns to expand, so we actually need to
22572179
/// perform some sort of test to make progress.
@@ -2363,8 +2285,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
23632285
// For each of the N possible test outcomes, build the vector of candidates that applies if
23642286
// the test has that particular outcome. This also mutates the candidates to remove match
23652287
// pairs that are fully satisfied by the relevant outcome.
2366-
let (remaining_candidates, target_candidates) =
2367-
self.sort_candidates(match_place, &test, candidates);
2288+
let PartitionedCandidates { target_candidates, remaining_candidates } =
2289+
self.partition_candidates_into_buckets(match_place, &test, candidates);
23682290

23692291
// The block that we should branch to if none of the `target_candidates` match.
23702292
let remainder_start = self.cfg.start_new_block();

0 commit comments

Comments
 (0)