1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your // option. This file may not be copied, modified, or distributed // except according to those terms. //! Translates expressions into MIR. As a caller into this module, you //! have many options, but the first thing you have to decide is //! whether you are evaluating this expression for its *value*, its //! *location*, or as a *constant*. //! //! Typically, you want the value: e.g., if you are doing `expr_a + //! expr_b`, you want the values of those expressions. In that case, //! you want one of the following functions. Note that if the expr has //! a type that is not `Copy`, then using any of these functions will //! "move" the value out of its current home (if any). //! //! - `into` -- writes the value into a specific location, which //! should be uninitialized //! - `as_operand` -- evaluates the value and yields an `Operand`, //! suitable for use as an argument to an `Rvalue` //! - `as_temp` -- evaluates into a temporary; this is similar to `as_operand` //! except it always returns a fresh lvalue, even for constants //! - `as_rvalue` -- yields an `Rvalue`, suitable for use in an assignment; //! as of this writing, never needed outside of the `expr` module itself //! //! Sometimes though want the expression's *location*. An example //! would be during a match statement, or the operand of the `&` //! operator. In that case, you want `as_lvalue`. This will create a //! temporary if necessary. //! //! Finally, if it's a constant you seek, then call //! `as_constant`. This creates a `Constant<H>`, but naturally it can //! only be used on constant expressions and hence is needed only in //! very limited contexts. //! //! ### Implementation notes //! //! For any given kind of expression, there is generally one way that //! can be translated most naturally. This is specified by the //! `Category::of` function in the `category` module. For example, a //! struct expression (or other expression that creates a new value) //! is typically easiest to write in terms of `as_rvalue` or `into`, //! whereas a reference to a field is easiest to write in terms of //! `as_lvalue`. (The exception to this is scope and paren //! expressions, which have no category.) //! //! Therefore, the various functions above make use of one another in //! a descending fashion. For any given expression, you should pick //! the most suitable spot to implement it, and then just let the //! other fns cycle around. The handoff works like this: //! //! - `into(lv)` -> fallback is to create a rvalue with `as_rvalue` and assign it to `lv` //! - `as_rvalue` -> fallback is to create an Operand with `as_operand` and use `Rvalue::use` //! - `as_operand` -> either invokes `as_constant` or `as_temp` //! - `as_constant` -> (no fallback) //! - `as_temp` -> creates a temporary and either calls `as_lvalue` or `into` //! - `as_lvalue` -> for rvalues, falls back to `as_temp` and returns that //! //! As you can see, there is a cycle where `into` can (in theory) fallback to `as_temp` //! which can fallback to `into`. So if one of the `ExprKind` variants is not, in fact, //! implemented in the category where it is supposed to be, there will be a problem. //! //! Of those fallbacks, the most interesting one is `as_temp`, because //! it discriminates based on the category of the expression. This is //! basically the point where the "by value" operations are bridged //! over to the "by reference" mode (`as_lvalue`). mod as_constant; mod as_lvalue; mod as_rvalue; mod as_operand; mod as_temp; mod category; mod into; mod stmt;