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
8 use rustc_ast
::{InlineAsmOptions, InlineAsmTemplatePiece}
;
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}
;
18 use rustc_target
::abi
::VariantIdx
;
19 use rustc_target
::asm
::InlineAsmRegOrRegClass
;
25 crate use self::pattern
::PatTyProj
;
26 crate use self::pattern
::{BindingMode, FieldPat, Pat, PatKind, PatRange}
;
30 #[derive(Copy, Clone, Debug)]
31 crate enum LintLevel
{
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
>,
42 crate stmts
: Vec
<StmtRef
<'tcx
>>,
43 crate expr
: Option
<ExprRef
<'tcx
>>,
44 crate safety_mode
: BlockSafety
,
47 #[derive(Copy, Clone, Debug)]
48 crate enum BlockSafety
{
50 ExplicitUnsafe(hir
::HirId
),
55 #[derive(Clone, Debug)]
56 crate enum StmtRef
<'tcx
> {
57 Mirror(Box
<Stmt
<'tcx
>>),
60 #[derive(Clone, Debug)]
61 crate struct Stmt
<'tcx
> {
62 crate kind
: StmtKind
<'tcx
>,
63 crate opt_destruction_scope
: Option
<region
::Scope
>,
66 #[derive(Clone, Debug)]
67 crate enum StmtKind
<'tcx
> {
69 /// scope for this statement; may be used as lifetime of temporaries
72 /// expression being evaluated in this statement
77 /// scope for variables bound in this let; covers this and
78 /// remaining statements in block
79 remainder_scope
: region
::Scope
,
81 /// scope for the initialization itself; might be used as
82 /// lifetime of temporaries
83 init_scope
: region
::Scope
,
87 /// if a type is included, it is added as an ascription pattern
90 /// let pat: ty = <INIT> ...
91 initializer
: Option
<ExprRef
<'tcx
>>,
93 /// the lint level for this let-statement
94 lint_level
: LintLevel
,
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);
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.
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
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
>,
125 /// span of the expression in the source
128 /// kind of expression
129 crate kind
: ExprKind
<'tcx
>,
132 #[derive(Clone, Debug)]
133 crate enum ExprKind
<'tcx
> {
135 region_scope
: region
::Scope
,
136 lint_level
: LintLevel
,
137 value
: ExprRef
<'tcx
>,
140 value
: 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.
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)`
155 }, // NOT overloaded!
160 }, // NOT overloaded!
165 }, // NOT overloaded!
166 // LogicalOp is distinct from BinaryOp because of lazy evaluation of the operands.
170 }, // NOT overloaded!
172 source
: ExprRef
<'tcx
>,
175 source
: ExprRef
<'tcx
>,
176 }, // Use a lexpr to get a vexpr.
178 source
: ExprRef
<'tcx
>,
182 source
: ExprRef
<'tcx
>,
188 scrutinee
: ExprRef
<'tcx
>,
189 arms
: Vec
<Arm
<'tcx
>>,
192 body
: &'tcx hir
::Block
<'tcx
>,
209 index
: ExprRef
<'tcx
>,
214 /// first argument, used for self in a closure
217 borrow_kind
: BorrowKind
,
220 /// A `&raw [const|mut] $place_expr` raw borrow resulting in type `*[const|mut] T`.
222 mutability
: hir
::Mutability
,
226 label
: region
::Scope
,
227 value
: Option
<ExprRef
<'tcx
>>,
230 label
: region
::Scope
,
233 value
: Option
<ExprRef
<'tcx
>>,
236 value
: ExprRef
<'tcx
>,
237 count
: &'tcx Const
<'tcx
>,
240 fields
: Vec
<ExprRef
<'tcx
>>,
243 fields
: Vec
<ExprRef
<'tcx
>>,
246 adt_def
: &'tcx AdtDef
,
247 variant_index
: VariantIdx
,
248 substs
: SubstsRef
<'tcx
>,
250 /// Optional user-given substs: for something like `let x =
251 /// Bar::<T> { ... }`.
252 user_ty
: Option
<Canonical
<'tcx
, UserType
<'tcx
>>>,
254 fields
: Vec
<FieldExprRef
<'tcx
>>,
255 base
: Option
<FruInfo
<'tcx
>>,
257 PlaceTypeAscription
{
258 source
: ExprRef
<'tcx
>,
259 /// Type that the user gave to this expression
260 user_ty
: Option
<Canonical
<'tcx
, UserType
<'tcx
>>>,
262 ValueTypeAscription
{
263 source
: ExprRef
<'tcx
>,
264 /// Type that the user gave to this expression
265 user_ty
: Option
<Canonical
<'tcx
, UserType
<'tcx
>>>,
269 substs
: UpvarSubsts
<'tcx
>,
270 upvars
: Vec
<ExprRef
<'tcx
>>,
271 movability
: Option
<hir
::Movability
>,
274 literal
: &'tcx Const
<'tcx
>,
275 user_ty
: Option
<Canonical
<'tcx
, UserType
<'tcx
>>>,
277 /// A literal containing the address of a `static`.
279 /// This is only distinguished from `Literal` so that we can register some
280 /// info for diagnostics.
282 literal
: &'tcx Const
<'tcx
>,
286 template
: &'tcx
[InlineAsmTemplatePiece
],
287 operands
: Vec
<InlineAsmOperand
<'tcx
>>,
288 options
: InlineAsmOptions
,
289 line_spans
: &'tcx
[Span
],
291 /// An expression taking a reference to a thread local.
292 ThreadLocalRef(DefId
),
294 asm
: &'tcx hir
::LlvmInlineAsmInner
,
295 outputs
: Vec
<ExprRef
<'tcx
>>,
296 inputs
: Vec
<ExprRef
<'tcx
>>,
299 value
: ExprRef
<'tcx
>,
303 #[derive(Clone, Debug)]
304 crate enum ExprRef
<'tcx
> {
305 Thir(&'tcx hir
::Expr
<'tcx
>),
306 Mirror(Box
<Expr
<'tcx
>>),
309 #[derive(Clone, Debug)]
310 crate struct FieldExprRef
<'tcx
> {
312 crate expr
: ExprRef
<'tcx
>,
315 #[derive(Clone, Debug)]
316 crate struct FruInfo
<'tcx
> {
317 crate base
: ExprRef
<'tcx
>,
318 crate field_types
: Vec
<Ty
<'tcx
>>,
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
,
331 #[derive(Clone, Debug)]
332 crate enum Guard
<'tcx
> {
336 #[derive(Copy, Clone, Debug)]
337 crate enum LogicalOp
{
342 impl<'tcx
> ExprRef
<'tcx
> {
343 crate fn span(&self) -> Span
{
345 ExprRef
::Thir(expr
) => expr
.span
,
346 ExprRef
::Mirror(expr
) => expr
.span
,
351 #[derive(Clone, Debug)]
352 crate enum InlineAsmOperand
<'tcx
> {
354 reg
: InlineAsmRegOrRegClass
,
358 reg
: InlineAsmRegOrRegClass
,
360 expr
: Option
<ExprRef
<'tcx
>>,
363 reg
: InlineAsmRegOrRegClass
,
368 reg
: InlineAsmRegOrRegClass
,
370 in_expr
: ExprRef
<'tcx
>,
371 out_expr
: Option
<ExprRef
<'tcx
>>,
384 ///////////////////////////////////////////////////////////////////////////
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
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
399 crate trait Mirror
<'tcx
> {
402 fn make_mirror(self, cx
: &mut Cx
<'_
, 'tcx
>) -> Self::Output
;
405 impl<'tcx
> Mirror
<'tcx
> for Expr
<'tcx
> {
406 type Output
= Expr
<'tcx
>;
408 fn make_mirror(self, _
: &mut Cx
<'_
, 'tcx
>) -> Expr
<'tcx
> {
413 impl<'tcx
> Mirror
<'tcx
> for ExprRef
<'tcx
> {
414 type Output
= Expr
<'tcx
>;
416 fn make_mirror(self, hir
: &mut Cx
<'_
, 'tcx
>) -> Expr
<'tcx
> {
418 ExprRef
::Thir(h
) => h
.make_mirror(hir
),
419 ExprRef
::Mirror(m
) => *m
,
424 impl<'tcx
> Mirror
<'tcx
> for Stmt
<'tcx
> {
425 type Output
= Stmt
<'tcx
>;
427 fn make_mirror(self, _
: &mut Cx
<'_
, 'tcx
>) -> Stmt
<'tcx
> {
432 impl<'tcx
> Mirror
<'tcx
> for StmtRef
<'tcx
> {
433 type Output
= Stmt
<'tcx
>;
435 fn make_mirror(self, _
: &mut Cx
<'_
, 'tcx
>) -> Stmt
<'tcx
> {
437 StmtRef
::Mirror(m
) => *m
,
442 impl<'tcx
> Mirror
<'tcx
> for Block
<'tcx
> {
443 type Output
= Block
<'tcx
>;
445 fn make_mirror(self, _
: &mut Cx
<'_
, 'tcx
>) -> Block
<'tcx
> {