Skip to content

Commit e8c6786

Browse files
committed
more docs changes
1 parent a9a2b89 commit e8c6786

File tree

1 file changed

+74
-26
lines changed

1 file changed

+74
-26
lines changed

compiler/rustc_mir_dataflow/src/impls/live_borrows.rs

Lines changed: 74 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,13 @@
2929
//!
3030
//! The `Node`s in the dependency graph include data values of type `NodeKind`. `NodeKind` has
3131
//! three variants: `Local`, `Borrow` and `LocalWithRefs`.
32-
//! * `NodeKind::Local` is used for `Local`s that are borrowed somewhere (`_4` in our example)
32+
//! * `NodeKind::Local` is used for `Local`s that are borrowed somewhere (`_4` in our example), but aren't
33+
//! themselves references or pointers.
3334
//! * `NodeKind::Borrow` is used for `Local`s that correspond to borrows (`_5` in our example) and
3435
//! also `Local`s that result from re-borrows.
3536
//! * `NodeKind::LocalWithRefs` is used for `Local`s that aren't themselves borrows, but contain
36-
//! borrowed `Local`s. We want to keep these `Local`s live and also any of the references/pointers
37-
//! they might contain. Let's look at an example:
37+
//! `Local`s that correspond to references, pointers or other `Local`s with `Node`s of kind
38+
//! `NodeKind::LocalWithRef`s. Let's look at an example:
3839
//!
3940
//! ```ignore(rust)
4041
//! _4 = Bar {}
@@ -47,9 +48,15 @@
4748
//! In this example `_6` would be given `NodeKind::LocalWithRefs` and our graph would look
4849
//! as follows:
4950
//!
50-
//! `_7 (NodeKind::Borrow) -> `_6` (NodeKind::LocalWithRefs) -> `_5` (NodeKind::Borrow) -> `_4` (NodeKind::Local)
51-
//!
52-
//! In addition to keeping `_6` alive over the range of `_7` we also keep `_4` alive (leaf node).
51+
//! `_7` (NodeKind::Borrow) -> `_6` (NodeKind::LocalWithRefs) -> `_5` (NodeKind::Borrow) -> `_4` (NodeKind::Local)
52+
//!
53+
//! On the one hand we need to treat `Local`s with `Node`s of kind `NodeKind::LocalWithRefs` similarly
54+
//! to how we treat `Local`s with `Node`s of kind `NodeKind::Local`, in the sense that if they are
55+
//! borrowed we want to keep them live over the live range of the borrow. But on the other hand we
56+
//! want to also treat them like `Local`s with `Node`s of kind `NodeKind::Borrow` as they ultimately
57+
//! could also contain references or pointers that refer to other `Local`s. So we want a
58+
//! path in the graph from a `NodeKind::LocalWithRef`s node to the `NodeKind::Local` nodes, whose borrows
59+
//! they might contain.
5360
//!
5461
//! Additionally `NodeKind::LocalWithRefs` is also used for raw pointers that are cast to
5562
//! `usize`:
@@ -66,13 +73,13 @@
6673
//! * `_5` (Borrow) -> `_4` (Local)
6774
//! * `_6` (LocalWithRefs) -> `_5` (Borrow)
6875
//! * `_7` (LocalWithRefs) -> `_6` (LocalWithRefs)
69-
//! * `_8` (LocalWithRefs) -> `_7` (LocalWithRefs) (FIXME this one is currently not being done)
76+
//! * `_8` (LocalWithRefs) -> `_7` (LocalWithRefs) (FIXME this one is currently not being done, but unsafe)
7077
//!
7178
//! We also have to be careful when dealing with `Terminator`s. Whenever we pass references,
72-
//! pointers or `Local`s with `NodeKind::LocalWithRefs` (FIXME currently not done) to
73-
//! a `TerminatorKind::Call` or `TerminatorKind::Yield` and the destination `Place` or resume place, resp.,
74-
//! contains references/pointers or generic parameters we have to be careful and treat the
75-
//! `Local`s corresponding to the `Place`s as `NodeKind::LocalWithRef`s.
79+
//! pointers or `Local`s with `NodeKind::LocalWithRefs` to a `TerminatorKind::Call` or
80+
//! `TerminatorKind::Yield`, the destination `Place` or resume place, resp., might contain
81+
//! these references, pointers or `NodeKind::LocalWithRefs` `Local`s, hence we have to be conservative
82+
//! and keep the `destination` `Local` and `resume_arg` `Local` live.
7683
//!
7784
//! 2. Liveness analysis for borrows
7885
//!
@@ -86,15 +93,19 @@
8693
//! 3. _5 = Ref(_3)
8794
//! 4. _6 = Ref(_4)
8895
//! 5. _7 = Aggregate(..)(move _5)
89-
//! 6. _8 = Call(..)(move _6) (assume _8 contains no refs/ptrs or generic params)
96+
//! 6. _8 = Call(..)(move _6)
9097
//! 7. _9 = (_8.0)
91-
//! 8. (_7.0) = _9
98+
//! 8. _10 = const 5
99+
//! 9. (_7.0) = move _10
92100
//! ```
93101
//!
94102
//! * `_5` is live from stmt 3 to stmt 5
95103
//! * `_6` is live from stmt 4 to stmt 6
96-
//! * `_7` is a `Local` of kind `LocalWithRef` so needs to be taken into account in the
97-
//! analyis. It's live from stmt 5 to stmt 8
104+
//! * `_7` is a `Local` of kind `LocalWithRefs` so needs to be taken into account in the
105+
//! analyis. It's live from stmt 5 to stmt 9
106+
//! * `_8` is a `Local` of kind `LocalWithRefs`. It's live from 6. to 7.
107+
//! * `_9` is a `Local` of kind `LocalWithRefs` (FIXME this is currently not done, see FIXME above),
108+
//! it's live at 7.
98109
//!
99110
//! 3. Determining which `Local`s are borrowed
100111
//!
@@ -103,7 +114,9 @@
103114
//! `_5` (Borrow) -> `_3` (Local)
104115
//! `_6` (Borrow) -> `_4` (Local)
105116
//! `_7` (LocalWithRef) -> `_5` (Borrow)
106-
//! `_7` (LocalWithRef) -> `_9` (Local)
117+
//! `_8` (LocalWithRef) -> `_6` (Borrow)
118+
//! `_9` (LocalWithRef) -> `_8` (LocalWithRef) (FIXME currently not done)
119+
//! `_7` (LocalWithRef) -> `_10` (Local)
107120
//!
108121
//! So at each of those statements we have the following `Local`s that are live due to borrows:
109122
//!
@@ -112,9 +125,10 @@
112125
//! 3. {_3}
113126
//! 4. {_3, _4}
114127
//! 5. {_3, _4, _7}
115-
//! 6. {_3, _4, _7}
116-
//! 7. {_3, _7}
128+
//! 6. {_3, _4, _7, _8}
129+
//! 7. {_3, _4, _7, _8}
117130
//! 8. {_3, _7}
131+
//! 9. {_3, _7}
118132
//!
119133
120134
use super::*;
@@ -134,16 +148,16 @@ use either::Either;
134148

