1# MIR borrow check
2
3The borrow check is Rust's "secret sauce" – it is tasked with
4enforcing a number of properties:
5
6- That all variables are initialized before they are used.
7- That you can't move the same value twice.
8- That you can't move a value while it is borrowed.
9- That you can't access a place while it is mutably borrowed (except through
10  the reference).
11- That you can't mutate a place while it is immutably borrowed.
12- etc
13
14The borrow checker operates on the MIR. An older implementation operated on the
15HIR. Doing borrow checking on MIR has several advantages:
16
17- The MIR is *far* less complex than the HIR; the radical desugaring
18  helps prevent bugs in the borrow checker. (If you're curious, you
19  can see
20  [a list of bugs that the MIR-based borrow checker fixes here][47366].)
21- Even more importantly, using the MIR enables ["non-lexical lifetimes"][nll],
22  which are regions derived from the control-flow graph.
23
24[47366]: https://github.com/rust-lang/rust/issues/47366
25[nll]: https://rust-lang.github.io/rfcs/2094-nll.html
26
27### Major phases of the borrow checker
28
29The borrow checker source is found in
30[the `rustc_borrow_ck` crate][b_c]. The main entry point is
31the [`mir_borrowck`] query.
32
33[b_c]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_borrowck/index.html
34[`mir_borrowck`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_borrowck/fn.mir_borrowck.html
35
36- We first create a **local copy** of the MIR. In the coming steps,
37  we will modify this copy in place to modify the types and things to
38  include references to the new regions that we are computing.
39- We then invoke [`replace_regions_in_mir`] to modify our local MIR.
40  Among other things, this function will replace all of the [regions](./appendix/glossary.md#region)
41  in the MIR with fresh [inference variables](./appendix/glossary.md#inf-var).
42- Next, we perform a number of
43  [dataflow analyses](./appendix/background.md#dataflow) that
44  compute what data is moved and when.
45- We then do a [second type check](borrow_check/type_check.md) across the MIR:
46  the purpose of this type check is to determine all of the constraints between
47  different regions.
48- Next, we do [region inference](borrow_check/region_inference.md), which computes
49  the values of each region — basically, the points in the control-flow graph where
50  each lifetime must be valid according to the constraints we collected.
51- At this point, we can compute the "borrows in scope" at each point.
52- Finally, we do a second walk over the MIR, looking at the actions it
53  does and reporting errors. For example, if we see a statement like
54  `*a + 1`, then we would check that the variable `a` is initialized
55  and that it is not mutably borrowed, as either of those would
56  require an error to be reported. Doing this check requires the results of all
57  the previous analyses.
58
59[`replace_regions_in_mir`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_borrowck/nll/fn.replace_regions_in_mir.html
60