Skip to content

Commit 496836a

Browse files
committed
Improve rustc_mir_build::matches docs
- Fix typos - Add more information - General cleanup
1 parent 1d0d76f commit 496836a

File tree

2 files changed

+72
-53
lines changed

2 files changed

+72
-53
lines changed

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

+71-52
Original file line numberDiff line numberDiff line change
@@ -82,8 +82,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
8282
/// visible through borrow checking. False edges ensure that the CFG as
8383
/// seen by borrow checking doesn't encode this. False edges are added:
8484
///
85-
/// * From each prebinding block to the next prebinding block.
86-
/// * From each otherwise block to the next prebinding block.
85+
/// * From each pre-binding block to the next pre-binding block.
86+
/// * From each otherwise block to the next pre-binding block.
8787
crate fn match_expr(
8888
&mut self,
8989
destination: Place<'tcx>,
@@ -630,10 +630,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
630630

631631
#[derive(Debug)]
632632
pub(super) struct Candidate<'pat, 'tcx> {
633-
/// `Span` of the original pattern that gave rise to this candidate
633+
/// [`Span`] of the original pattern that gave rise to this candidate.
634634
span: Span,
635635

636-
/// This `Candidate` has a guard.
636+
/// Whether this `Candidate` has a guard.
637637
has_guard: bool,
638638

639639
/// All of these must be satisfied...
@@ -645,14 +645,15 @@ pub(super) struct Candidate<'pat, 'tcx> {
645645
/// ...and these types asserted...
646646
ascriptions: Vec<Ascription<'tcx>>,
647647

648-
/// ... and if this is non-empty, one of these subcandidates also has to match ...
648+
/// ...and if this is non-empty, one of these subcandidates also has to match...
649649
subcandidates: Vec<Candidate<'pat, 'tcx>>,
650650

651-
/// ...and the guard must be evaluated, if false branch to Block...
651+
/// ...and the guard must be evaluated; if it's `false` then branch to `otherwise_block`.
652652
otherwise_block: Option<BasicBlock>,
653653

654-
/// ...and the blocks for add false edges between candidates
654+
/// The block before the `bindings` have been established.
655655
pre_binding_block: Option<BasicBlock>,
656+
/// The pre-binding block of the next candidate.
656657
next_candidate_pre_binding_block: Option<BasicBlock>,
657658
}
658659

@@ -737,26 +738,27 @@ crate struct MatchPair<'pat, 'tcx> {
737738
pattern: &'pat Pat<'tcx>,
738739
}
739740

741+
/// See [`Test`] for more.
740742
#[derive(Clone, Debug, PartialEq)]
741743
enum TestKind<'tcx> {
742-
/// Test the branches of enum.
744+
/// Test what enum variant a value is.
743745
Switch {
744-
/// The enum being tested
746+
/// The enum type being tested.
745747
adt_def: &'tcx ty::AdtDef,
746748
/// The set of variants that we should create a branch for. We also
747749
/// create an additional "otherwise" case.
748750
variants: BitSet<VariantIdx>,
749751
},
750752

751-
/// Test what value an `integer`, `bool` or `char` has.
753+
/// Test what value an integer, `bool`, or `char` has.
752754
SwitchInt {
753755
/// The type of the value that we're testing.
754756
switch_ty: Ty<'tcx>,
755757
/// The (ordered) set of values that we test for.
756758
///
757759
/// For integers and `char`s we create a branch to each of the values in
758760
/// `options`, as well as an "otherwise" branch for all other values, even
759-
/// in the (rare) case that options is exhaustive.
761+
/// in the (rare) case that `options` is exhaustive.
760762
///
761763
/// For `bool` we always generate two edges, one for `true` and one for
762764
/// `false`.
@@ -776,17 +778,21 @@ enum TestKind<'tcx> {
776778
/// Test whether the value falls within an inclusive or exclusive range
777779
Range(PatRange<'tcx>),
778780

779-
/// Test length of the slice is equal to len
781+
/// Test that the length of the slice is equal to `len`.
780782
Len { len: u64, op: BinOp },
781783
}
782784

785+
/// A test to perform to determine which [`Candidate`] matches a value.
786+
///
787+
/// [`Test`] is just the test to perform; it does not include the value
788+
/// to be tested.
783789
#[derive(Debug)]
784790
crate struct Test<'tcx> {
785791
span: Span,
786792
kind: TestKind<'tcx>,
787793
}
788794

789-
/// ArmHasGuard is isomorphic to a boolean flag. It indicates whether
795+
/// `ArmHasGuard` is a wrapper around a boolean flag. It indicates whether
790796
/// a match arm has a guard expression attached to it.
791797
#[derive(Copy, Clone, Debug)]
792798
crate struct ArmHasGuard(crate bool);
@@ -801,27 +807,27 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
801807
/// candidates are sorted such that the first item in the list
802808
/// has the highest priority. When a candidate is found to match
803809
/// the value, we will set and generate a branch to the appropriate
804-
/// prebinding block.
810+
/// pre-binding block.
805811
///
806812
/// If we find that *NONE* of the candidates apply, we branch to the
807813
/// `otherwise_block`, setting it to `Some` if required. In principle, this
808814
/// means that the input list was not exhaustive, though at present we
809815
/// sometimes are not smart enough to recognize all exhaustive inputs.
810816
///
811-
/// It might be surprising that the input can be inexhaustive.
817+
/// It might be surprising that the input can be non-exhaustive.
812818
/// Indeed, initially, it is not, because all matches are
813819
/// exhaustive in Rust. But during processing we sometimes divide
814820
/// up the list of candidates and recurse with a non-exhaustive
815821
/// list. This is important to keep the size of the generated code
816-
/// under control. See `test_candidates` for more details.
822+
/// under control. See [`Builder::test_candidates`] for more details.
817823
///
818-
/// If `fake_borrows` is Some, then places which need fake borrows
824+
/// If `fake_borrows` is `Some`, then places which need fake borrows
819825
/// will be added to it.
820826
///
821827
/// For an example of a case where we set `otherwise_block`, even for an
822-
/// exhaustive match consider:
828+
/// exhaustive match, consider:
823829
///
824-
/// ```rust
830+
/// ```
825831
/// match x {
826832
/// (true, true) => (),
827833
/// (_, false) => (),
@@ -830,8 +836,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
830836
/// ```
831837
///
832838
/// For this match, we check if `x.0` matches `true` (for the first
833-
/// arm). If that's false, we check `x.1`. If it's `true` we check if
834-
/// `x.0` matches `false` (for the third arm). In the (impossible at
839+
/// arm). If it doesn't match, we check `x.1`. If `x.1` is `true` we check
840+
/// if `x.0` matches `false` (for the third arm). In the (impossible at
835841
/// runtime) case when `x.0` is now `true`, we branch to
836842
/// `otherwise_block`.
837843
fn match_candidates<'pat>(
@@ -938,26 +944,31 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
938944
);
939945
}
940946