135149
#[derive(Copy, Clone, Debug)]
136150
enum NodeKind {
137-
// An node corresponding to the place of the borrowed place (`_4` in this case) in
138-
// an assignment like `_3 = Ref(_, _, _4)`.
151+
// An node corresponding to the place on the lhs of an assignment like `_3 = Ref(_, _, _4)`.
139152
Borrow(Local),
140153

141154
// Nodes corresponding to the place on the lhs of a statement like
142155
// `_2 = Aggregate(Adt(..), _, _, _, _), [move _3, move _6])`,
143156
// where _3 and _6 are places corresponding to references or raw pointers.
144157
LocalWithRefs(Local),
145158

146-
// Nodes corresponding to the place on the lhs of an assignment like `_2 = Ref(..)`.
159+
// Nodes corresponding to the borrowed place of an assignment like `_2 = Ref(_, _, borrowed_place)`,
160+
// if `borrowed_place` is a non-ref or non-ptr value.
147161
Local(Local),
148162
}
149163

@@ -159,11 +173,25 @@ impl NodeKind {
159173

160174
/// Used to build a dependency graph between borrows/pointers and the `Local`s that
161175
/// they reference.
162-
/// We add edges to the graph in two kinds of situations:
163-
/// * direct assignment of reference or raw pointer (e.g. `_4 = Ref(..)` or `_4 = AddressOf`)
176+
/// We add edges to the graph in following situations:
177+
/// * direct assignment of reference or raw pointer (e.g. `_4 = Ref(_, _ , borrowed_place)` or
178+
/// `_4 = AddressOf(_, borrowed_place)`). For this case we create a `Node` of kind
179+
/// `NodeKind::Borrow` for the `Local` being assigned to and an edge to either an existing
180+
/// `Node` or if none exists yet to a new `Node` of type `NodeKind::Local` corresponding to
181+
/// a non-ref/ptr `Local`.
164182
/// * assignments to non-reference or non-pointer `Local`s, which themselves might contain
165183
/// references or pointers (e.g. `_2 = Aggregate(Adt(..), _, _, _, _), [move _3, move _6])`,
166-
/// where `_3` and `_6` are places corresponding to references or raw pointers).
184+
/// where `_3` and `_6` are places corresponding to references or raw pointers). In this case
185+
/// we create a `Node` of kind `NodeKind::LocalWithRefs` for `_2`. Since `_3` and `_6` are
186+
/// `Local`s that correspond to references, pointers or composite types that might contain
187+
/// references or pointers (`NodeKind::LocalWithRefs`), there already exist `Node`s for these
188+
/// `Local`s. We then add edges from the `Node` for `_2` to both the `Node` for `_3` and the
189+
/// `Node` for `_6`.
190+
/// * `destination` places for `TerminatorKind::Call` and the `resume_arg` places for
191+
/// `TerminatorKind::Yield` if we pass in any references, pointers or composite values that
192+
/// might correspond to references, pointers or exposed pointers (`NodeKind::LocalWithRef`s).
193+
/// The rationale for this is that the return values of both of these terminators might themselves
194+
/// contain any of the references or pointers passed as arguments.
167195
struct BorrowDependencies<'a, 'tcx> {
168196
tcx: TyCtxt<'tcx>,
169197
local_decls: &'a LocalDecls<'tcx>,
@@ -396,7 +424,13 @@ impl<'a, 'tcx> Visitor<'tcx> for BorrowDependencies<'a, 'tcx> {
396424
}
397425

398426
pub struct BorrowedLocalsResults<'mir, 'tcx> {
427+
// the results of the liveness analysis of `LiveBorrows`
399428
borrows_analysis_results: Results<'tcx, LiveBorrows<'mir, 'tcx>>,
429+
430+
// Maps each `Local` that corresponds to a reference, pointer or a node of kind
431+
// `NodeKind::LocalWithRefs` (i.e. `Local`s which either correspond to refs, pointers or
432+
// exposed pointers or a composite value that might include refs, pointers or exposed pointers)
433+
// to the set of `Local`s that are borrowed through those references, pointers or composite values.
400434
borrowed_local_to_locals_to_keep_alive: FxHashMap<Local, Vec<Local>>,
401435
}
402436

@@ -473,6 +507,8 @@ where
473507
}
474508
}
475509

