rustc_mir_build/builder/expr/
category.rs

1use rustc_middle::thir::*;
2
3#[derive(Debug, PartialEq)]
4pub(crate) enum Category {
5    /// An assignable memory location like `x`, `x.f`, `foo()[3]`, that
6    /// sort of thing. Something that could appear on the LHS of an `=`
7    /// sign.
8    Place,
9
10    /// A literal like `23` or `"foo"`. Does not include constant
11    /// expressions like `3 + 5`.
12    Constant,
13
14    /// Something that generates a new value at runtime, like `x + y`
15    /// or `foo()`.
16    Rvalue(RvalueFunc),
17}
18
19/// Rvalues fall into different "styles" that will determine which fn
20/// is best suited to generate them.
21#[derive(Debug, PartialEq)]
22pub(crate) enum RvalueFunc {
23    /// Best generated by `into`. This is generally exprs that
24    /// cause branching, like `match`, but also includes calls.
25    Into,
26
27    /// Best generated by `as_rvalue`. This is usually the case.
28    AsRvalue,
29}
30
31impl Category {
32    /// Determines the category for a given expression. Note that scope
33    /// and paren expressions have no category.
34    pub(crate) fn of(ek: &ExprKind<'_>) -> Option<Category> {
35        match *ek {
36            ExprKind::Scope { .. } => None,
37
38            ExprKind::Field { .. }
39            | ExprKind::Deref { .. }
40            | ExprKind::Index { .. }
41            | ExprKind::UpvarRef { .. }
42            | ExprKind::VarRef { .. }
43            | ExprKind::PlaceTypeAscription { .. }
44            | ExprKind::ValueTypeAscription { .. }
45            | ExprKind::PlaceUnwrapUnsafeBinder { .. }
46            | ExprKind::ValueUnwrapUnsafeBinder { .. } => Some(Category::Place),
47
48            ExprKind::LogicalOp { .. }
49            | ExprKind::Match { .. }
50            | ExprKind::If { .. }
51            | ExprKind::Let { .. }
52            | ExprKind::NeverToAny { .. }
53            | ExprKind::Use { .. }
54            | ExprKind::Adt { .. }
55            | ExprKind::Borrow { .. }
56            | ExprKind::RawBorrow { .. }
57            | ExprKind::Yield { .. }
58            | ExprKind::Call { .. }
59            | ExprKind::InlineAsm { .. } => Some(Category::Rvalue(RvalueFunc::Into)),
60
61            ExprKind::Array { .. }
62            | ExprKind::Tuple { .. }
63            | ExprKind::Closure { .. }
64            | ExprKind::Unary { .. }
65            | ExprKind::Binary { .. }
66            | ExprKind::Box { .. }
67            | ExprKind::Cast { .. }
68            | ExprKind::PointerCoercion { .. }
69            | ExprKind::Repeat { .. }
70            | ExprKind::Assign { .. }
71            | ExprKind::AssignOp { .. }
72            | ExprKind::ThreadLocalRef(_)
73            | ExprKind::OffsetOf { .. }
74            | ExprKind::WrapUnsafeBinder { .. } => Some(Category::Rvalue(RvalueFunc::AsRvalue)),
75
76            ExprKind::ConstBlock { .. }
77            | ExprKind::Literal { .. }
78            | ExprKind::NonHirLiteral { .. }
79            | ExprKind::ZstLiteral { .. }
80            | ExprKind::ConstParam { .. }
81            | ExprKind::StaticRef { .. }
82            | ExprKind::NamedConst { .. } => Some(Category::Constant),
83
84            ExprKind::Loop { .. }
85            | ExprKind::Block { .. }
86            | ExprKind::Break { .. }
87            | ExprKind::Continue { .. }
88            | ExprKind::Return { .. }
89            | ExprKind::Become { .. } =>
90            // FIXME(#27840) these probably want their own
91            // category, like "nonterminating"
92            {
93                Some(Category::Rvalue(RvalueFunc::Into))
94            }
95        }
96    }
97}