941-
/// Link up matched candidates. For example, if we have something like
942-
/// this:
947+
/// Link up matched candidates.
948+
///
949+
/// For example, if we have something like this:
943950
///
944951
/// ```rust
945952
/// ...
946-
/// Some(x) if cond => ...
953+
/// Some(x) if cond1 => ...
947954
/// Some(x) => ...
948-
/// Some(x) if cond => ...
955+
/// Some(x) if cond2 => ...
949956
/// ...
950957
/// ```
951958
///
952959
/// We generate real edges from:
953-
/// * `start_block` to the `prebinding_block` of the first pattern,
954-
/// * the otherwise block of the first pattern to the second pattern,
955-
/// * the otherwise block of the third pattern to the a block with an
956-
/// Unreachable terminator.
957960
///
958-
/// As well as that we add fake edges from the otherwise blocks to the
959-
/// prebinding block of the next candidate in the original set of
961+
/// * `start_block` to the [pre-binding block] of the first pattern,
962+
/// * the [otherwise block] of the first pattern to the second pattern,
963+
/// * the [otherwise block] of the third pattern to a block with an
964+
/// [`Unreachable` terminator](TerminatorKind::Unreachable).
965+
///
966+
/// In addition, we add fake edges from the otherwise blocks to the
967+
/// pre-binding block of the next candidate in the original set of
960968
/// candidates.
969+
///
970+
/// [pre-binding block]: Candidate::pre_binding_block
971+
/// [otherwise block]: Candidate::otherwise_block
961972
fn select_matched_candidates(
962973
&mut self,
963974
matched_candidates: &mut [&mut Candidate<'_, 'tcx>],
@@ -1044,7 +1055,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
10441055
/// forwards to [Builder::test_candidates].
10451056
///
10461057
/// Given a pattern `(P | Q, R | S)` we (in principle) generate a CFG like
1047-
/// so
1058+
/// so:
10481059
///
10491060
/// ```text
10501061
/// [ start ]
@@ -1214,31 +1225,35 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
12141225
/// This is the most subtle part of the matching algorithm. At
12151226
/// this point, the input candidates have been fully simplified,
12161227
/// and so we know that all remaining match-pairs require some
1217-
/// sort of test. To decide what test to do, we take the highest
1228+
/// sort of test. To decide what test to perform, we take the highest
12181229
/// priority candidate (last one in the list) and extract the
12191230
/// first match-pair from the list. From this we decide what kind
1220-
/// of test is needed using `test`, defined in the `test` module.
1231+
/// of test is needed using [`Builder::test`], defined in the
1232+
/// [`test` module](mod@test).
12211233
///
12221234
/// *Note:* taking the first match pair is somewhat arbitrary, and
12231235
/// we might do better here by choosing more carefully what to
12241236
/// test.
12251237
///
12261238
/// For example, consider the following possible match-pairs:
12271239
///
1228-
/// 1. `x @ Some(P)` -- we will do a `Switch` to decide what variant `x` has
1229-
/// 2. `x @ 22` -- we will do a `SwitchInt`
1230-
/// 3. `x @ 3..5` -- we will do a range test
1240+
/// 1. `x @ Some(P)` -- we will do a [`Switch`] to decide what variant `x` has
1241+
/// 2. `x @ 22` -- we will do a [`SwitchInt`] to decide what value `x` has
1242+
/// 3. `x @ 3..5` -- we will do a [`Range`] test to decide what range `x` falls in
12311243
/// 4. etc.
12321244
///
1245+
/// [`Switch`]: TestKind::Switch
1246+
/// [`SwitchInt`]: TestKind::SwitchInt
1247+
/// [`Range`]: TestKind::Range
1248+
///
12331249
/// Once we know what sort of test we are going to perform, this
1234-
/// Tests may also help us with other candidates. So we walk over
1250+
/// test may also help us winnow down our candidates. So we walk over
12351251
/// the candidates (from high to low priority) and check. This
12361252
/// gives us, for each outcome of the test, a transformed list of
1237-
/// candidates. For example, if we are testing the current
1238-
/// variant of `x.0`, and we have a candidate `{x.0 @ Some(v), x.1
1239-
/// @ 22}`, then we would have a resulting candidate of `{(x.0 as
1240-
/// Some).0 @ v, x.1 @ 22}`. Note that the first match-pair is now
1241-
/// simpler (and, in fact, irrefutable).
1253+
/// candidates. For example, if we are testing `x.0`'s variant,
1254+
/// and we have a candidate `(x.0 @ Some(v), x.1 @ 22)`,
1255+
/// then we would have a resulting candidate of `((x.0 as Some).0 @ v, x.1 @ 22)`.
1256+
/// Note that the first match-pair is now simpler (and, in fact, irrefutable).
12421257
///
12431258
/// But there may also be candidates that the test just doesn't
12441259
/// apply to. The classical example involves wildcards:
@@ -1268,7 +1283,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
12681283
/// is trivially NP-complete:
12691284
///
12701285
/// ```rust
1271-
/// match (var0, var1, var2, var3, ..) {
1286+
/// match (var0, var1, var2, var3, ...) {
12721287
/// (true, _, _, false, true, ...) => false,
12731288
/// (_, true, true, false, _, ...) => false,
12741289
/// (false, _, false, false, _, ...) => false,
@@ -1283,7 +1298,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
12831298
///
12841299
/// That kind of exponential worst-case might not occur in practice, but
12851300
/// our simplistic treatment of constants and guards would make it occur
1286-
/// in very common situations - for example #29740:
1301+
/// in very common situations - for example [#29740]:
12871302
///
12881303
/// ```rust
12891304
/// match x {
@@ -1294,13 +1309,17 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
12941309
/// }
12951310
/// ```
12961311
///
1297-
/// Here we first test the match-pair `x @ "foo"`, which is an `Eq` test.
1312+
/// [#29740]: https://github.com/rust-lang/rust/issues/29740
1313+
///
1314+
/// Here we first test the match-pair `x @ "foo"`, which is an [`Eq` test].
1315+
///
1316+
/// [`Eq` test]: TestKind::Eq
12981317
///
12991318
/// It might seem that we would end up with 2 disjoint candidate
1300-
/// sets, consisting of the first candidate or the other 3, but our
1301-
/// algorithm doesn't reason about "foo" being distinct from the other
1319+
/// sets, consisting of the first candidate or the other two, but our
1320+
/// algorithm doesn't reason about `"foo"` being distinct from the other
13021321
/// constants; it considers the latter arms to potentially match after
1303-
/// both outcomes, which obviously leads to an exponential amount
1322+
/// both outcomes, which obviously leads to an exponential number
13041323
/// of tests.
13051324
///
13061325
/// To avoid these kinds of problems, our algorithm tries to ensure
@@ -1312,16 +1331,16 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
13121331
///
13131332
/// After we perform our test, we branch into the appropriate candidate
13141333
/// set and recurse with `match_candidates`. These sub-matches are
1315-
/// obviously inexhaustive - as we discarded our otherwise set - so
1334+
/// obviously non-exhaustive - as we discarded our otherwise set - so
13161335
/// we set their continuation to do `match_candidates` on the
1317-
/// "unmatched" set (which is again inexhaustive).
1336+
/// "unmatched" set (which is again non-exhaustive).
13181337
///
13191338
/// If you apply this to the above test, you basically wind up
13201339
/// with an if-else-if chain, testing each candidate in turn,
13211340
/// which is precisely what we want.
13221341
///
13231342
/// In addition to avoiding exponential-time blowups, this algorithm
1324-
/// also has nice property that each guard and arm is only generated
1343+
/// also has the nice property that each guard and arm is only generated
13251344
/// once.
13261345
fn test_candidates<'pat, 'b, 'c>(
13271346
&mut self,

compiler/rustc_mir_build/src/build/matches/test.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ use std::cmp::Ordering;
2323
impl<'a, 'tcx> Builder<'a, 'tcx> {
2424
/// Identifies what test is needed to decide if `match_pair` is applicable.
2525
///
26-
/// It is a bug to call this with a simplifiable pattern.
26+
/// It is a bug to call this with a not-fully-simplified pattern.
2727
pub(super) fn test<'pat>(&mut self, match_pair: &MatchPair<'pat, 'tcx>) -> Test<'tcx> {
2828
match *match_pair.pattern.kind {
2929
PatKind::Variant { ref adt_def, substs: _, variant_index: _, subpatterns: _ } => Test {

0 commit comments

Comments
 (0)