510+
/// The function gets the results of the borrowed locals analysis in this module. See the module
511+
/// doc-comment for information on what exactly this analysis does.
476512
#[instrument(skip(tcx), level = "debug")]
477513
pub fn get_borrowed_locals_results<'mir, 'tcx>(
478514
body: &'mir Body<'tcx>,
@@ -517,9 +553,19 @@ pub fn get_borrowed_locals_results<'mir, 'tcx>(
517553
BorrowedLocalsResults::new(results)
518554
}
519555

556+
/// The `ResultsCursor` equivalent for the borrowed locals analysis. Since this analysis doesn't
557+
/// require convergence, we expose the set of borrowed `Local`s for a `Location` directly via
558+
/// the `get` method without the need for any prior 'seek' calls.
520559
pub struct BorrowedLocalsResultsCursor<'a, 'mir, 'tcx> {
521560
body: &'mir Body<'tcx>,
561+
562+
// The cursor for the liveness analysis performed by `LiveBorrows`
522563
borrows_analysis_cursor: ResultsRefCursor<'a, 'mir, 'tcx, LiveBorrows<'mir, 'tcx>>,
564+
565+
// Maps each `Local` corresponding to a reference or pointer to the set of `Local`s
566+
// that are borrowed through the ref/ptr. Additionally contains entries for `Local`s
567+
// corresponding to `NodeKind::LocalWithRefs` since they might contain refs, ptrs or
568+
// exposed pointers and need to be treated equivalently to refs/ptrs
523569
borrowed_local_to_locals_to_keep_alive: &'a FxHashMap<Local, Vec<Local>>,
524570
}
525571

@@ -586,7 +632,9 @@ impl<'a, 'mir, 'tcx> BorrowedLocalsResultsCursor<'a, 'mir, 'tcx> {
586632
}
587633
}
588634

589-
/// Performs a liveness analysis for borrows and raw pointers.
635+
/// Performs a liveness analysis for borrows and raw pointers. This analysis also tracks `Local`s
636+
/// corresponding to `Node`s of kind `NodeKind::LocalWithRefs`, as these could potentially refer to
637+
/// or include references, pointers or exposed pointers.
590638
pub struct LiveBorrows<'mir, 'tcx> {
591639
body: &'mir Body<'tcx>,
592640
tcx: TyCtxt<'tcx>,
@@ -662,7 +710,7 @@ impl<'a, 'tcx> GenKillAnalysis<'tcx> for LiveBorrows<'a, 'tcx> {
662710
}
663711
}
664712

665-
/// A `Visitor` that defines the transfer function for `MaybeBorrowedLocals`.
713+
/// A `Visitor` that defines the transfer function for `LiveBorrows`.
666714
struct TransferFunction<'a, 'b, 'c, 'tcx, T> {
667715
body: &'a Body<'tcx>,
668716
tcx: TyCtxt<'tcx>,

0 commit comments

Comments
 (0)