]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_mir_build/src/build/expr/mod.rs
Add 'src/tools/miri/' from commit '75dd959a3a40eb5b4574f8d2e23aa6efbeb33573'
[rust.git] / compiler / rustc_mir_build / src / build / expr / mod.rs
1 //! Builds MIR from expressions. As a caller into this module, you
2 //! have many options, but the first thing you have to decide is
3 //! whether you are evaluating this expression for its *value*, its
4 //! *location*, or as a *constant*.
5 //!
6 //! Typically, you want the value: e.g., if you are doing `expr_a +
7 //! expr_b`, you want the values of those expressions. In that case,
8 //! you want one of the following functions. Note that if the expr has
9 //! a type that is not `Copy`, then using any of these functions will
10 //! "move" the value out of its current home (if any).
11 //!
12 //! - `expr_into_dest` -- writes the value into a specific location, which
13 //!   should be uninitialized
14 //! - `as_operand` -- evaluates the value and yields an `Operand`,
15 //!   suitable for use as an argument to an `Rvalue`
16 //! - `as_temp` -- evaluates into a temporary; this is similar to `as_operand`
17 //!   except it always returns a fresh place, even for constants
18 //! - `as_rvalue` -- yields an `Rvalue`, suitable for use in an assignment;
19 //!   as of this writing, never needed outside of the `expr` module itself
20 //!
21 //! Sometimes though want the expression's *location*. An example
22 //! would be during a match statement, or the operand of the `&`
23 //! operator. In that case, you want `as_place`. This will create a
24 //! temporary if necessary.
25 //!
26 //! Finally, if it's a constant you seek, then call
27 //! `as_constant`. This creates a `Constant<H>`, but naturally it can
28 //! only be used on constant expressions and hence is needed only in
29 //! very limited contexts.
30 //!
31 //! ### Implementation notes
32 //!
33 //! For any given kind of expression, there is generally one way that
34 //! can be lowered most naturally. This is specified by the
35 //! `Category::of` function in the `category` module. For example, a
36 //! struct expression (or other expression that creates a new value)
37 //! is typically easiest to write in terms of `as_rvalue` or `into`,
38 //! whereas a reference to a field is easiest to write in terms of
39 //! `as_place`. (The exception to this is scope and paren
40 //! expressions, which have no category.)
41 //!
42 //! Therefore, the various functions above make use of one another in
43 //! a descending fashion. For any given expression, you should pick
44 //! the most suitable spot to implement it, and then just let the
45 //! other fns cycle around. The handoff works like this:
46 //!
47 //! - `into(place)` -> fallback is to create a rvalue with `as_rvalue` and assign it to `place`
48 //! - `as_rvalue` -> fallback is to create an Operand with `as_operand` and use `Rvalue::use`
49 //! - `as_operand` -> either invokes `as_constant` or `as_temp`
50 //! - `as_constant` -> (no fallback)
51 //! - `as_temp` -> creates a temporary and either calls `as_place` or `into`
52 //! - `as_place` -> for rvalues, falls back to `as_temp` and returns that
53 //!
54 //! As you can see, there is a cycle where `into` can (in theory) fallback to `as_temp`
55 //! which can fallback to `into`. So if one of the `ExprKind` variants is not, in fact,
56 //! implemented in the category where it is supposed to be, there will be a problem.
57 //!
58 //! Of those fallbacks, the most interesting one is `into`, because
59 //! it discriminates based on the category of the expression. This is
60 //! basically the point where the "by value" operations are bridged
61 //! over to the "by reference" mode (`as_place`).
62
63 pub(crate) mod as_constant;
64 mod as_operand;
65 pub mod as_place;
66 mod as_rvalue;
67 mod as_temp;
68 pub mod category;
69 mod into;
70 mod stmt;