]> git.lizzy.rs Git - rust.git/blob - src/librustc_mir/hair/mod.rs
Rollup merge of #65408 - guanqun:remove-rust-optimize, r=Mark-Simulacrum
[rust.git] / src / librustc_mir / hair / mod.rs
1 //! The MIR is built from some high-level abstract IR
2 //! (HAIR). This section defines the HAIR along with a trait for
3 //! accessing it. The intention is to allow MIR construction to be
4 //! unit-tested and separated from the Rust source and compiler data
5 //! structures.
6
7 use rustc::mir::{BinOp, BorrowKind, Field, UnOp};
8 use rustc::hir::def_id::DefId;
9 use rustc::infer::canonical::Canonical;
10 use rustc::middle::region;
11 use rustc::ty::subst::SubstsRef;
12 use rustc::ty::{AdtDef, UpvarSubsts, Ty, Const, UserType};
13 use rustc::ty::adjustment::{PointerCast};
14 use rustc::ty::layout::VariantIdx;
15 use rustc::hir;
16 use syntax_pos::Span;
17 use self::cx::Cx;
18
19 pub mod cx;
20 mod constant;
21
22 pub mod pattern;
23 pub use self::pattern::{BindingMode, Pat, PatKind, PatRange, FieldPat};
24 pub(crate) use self::pattern::PatTyProj;
25
26 mod util;
27
28 #[derive(Copy, Clone, Debug)]
29 pub enum LintLevel {
30     Inherited,
31     Explicit(hir::HirId)
32 }
33
34 #[derive(Clone, Debug)]
35 pub struct Block<'tcx> {
36     pub targeted_by_break: bool,
37     pub region_scope: region::Scope,
38     pub opt_destruction_scope: Option<region::Scope>,
39     pub span: Span,
40     pub stmts: Vec<StmtRef<'tcx>>,
41     pub expr: Option<ExprRef<'tcx>>,
42     pub safety_mode: BlockSafety,
43 }
44
45 #[derive(Copy, Clone, Debug)]
46 pub enum BlockSafety {
47     Safe,
48     ExplicitUnsafe(hir::HirId),
49     PushUnsafe,
50     PopUnsafe
51 }
52
53 #[derive(Clone, Debug)]
54 pub enum StmtRef<'tcx> {
55     Mirror(Box<Stmt<'tcx>>),
56 }
57
58 #[derive(Clone, Debug)]
59 pub struct Stmt<'tcx> {
60     pub kind: StmtKind<'tcx>,
61     pub opt_destruction_scope: Option<region::Scope>,
62 }
63
64 #[derive(Clone, Debug)]
65 pub enum StmtKind<'tcx> {
66     Expr {
67         /// scope for this statement; may be used as lifetime of temporaries
68         scope: region::Scope,
69
70         /// expression being evaluated in this statement
71         expr: ExprRef<'tcx>,
72     },
73
74     Let {
75         /// scope for variables bound in this let; covers this and
76         /// remaining statements in block
77         remainder_scope: region::Scope,
78
79         /// scope for the initialization itself; might be used as
80         /// lifetime of temporaries
81         init_scope: region::Scope,
82
83         /// `let <PAT> = ...`
84         ///
85         /// if a type is included, it is added as an ascription pattern
86         pattern: Pat<'tcx>,
87
88         /// let pat: ty = <INIT> ...
89         initializer: Option<ExprRef<'tcx>>,
90
91         /// the lint level for this let-statement
92         lint_level: LintLevel,
93     },
94 }
95
96 /// The Hair trait implementor lowers their expressions (`&'tcx H::Expr`)
97 /// into instances of this `Expr` enum. This lowering can be done
98 /// basically as lazily or as eagerly as desired: every recursive
99 /// reference to an expression in this enum is an `ExprRef<'tcx>`, which
100 /// may in turn be another instance of this enum (boxed), or else an
101 /// unlowered `&'tcx H::Expr`. Note that instances of `Expr` are very
102 /// short-lived. They are created by `Hair::to_expr`, analyzed and
103 /// converted into MIR, and then discarded.
104 ///
105 /// If you compare `Expr` to the full compiler AST, you will see it is
106 /// a good bit simpler. In fact, a number of the more straight-forward
107 /// MIR simplifications are already done in the impl of `Hair`. For
108 /// example, method calls and overloaded operators are absent: they are
109 /// expected to be converted into `Expr::Call` instances.
110 #[derive(Clone, Debug)]
111 pub struct Expr<'tcx> {
112     /// type of this expression
113     pub ty: Ty<'tcx>,
114
115     /// lifetime of this expression if it should be spilled into a
116     /// temporary; should be None only if in a constant context
117     pub temp_lifetime: Option<region::Scope>,
118
119     /// span of the expression in the source
120     pub span: Span,
121
122     /// kind of expression
123     pub kind: ExprKind<'tcx>,
124 }
125
126 #[derive(Clone, Debug)]
127 pub enum ExprKind<'tcx> {
128     Scope {
129         region_scope: region::Scope,
130         lint_level: LintLevel,
131         value: ExprRef<'tcx>,
132     },
133     Box {
134         value: ExprRef<'tcx>,
135     },
136     Call {
137         ty: Ty<'tcx>,
138         fun: ExprRef<'tcx>,
139         args: Vec<ExprRef<'tcx>>,
140         // Whether this is from a call in HIR, rather than from an overloaded
141         // operator. True for overloaded function call.
142         from_hir_call: bool,
143     },
144     Deref {
145         arg: ExprRef<'tcx>,
146     }, // NOT overloaded!
147     Binary {
148         op: BinOp,
149         lhs: ExprRef<'tcx>,
150         rhs: ExprRef<'tcx>,
151     }, // NOT overloaded!
152     LogicalOp {
153         op: LogicalOp,
154         lhs: ExprRef<'tcx>,
155         rhs: ExprRef<'tcx>,
156     }, // NOT overloaded!
157        // LogicalOp is distinct from BinaryOp because of lazy evaluation of the operands.
158     Unary {
159         op: UnOp,
160         arg: ExprRef<'tcx>,
161     }, // NOT overloaded!
162     Cast {
163         source: ExprRef<'tcx>,
164     },
165     Use {
166         source: ExprRef<'tcx>,
167     }, // Use a lexpr to get a vexpr.
168     NeverToAny {
169         source: ExprRef<'tcx>,
170     },
171     Pointer {
172         cast: PointerCast,
173         source: ExprRef<'tcx>,
174     },
175     Loop {
176         body: ExprRef<'tcx>,
177     },
178     Match {
179         scrutinee: ExprRef<'tcx>,
180         arms: Vec<Arm<'tcx>>,
181     },
182     Block {
183         body: &'tcx hir::Block,
184     },
185     Assign {
186         lhs: ExprRef<'tcx>,
187         rhs: ExprRef<'tcx>,
188     },
189     AssignOp {
190         op: BinOp,
191         lhs: ExprRef<'tcx>,
192         rhs: ExprRef<'tcx>,
193     },
194     Field {
195         lhs: ExprRef<'tcx>,
196         name: Field,
197     },
198     Index {
199         lhs: ExprRef<'tcx>,
200         index: ExprRef<'tcx>,
201     },
202     VarRef {
203         id: hir::HirId,
204     },
205     /// first argument, used for self in a closure
206     SelfRef,
207     StaticRef {
208         id: DefId,
209     },
210     Borrow {
211         borrow_kind: BorrowKind,
212         arg: ExprRef<'tcx>,
213     },
214     Break {
215         label: region::Scope,
216         value: Option<ExprRef<'tcx>>,
217     },
218     Continue {
219         label: region::Scope,
220     },
221     Return {
222         value: Option<ExprRef<'tcx>>,
223     },
224     Repeat {
225         value: ExprRef<'tcx>,
226         count: u64,
227     },
228     Array {
229         fields: Vec<ExprRef<'tcx>>,
230     },
231     Tuple {
232         fields: Vec<ExprRef<'tcx>>,
233     },
234     Adt {
235         adt_def: &'tcx AdtDef,
236         variant_index: VariantIdx,
237         substs: SubstsRef<'tcx>,
238
239         /// Optional user-given substs: for something like `let x =
240         /// Bar::<T> { ... }`.
241         user_ty: Option<Canonical<'tcx, UserType<'tcx>>>,
242
243         fields: Vec<FieldExprRef<'tcx>>,
244         base: Option<FruInfo<'tcx>>
245     },
246     PlaceTypeAscription {
247         source: ExprRef<'tcx>,
248         /// Type that the user gave to this expression
249         user_ty: Option<Canonical<'tcx, UserType<'tcx>>>,
250     },
251     ValueTypeAscription {
252         source: ExprRef<'tcx>,
253         /// Type that the user gave to this expression
254         user_ty: Option<Canonical<'tcx, UserType<'tcx>>>,
255     },
256     Closure {
257         closure_id: DefId,
258         substs: UpvarSubsts<'tcx>,
259         upvars: Vec<ExprRef<'tcx>>,
260         movability: Option<hir::GeneratorMovability>,
261     },
262     Literal {
263         literal: &'tcx Const<'tcx>,
264         user_ty: Option<Canonical<'tcx, UserType<'tcx>>>,
265     },
266     InlineAsm {
267         asm: &'tcx hir::InlineAsm,
268         outputs: Vec<ExprRef<'tcx>>,
269         inputs: Vec<ExprRef<'tcx>>
270     },
271     Yield {
272         value: ExprRef<'tcx>,
273     },
274 }
275
276 #[derive(Clone, Debug)]
277 pub enum ExprRef<'tcx> {
278     Hair(&'tcx hir::Expr),
279     Mirror(Box<Expr<'tcx>>),
280 }
281
282 #[derive(Clone, Debug)]
283 pub struct FieldExprRef<'tcx> {
284     pub name: Field,
285     pub expr: ExprRef<'tcx>,
286 }
287
288 #[derive(Clone, Debug)]
289 pub struct FruInfo<'tcx> {
290     pub base: ExprRef<'tcx>,
291     pub field_types: Vec<Ty<'tcx>>
292 }
293
294 #[derive(Clone, Debug)]
295 pub struct Arm<'tcx> {
296     pub pattern: Pat<'tcx>,
297     pub guard: Option<Guard<'tcx>>,
298     pub body: ExprRef<'tcx>,
299     pub lint_level: LintLevel,
300     pub scope: region::Scope,
301     pub span: Span,
302 }
303
304 impl Arm<'tcx> {
305     // HACK(or_patterns; Centril | dlrobertson): Remove this and
306     // correctly handle each case in which this method is used.
307     pub fn top_pats_hack(&self) -> &[Pat<'tcx>] {
308         match &*self.pattern.kind {
309             PatKind::Or { pats } => pats,
310             _ => std::slice::from_ref(&self.pattern),
311         }
312     }
313 }
314
315 #[derive(Clone, Debug)]
316 pub enum Guard<'tcx> {
317     If(ExprRef<'tcx>),
318 }
319
320 #[derive(Copy, Clone, Debug)]
321 pub enum LogicalOp {
322     And,
323     Or,
324 }
325
326 impl<'tcx> ExprRef<'tcx> {
327     pub fn span(&self) -> Span {
328         match self {
329             ExprRef::Hair(expr) => expr.span,
330             ExprRef::Mirror(expr) => expr.span,
331         }
332     }
333 }
334
335 ///////////////////////////////////////////////////////////////////////////
336 // The Mirror trait
337
338 /// "Mirroring" is the process of converting from a HIR type into one
339 /// of the HAIR types defined in this file. This is basically a "on
340 /// the fly" desugaring step that hides a lot of the messiness in the
341 /// tcx. For example, the mirror of a `&'tcx hir::Expr` is an
342 /// `Expr<'tcx>`.
343 ///
344 /// Mirroring is gradual: when you mirror an outer expression like `e1
345 /// + e2`, the references to the inner expressions `e1` and `e2` are
346 /// `ExprRef<'tcx>` instances, and they may or may not be eagerly
347 /// mirrored. This allows a single AST node from the compiler to
348 /// expand into one or more Hair nodes, which lets the Hair nodes be
349 /// simpler.
350 pub trait Mirror<'tcx> {
351     type Output;
352
353     fn make_mirror(self, cx: &mut Cx<'_, 'tcx>) -> Self::Output;
354 }
355
356 impl<'tcx> Mirror<'tcx> for Expr<'tcx> {
357     type Output = Expr<'tcx>;
358
359     fn make_mirror(self, _: &mut Cx<'_, 'tcx>) -> Expr<'tcx> {
360         self
361     }
362 }
363
364 impl<'tcx> Mirror<'tcx> for ExprRef<'tcx> {
365     type Output = Expr<'tcx>;
366
367     fn make_mirror(self, hir: &mut Cx<'a, 'tcx>) -> Expr<'tcx> {
368         match self {
369             ExprRef::Hair(h) => h.make_mirror(hir),
370             ExprRef::Mirror(m) => *m,
371         }
372     }
373 }
374
375 impl<'tcx> Mirror<'tcx> for Stmt<'tcx> {
376     type Output = Stmt<'tcx>;
377
378     fn make_mirror(self, _: &mut Cx<'_, 'tcx>) -> Stmt<'tcx> {
379         self
380     }
381 }
382
383 impl<'tcx> Mirror<'tcx> for StmtRef<'tcx> {
384     type Output = Stmt<'tcx>;
385
386     fn make_mirror(self, _: &mut Cx<'_, 'tcx>) -> Stmt<'tcx> {
387         match self {
388             StmtRef::Mirror(m) => *m,
389         }
390     }
391 }
392
393 impl<'tcx> Mirror<'tcx> for Block<'tcx> {
394     type Output = Block<'tcx>;
395
396     fn make_mirror(self, _: &mut Cx<'_, 'tcx>) -> Block<'tcx> {
397         self
398     }
399 }