]> git.proxmox.com Git - rustc.git/blob - src/librustc_mir_build/thir/mod.rs
New upstream version 1.47.0+dfsg1
[rustc.git] / src / librustc_mir_build / 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 /// first argument, used for self in a closure
215 SelfRef,
216 Borrow {
217 borrow_kind: BorrowKind,
218 arg: ExprRef<'tcx>,
219 },
220 /// A `&raw [const|mut] $place_expr` raw borrow resulting in type `*[const|mut] T`.
221 AddressOf {
222 mutability: hir::Mutability,
223 arg: ExprRef<'tcx>,
224 },
225 Break {
226 label: region::Scope,
227 value: Option<ExprRef<'tcx>>,
228 },
229 Continue {
230 label: region::Scope,
231 },
232 Return {
233 value: Option<ExprRef<'tcx>>,
234 },
235 Repeat {
236 value: ExprRef<'tcx>,
237 count: &'tcx Const<'tcx>,
238 },
239 Array {
240 fields: Vec<ExprRef<'tcx>>,
241 },
242 Tuple {
243 fields: Vec<ExprRef<'tcx>>,
244 },
245 Adt {
246 adt_def: &'tcx AdtDef,
247 variant_index: VariantIdx,
248 substs: SubstsRef<'tcx>,
249
250 /// Optional user-given substs: for something like `let x =
251 /// Bar::<T> { ... }`.
252 user_ty: Option<Canonical<'tcx, UserType<'tcx>>>,
253
254 fields: Vec<FieldExprRef<'tcx>>,
255 base: Option<FruInfo<'tcx>>,
256 },
257 PlaceTypeAscription {
258 source: ExprRef<'tcx>,
259 /// Type that the user gave to this expression
260 user_ty: Option<Canonical<'tcx, UserType<'tcx>>>,
261 },
262 ValueTypeAscription {
263 source: ExprRef<'tcx>,
264 /// Type that the user gave to this expression
265 user_ty: Option<Canonical<'tcx, UserType<'tcx>>>,
266 },
267 Closure {
268 closure_id: DefId,
269 substs: UpvarSubsts<'tcx>,
270 upvars: Vec<ExprRef<'tcx>>,
271 movability: Option<hir::Movability>,
272 },
273 Literal {
274 literal: &'tcx Const<'tcx>,
275 user_ty: Option<Canonical<'tcx, UserType<'tcx>>>,
276 },
277 /// A literal containing the address of a `static`.
278 ///
279 /// This is only distinguished from `Literal` so that we can register some
280 /// info for diagnostics.
281 StaticRef {
282 literal: &'tcx Const<'tcx>,
283 def_id: DefId,
284 },
285 InlineAsm {
286 template: &'tcx [InlineAsmTemplatePiece],
287 operands: Vec<InlineAsmOperand<'tcx>>,
288 options: InlineAsmOptions,
289 line_spans: &'tcx [Span],
290 },
291 /// An expression taking a reference to a thread local.
292 ThreadLocalRef(DefId),
293 LlvmInlineAsm {
294 asm: &'tcx hir::LlvmInlineAsmInner,
295 outputs: Vec<ExprRef<'tcx>>,
296 inputs: Vec<ExprRef<'tcx>>,
297 },
298 Yield {
299 value: ExprRef<'tcx>,
300 },
301 }
302
303 #[derive(Clone, Debug)]
304 crate enum ExprRef<'tcx> {
305 Thir(&'tcx hir::Expr<'tcx>),
306 Mirror(Box<Expr<'tcx>>),
307 }
308
309 #[derive(Clone, Debug)]
310 crate struct FieldExprRef<'tcx> {
311 crate name: Field,
312 crate expr: ExprRef<'tcx>,
313 }
314
315 #[derive(Clone, Debug)]
316 crate struct FruInfo<'tcx> {
317 crate base: ExprRef<'tcx>,
318 crate field_types: Vec<Ty<'tcx>>,
319 }
320
321 #[derive(Clone, Debug)]
322 crate struct Arm<'tcx> {
323 crate pattern: Pat<'tcx>,
324 crate guard: Option<Guard<'tcx>>,
325 crate body: ExprRef<'tcx>,
326 crate lint_level: LintLevel,
327 crate scope: region::Scope,
328 crate span: Span,
329 }
330
331 #[derive(Clone, Debug)]
332 crate enum Guard<'tcx> {
333 If(ExprRef<'tcx>),
334 }
335
336 #[derive(Copy, Clone, Debug)]
337 crate enum LogicalOp {
338 And,
339 Or,
340 }
341
342 impl<'tcx> ExprRef<'tcx> {
343 crate fn span(&self) -> Span {
344 match self {
345 ExprRef::Thir(expr) => expr.span,
346 ExprRef::Mirror(expr) => expr.span,
347 }
348 }
349 }
350
351 #[derive(Clone, Debug)]
352 crate enum InlineAsmOperand<'tcx> {
353 In {
354 reg: InlineAsmRegOrRegClass,
355 expr: ExprRef<'tcx>,
356 },
357 Out {
358 reg: InlineAsmRegOrRegClass,
359 late: bool,
360 expr: Option<ExprRef<'tcx>>,
361 },
362 InOut {
363 reg: InlineAsmRegOrRegClass,
364 late: bool,
365 expr: ExprRef<'tcx>,
366 },
367 SplitInOut {
368 reg: InlineAsmRegOrRegClass,
369 late: bool,
370 in_expr: ExprRef<'tcx>,
371 out_expr: Option<ExprRef<'tcx>>,
372 },
373 Const {
374 expr: ExprRef<'tcx>,
375 },
376 SymFn {
377 expr: ExprRef<'tcx>,
378 },
379 SymStatic {
380 def_id: DefId,
381 },
382 }
383
384 ///////////////////////////////////////////////////////////////////////////
385 // The Mirror trait
386
387 /// "Mirroring" is the process of converting from a HIR type into one
388 /// of the THIR types defined in this file. This is basically a "on
389 /// the fly" desugaring step that hides a lot of the messiness in the
390 /// tcx. For example, the mirror of a `&'tcx hir::Expr` is an
391 /// `Expr<'tcx>`.
392 ///
393 /// Mirroring is gradual: when you mirror an outer expression like `e1
394 /// + e2`, the references to the inner expressions `e1` and `e2` are
395 /// `ExprRef<'tcx>` instances, and they may or may not be eagerly
396 /// mirrored. This allows a single AST node from the compiler to
397 /// expand into one or more Thir nodes, which lets the Thir nodes be
398 /// simpler.
399 crate trait Mirror<'tcx> {
400 type Output;
401
402 fn make_mirror(self, cx: &mut Cx<'_, 'tcx>) -> Self::Output;
403 }
404
405 impl<'tcx> Mirror<'tcx> for Expr<'tcx> {
406 type Output = Expr<'tcx>;
407
408 fn make_mirror(self, _: &mut Cx<'_, 'tcx>) -> Expr<'tcx> {
409 self
410 }
411 }
412
413 impl<'tcx> Mirror<'tcx> for ExprRef<'tcx> {
414 type Output = Expr<'tcx>;
415
416 fn make_mirror(self, hir: &mut Cx<'_, 'tcx>) -> Expr<'tcx> {
417 match self {
418 ExprRef::Thir(h) => h.make_mirror(hir),
419 ExprRef::Mirror(m) => *m,
420 }
421 }
422 }
423
424 impl<'tcx> Mirror<'tcx> for Stmt<'tcx> {
425 type Output = Stmt<'tcx>;
426
427 fn make_mirror(self, _: &mut Cx<'_, 'tcx>) -> Stmt<'tcx> {
428 self
429 }
430 }
431
432 impl<'tcx> Mirror<'tcx> for StmtRef<'tcx> {
433 type Output = Stmt<'tcx>;
434
435 fn make_mirror(self, _: &mut Cx<'_, 'tcx>) -> Stmt<'tcx> {
436 match self {
437 StmtRef::Mirror(m) => *m,
438 }
439 }
440 }
441
442 impl<'tcx> Mirror<'tcx> for Block<'tcx> {
443 type Output = Block<'tcx>;
444
445 fn make_mirror(self, _: &mut Cx<'_, 'tcx>) -> Block<'tcx> {
446 self
447 }
448 }