]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_mir_build/src/thir/mod.rs
Remove THIR::ExprKind::SelfRef
[rust.git] / compiler / rustc_mir_build / src / thir / mod.rs
1 //! The MIR is built from some typed high-level IR
2 //! (THIR). This section defines the THIR 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 self::cx::Cx;
8 use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
9 use rustc_hir as hir;
10 use rustc_hir::def_id::DefId;
11 use rustc_middle::infer::canonical::Canonical;
12 use rustc_middle::middle::region;
13 use rustc_middle::mir::{BinOp, BorrowKind, Field, UnOp};
14 use rustc_middle::ty::adjustment::PointerCast;
15 use rustc_middle::ty::subst::SubstsRef;
16 use rustc_middle::ty::{AdtDef, Const, Ty, UpvarSubsts, UserType};
17 use rustc_span::Span;
18 use rustc_target::abi::VariantIdx;
19 use rustc_target::asm::InlineAsmRegOrRegClass;
20
21 crate mod constant;
22 crate mod cx;
23
24 crate mod pattern;
25 crate use self::pattern::PatTyProj;
26 crate use self::pattern::{BindingMode, FieldPat, Pat, PatKind, PatRange};
27
28 mod util;
29
30 #[derive(Copy, Clone, Debug)]
31 crate enum LintLevel {
32     Inherited,
33     Explicit(hir::HirId),
34 }
35
36 #[derive(Clone, Debug)]
37 crate struct Block<'tcx> {
38     crate targeted_by_break: bool,
39     crate region_scope: region::Scope,
40     crate opt_destruction_scope: Option<region::Scope>,
41     crate span: Span,
42     crate stmts: Vec<StmtRef<'tcx>>,
43     crate expr: Option<ExprRef<'tcx>>,
44     crate safety_mode: BlockSafety,
45 }
46
47 #[derive(Copy, Clone, Debug)]
48 crate enum BlockSafety {
49     Safe,
50     ExplicitUnsafe(hir::HirId),
51     PushUnsafe,
52     PopUnsafe,
53 }
54
55 #[derive(Clone, Debug)]
56 crate enum StmtRef<'tcx> {
57     Mirror(Box<Stmt<'tcx>>),
58 }
59
60 #[derive(Clone, Debug)]
61 crate struct Stmt<'tcx> {
62     crate kind: StmtKind<'tcx>,
63     crate opt_destruction_scope: Option<region::Scope>,
64 }
65
66 #[derive(Clone, Debug)]
67 crate enum StmtKind<'tcx> {
68     Expr {
69         /// scope for this statement; may be used as lifetime of temporaries
70         scope: region::Scope,
71
72         /// expression being evaluated in this statement
73         expr: ExprRef<'tcx>,
74     },
75
76     Let {
77         /// scope for variables bound in this let; covers this and
78         /// remaining statements in block
79         remainder_scope: region::Scope,
80
81         /// scope for the initialization itself; might be used as
82         /// lifetime of temporaries
83         init_scope: region::Scope,
84
85         /// `let <PAT> = ...`
86         ///
87         /// if a type is included, it is added as an ascription pattern
88         pattern: Pat<'tcx>,
89
90         /// let pat: ty = <INIT> ...
91         initializer: Option<ExprRef<'tcx>>,
92
93         /// the lint level for this let-statement
94         lint_level: LintLevel,
95     },
96 }
97
98 // `Expr` is used a lot. Make sure it doesn't unintentionally get bigger.
99 #[cfg(target_arch = "x86_64")]
100 rustc_data_structures::static_assert_size!(Expr<'_>, 168);
101
102 /// The Thir trait implementor lowers their expressions (`&'tcx H::Expr`)
103 /// into instances of this `Expr` enum. This lowering can be done
104 /// basically as lazily or as eagerly as desired: every recursive
105 /// reference to an expression in this enum is an `ExprRef<'tcx>`, which
106 /// may in turn be another instance of this enum (boxed), or else an
107 /// unlowered `&'tcx H::Expr`. Note that instances of `Expr` are very
108 /// short-lived. They are created by `Thir::to_expr`, analyzed and
109 /// converted into MIR, and then discarded.
110 ///
111 /// If you compare `Expr` to the full compiler AST, you will see it is
112 /// a good bit simpler. In fact, a number of the more straight-forward
113 /// MIR simplifications are already done in the impl of `Thir`. For
114 /// example, method calls and overloaded operators are absent: they are
115 /// expected to be converted into `Expr::Call` instances.
116 #[derive(Clone, Debug)]
117 crate struct Expr<'tcx> {
118     /// type of this expression
119     crate ty: Ty<'tcx>,
120
121     /// lifetime of this expression if it should be spilled into a
122     /// temporary; should be None only if in a constant context
123     crate temp_lifetime: Option<region::Scope>,
124
125     /// span of the expression in the source
126     crate span: Span,
127
128     /// kind of expression
129     crate kind: ExprKind<'tcx>,
130 }
131
132 #[derive(Clone, Debug)]
133 crate enum ExprKind<'tcx> {
134     Scope {
135         region_scope: region::Scope,
136         lint_level: LintLevel,
137         value: ExprRef<'tcx>,
138     },
139     Box {
140         value: ExprRef<'tcx>,
141     },
142     Call {
143         ty: Ty<'tcx>,
144         fun: ExprRef<'tcx>,
145         args: Vec<ExprRef<'tcx>>,
146         // Whether this is from a call in HIR, rather than from an overloaded
147         // operator. True for overloaded function call.
148         from_hir_call: bool,
149         /// This `Span` is the span of the function, without the dot and receiver
150         /// (e.g. `foo(a, b)` in `x.foo(a, b)`
151         fn_span: Span,
152     },
153     Deref {
154         arg: ExprRef<'tcx>,
155     }, // NOT overloaded!
156     Binary {
157         op: BinOp,
158         lhs: ExprRef<'tcx>,
159         rhs: ExprRef<'tcx>,
160     }, // NOT overloaded!
161     LogicalOp {
162         op: LogicalOp,
163         lhs: ExprRef<'tcx>,
164         rhs: ExprRef<'tcx>,
165     }, // NOT overloaded!
166     // LogicalOp is distinct from BinaryOp because of lazy evaluation of the operands.
167     Unary {
168         op: UnOp,
169         arg: ExprRef<'tcx>,
170     }, // NOT overloaded!
171     Cast {
172         source: ExprRef<'tcx>,
173     },
174     Use {
175         source: ExprRef<'tcx>,
176     }, // Use a lexpr to get a vexpr.
177     NeverToAny {
178         source: ExprRef<'tcx>,
179     },
180     Pointer {
181         cast: PointerCast,
182         source: ExprRef<'tcx>,
183     },
184     Loop {
185         body: ExprRef<'tcx>,
186     },
187     Match {
188         scrutinee: ExprRef<'tcx>,
189         arms: Vec<Arm<'tcx>>,
190     },
191     Block {
192         body: &'tcx hir::Block<'tcx>,
193     },
194     Assign {
195         lhs: ExprRef<'tcx>,
196         rhs: ExprRef<'tcx>,
197     },
198     AssignOp {
199         op: BinOp,
200         lhs: ExprRef<'tcx>,
201         rhs: ExprRef<'tcx>,
202     },
203     Field {
204         lhs: ExprRef<'tcx>,
205         name: Field,
206     },
207     Index {
208         lhs: ExprRef<'tcx>,
209         index: ExprRef<'tcx>,
210     },
211     VarRef {
212         id: hir::HirId,
213     },
214     /// Used to represent upvars mentioned in a closure/generator
215     UpvarRef {
216         /// DefId of the closure/generator
217         closure_def_id: DefId,
218
219         /// HirId of the root variable
220         var_hir_id: hir::HirId,
221     },
222     Borrow {
223         borrow_kind: BorrowKind,
224         arg: ExprRef<'tcx>,
225     },
226     /// A `&raw [const|mut] $place_expr` raw borrow resulting in type `*[const|mut] T`.
227     AddressOf {
228         mutability: hir::Mutability,
229         arg: ExprRef<'tcx>,
230     },
231     Break {
232         label: region::Scope,
233         value: Option<ExprRef<'tcx>>,
234     },
235     Continue {
236         label: region::Scope,
237     },
238     Return {
239         value: Option<ExprRef<'tcx>>,
240     },
241     ConstBlock {
242         value: &'tcx Const<'tcx>,
243     },
244     Repeat {
245         value: ExprRef<'tcx>,
246         count: &'tcx Const<'tcx>,
247     },
248     Array {
249         fields: Vec<ExprRef<'tcx>>,
250     },
251     Tuple {
252         fields: Vec<ExprRef<'tcx>>,
253     },
254     Adt {
255         adt_def: &'tcx AdtDef,
256         variant_index: VariantIdx,
257         substs: SubstsRef<'tcx>,
258
259         /// Optional user-given substs: for something like `let x =
260         /// Bar::<T> { ... }`.
261         user_ty: Option<Canonical<'tcx, UserType<'tcx>>>,
262
263         fields: Vec<FieldExprRef<'tcx>>,
264         base: Option<FruInfo<'tcx>>,
265     },
266     PlaceTypeAscription {
267         source: ExprRef<'tcx>,
268         /// Type that the user gave to this expression
269         user_ty: Option<Canonical<'tcx, UserType<'tcx>>>,
270     },
271     ValueTypeAscription {
272         source: ExprRef<'tcx>,
273         /// Type that the user gave to this expression
274         user_ty: Option<Canonical<'tcx, UserType<'tcx>>>,
275     },
276     Closure {
277         closure_id: DefId,
278         substs: UpvarSubsts<'tcx>,
279         upvars: Vec<ExprRef<'tcx>>,
280         movability: Option<hir::Movability>,
281     },
282     Literal {
283         literal: &'tcx Const<'tcx>,
284         user_ty: Option<Canonical<'tcx, UserType<'tcx>>>,
285         /// The `DefId` of the `const` item this literal
286         /// was produced from, if this is not a user-written
287         /// literal value.
288         const_id: Option<DefId>,
289     },
290     /// A literal containing the address of a `static`.
291     ///
292     /// This is only distinguished from `Literal` so that we can register some
293     /// info for diagnostics.
294     StaticRef {
295         literal: &'tcx Const<'tcx>,
296         def_id: DefId,
297     },
298     InlineAsm {
299         template: &'tcx [InlineAsmTemplatePiece],
300         operands: Vec<InlineAsmOperand<'tcx>>,
301         options: InlineAsmOptions,
302         line_spans: &'tcx [Span],
303     },
304     /// An expression taking a reference to a thread local.
305     ThreadLocalRef(DefId),
306     LlvmInlineAsm {
307         asm: &'tcx hir::LlvmInlineAsmInner,
308         outputs: Vec<ExprRef<'tcx>>,
309         inputs: Vec<ExprRef<'tcx>>,
310     },
311     Yield {
312         value: ExprRef<'tcx>,
313     },
314 }
315
316 #[derive(Clone, Debug)]
317 crate enum ExprRef<'tcx> {
318     Thir(&'tcx hir::Expr<'tcx>),
319     Mirror(Box<Expr<'tcx>>),
320 }
321
322 #[derive(Clone, Debug)]
323 crate struct FieldExprRef<'tcx> {
324     crate name: Field,
325     crate expr: ExprRef<'tcx>,
326 }
327
328 #[derive(Clone, Debug)]
329 crate struct FruInfo<'tcx> {
330     crate base: ExprRef<'tcx>,
331     crate field_types: Vec<Ty<'tcx>>,
332 }
333
334 #[derive(Clone, Debug)]
335 crate struct Arm<'tcx> {
336     crate pattern: Pat<'tcx>,
337     crate guard: Option<Guard<'tcx>>,
338     crate body: ExprRef<'tcx>,
339     crate lint_level: LintLevel,
340     crate scope: region::Scope,
341     crate span: Span,
342 }
343
344 #[derive(Clone, Debug)]
345 crate enum Guard<'tcx> {
346     If(ExprRef<'tcx>),
347 }
348
349 #[derive(Copy, Clone, Debug)]
350 crate enum LogicalOp {
351     And,
352     Or,
353 }
354
355 impl<'tcx> ExprRef<'tcx> {
356     crate fn span(&self) -> Span {
357         match self {
358             ExprRef::Thir(expr) => expr.span,
359             ExprRef::Mirror(expr) => expr.span,
360         }
361     }
362 }
363
364 #[derive(Clone, Debug)]
365 crate enum InlineAsmOperand<'tcx> {
366     In {
367         reg: InlineAsmRegOrRegClass,
368         expr: ExprRef<'tcx>,
369     },
370     Out {
371         reg: InlineAsmRegOrRegClass,
372         late: bool,
373         expr: Option<ExprRef<'tcx>>,
374     },
375     InOut {
376         reg: InlineAsmRegOrRegClass,
377         late: bool,
378         expr: ExprRef<'tcx>,
379     },
380     SplitInOut {
381         reg: InlineAsmRegOrRegClass,
382         late: bool,
383         in_expr: ExprRef<'tcx>,
384         out_expr: Option<ExprRef<'tcx>>,
385     },
386     Const {
387         expr: ExprRef<'tcx>,
388     },
389     SymFn {
390         expr: ExprRef<'tcx>,
391     },
392     SymStatic {
393         def_id: DefId,
394     },
395 }
396
397 ///////////////////////////////////////////////////////////////////////////
398 // The Mirror trait
399
400 /// "Mirroring" is the process of converting from a HIR type into one
401 /// of the THIR types defined in this file. This is basically a "on
402 /// the fly" desugaring step that hides a lot of the messiness in the
403 /// tcx. For example, the mirror of a `&'tcx hir::Expr` is an
404 /// `Expr<'tcx>`.
405 ///
406 /// Mirroring is gradual: when you mirror an outer expression like `e1
407 /// + e2`, the references to the inner expressions `e1` and `e2` are
408 /// `ExprRef<'tcx>` instances, and they may or may not be eagerly
409 /// mirrored. This allows a single AST node from the compiler to
410 /// expand into one or more Thir nodes, which lets the Thir nodes be
411 /// simpler.
412 crate trait Mirror<'tcx> {
413     type Output;
414
415     fn make_mirror(self, cx: &mut Cx<'_, 'tcx>) -> Self::Output;
416 }
417
418 impl<'tcx> Mirror<'tcx> for Expr<'tcx> {
419     type Output = Expr<'tcx>;
420
421     fn make_mirror(self, _: &mut Cx<'_, 'tcx>) -> Expr<'tcx> {
422         self
423     }
424 }
425
426 impl<'tcx> Mirror<'tcx> for ExprRef<'tcx> {
427     type Output = Expr<'tcx>;
428
429     fn make_mirror(self, hir: &mut Cx<'_, 'tcx>) -> Expr<'tcx> {
430         match self {
431             ExprRef::Thir(h) => h.make_mirror(hir),
432             ExprRef::Mirror(m) => *m,
433         }
434     }
435 }
436
437 impl<'tcx> Mirror<'tcx> for Stmt<'tcx> {
438     type Output = Stmt<'tcx>;
439
440     fn make_mirror(self, _: &mut Cx<'_, 'tcx>) -> Stmt<'tcx> {
441         self
442     }
443 }
444
445 impl<'tcx> Mirror<'tcx> for StmtRef<'tcx> {
446     type Output = Stmt<'tcx>;
447
448     fn make_mirror(self, _: &mut Cx<'_, 'tcx>) -> Stmt<'tcx> {
449         match self {
450             StmtRef::Mirror(m) => *m,
451         }
452     }
453 }
454
455 impl<'tcx> Mirror<'tcx> for Block<'tcx> {
456     type Output = Block<'tcx>;
457
458     fn make_mirror(self, _: &mut Cx<'_, 'tcx>) -> Block<'tcx> {
459         self
460     }
461 }