1 // Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
11 //! The MIR is translated from some high-level abstract IR
12 //! (HAIR). This section defines the HAIR along with a trait for
13 //! accessing it. The intention is to allow MIR construction to be
14 //! unit-tested and separated from the Rust source and compiler data
17 use rustc
::mir
::{BinOp, BorrowKind, Field, Literal, UnOp}
;
18 use rustc
::hir
::def_id
::DefId
;
19 use rustc
::middle
::region
;
20 use rustc
::ty
::subst
::Substs
;
21 use rustc
::ty
::{AdtDef, ClosureSubsts, Region, Ty, GeneratorInterior}
;
30 pub use self::pattern
::{BindingMode, Pattern, PatternKind, FieldPattern}
;
32 #[derive(Copy, Clone, Debug)]
39 pub fn is_explicit(self) -> bool
{
41 LintLevel
::Inherited
=> false,
42 LintLevel
::Explicit(_
) => true
47 #[derive(Clone, Debug)]
48 pub struct Block
<'tcx
> {
49 pub targeted_by_break
: bool
,
50 pub region_scope
: region
::Scope
,
51 pub opt_destruction_scope
: Option
<region
::Scope
>,
53 pub stmts
: Vec
<StmtRef
<'tcx
>>,
54 pub expr
: Option
<ExprRef
<'tcx
>>,
55 pub safety_mode
: BlockSafety
,
58 #[derive(Copy, Clone, Debug)]
59 pub enum BlockSafety
{
61 ExplicitUnsafe(ast
::NodeId
),
66 #[derive(Clone, Debug)]
67 pub enum StmtRef
<'tcx
> {
68 Mirror(Box
<Stmt
<'tcx
>>),
71 #[derive(Clone, Debug)]
72 pub struct Stmt
<'tcx
> {
73 pub kind
: StmtKind
<'tcx
>,
74 pub opt_destruction_scope
: Option
<region
::Scope
>,
77 #[derive(Clone, Debug)]
78 pub enum StmtKind
<'tcx
> {
80 /// scope for this statement; may be used as lifetime of temporaries
83 /// expression being evaluated in this statement
88 /// scope for variables bound in this let; covers this and
89 /// remaining statements in block
90 remainder_scope
: region
::Scope
,
92 /// scope for the initialization itself; might be used as
93 /// lifetime of temporaries
94 init_scope
: region
::Scope
,
96 /// let <PAT>: ty = ...
97 pattern
: Pattern
<'tcx
>,
99 /// let pat: <TY> = init ...
100 ty
: Option
<hir
::HirId
>,
102 /// let pat: ty = <INIT> ...
103 initializer
: Option
<ExprRef
<'tcx
>>,
105 /// the lint level for this let-statement
106 lint_level
: LintLevel
,
110 /// The Hair trait implementor translates their expressions (`&'tcx H::Expr`)
111 /// into instances of this `Expr` enum. This translation can be done
112 /// basically as lazily or as eagerly as desired: every recursive
113 /// reference to an expression in this enum is an `ExprRef<'tcx>`, which
114 /// may in turn be another instance of this enum (boxed), or else an
115 /// untranslated `&'tcx H::Expr`. Note that instances of `Expr` are very
116 /// shortlived. They are created by `Hair::to_expr`, analyzed and
117 /// converted into MIR, and then discarded.
119 /// If you compare `Expr` to the full compiler AST, you will see it is
120 /// a good bit simpler. In fact, a number of the more straight-forward
121 /// MIR simplifications are already done in the impl of `Hair`. For
122 /// example, method calls and overloaded operators are absent: they are
123 /// expected to be converted into `Expr::Call` instances.
124 #[derive(Clone, Debug)]
125 pub struct Expr
<'tcx
> {
126 /// type of this expression
129 /// lifetime of this expression if it should be spilled into a
130 /// temporary; should be None only if in a constant context
131 pub temp_lifetime
: Option
<region
::Scope
>,
133 /// span of the expression in the source
136 /// kind of expression
137 pub kind
: ExprKind
<'tcx
>,
140 #[derive(Clone, Debug)]
141 pub enum ExprKind
<'tcx
> {
143 region_scope
: region
::Scope
,
144 lint_level
: LintLevel
,
145 value
: ExprRef
<'tcx
>,
148 value
: ExprRef
<'tcx
>,
153 args
: Vec
<ExprRef
<'tcx
>>,
157 }, // NOT overloaded!
162 }, // NOT overloaded!
167 }, // NOT overloaded!
168 // LogicalOp is distinct from BinaryOp because of lazy evaluation of the operands.
172 }, // NOT overloaded!
174 source
: ExprRef
<'tcx
>,
177 source
: ExprRef
<'tcx
>,
178 }, // Use a lexpr to get a vexpr.
180 source
: ExprRef
<'tcx
>,
183 source
: ExprRef
<'tcx
>,
186 source
: ExprRef
<'tcx
>,
189 source
: ExprRef
<'tcx
>,
192 source
: ExprRef
<'tcx
>,
195 condition
: ExprRef
<'tcx
>,
197 otherwise
: Option
<ExprRef
<'tcx
>>,
200 condition
: Option
<ExprRef
<'tcx
>>,
204 discriminant
: ExprRef
<'tcx
>,
205 arms
: Vec
<Arm
<'tcx
>>,
208 body
: &'tcx hir
::Block
,
225 index
: ExprRef
<'tcx
>,
230 /// first argument, used for self in a closure
236 region
: Region
<'tcx
>,
237 borrow_kind
: BorrowKind
,
241 label
: region
::Scope
,
242 value
: Option
<ExprRef
<'tcx
>>,
245 label
: region
::Scope
,
248 value
: Option
<ExprRef
<'tcx
>>,
251 value
: ExprRef
<'tcx
>,
255 fields
: Vec
<ExprRef
<'tcx
>>,
258 fields
: Vec
<ExprRef
<'tcx
>>,
261 adt_def
: &'tcx AdtDef
,
262 variant_index
: usize,
263 substs
: &'tcx Substs
<'tcx
>,
264 fields
: Vec
<FieldExprRef
<'tcx
>>,
265 base
: Option
<FruInfo
<'tcx
>>
269 substs
: ClosureSubsts
<'tcx
>,
270 upvars
: Vec
<ExprRef
<'tcx
>>,
271 interior
: Option
<GeneratorInterior
<'tcx
>>,
274 literal
: Literal
<'tcx
>,
277 asm
: &'tcx hir
::InlineAsm
,
278 outputs
: Vec
<ExprRef
<'tcx
>>,
279 inputs
: Vec
<ExprRef
<'tcx
>>
282 value
: ExprRef
<'tcx
>,
286 #[derive(Clone, Debug)]
287 pub enum ExprRef
<'tcx
> {
288 Hair(&'tcx hir
::Expr
),
289 Mirror(Box
<Expr
<'tcx
>>),
292 #[derive(Clone, Debug)]
293 pub struct FieldExprRef
<'tcx
> {
295 pub expr
: ExprRef
<'tcx
>,
298 #[derive(Clone, Debug)]
299 pub struct FruInfo
<'tcx
> {
300 pub base
: ExprRef
<'tcx
>,
301 pub field_types
: Vec
<Ty
<'tcx
>>
304 #[derive(Clone, Debug)]
305 pub struct Arm
<'tcx
> {
306 pub patterns
: Vec
<Pattern
<'tcx
>>,
307 pub guard
: Option
<ExprRef
<'tcx
>>,
308 pub body
: ExprRef
<'tcx
>,
309 pub lint_level
: LintLevel
,
312 #[derive(Copy, Clone, Debug)]
318 ///////////////////////////////////////////////////////////////////////////
321 /// "Mirroring" is the process of converting from a HIR type into one
322 /// of the HAIR types defined in this file. This is basically a "on
323 /// the fly" desugaring step that hides a lot of the messiness in the
324 /// tcx. For example, the mirror of a `&'tcx hir::Expr` is an
327 /// Mirroring is gradual: when you mirror an outer expression like `e1
328 /// + e2`, the references to the inner expressions `e1` and `e2` are
329 /// `ExprRef<'tcx>` instances, and they may or may not be eagerly
330 /// mirrored. This allows a single AST node from the compiler to
331 /// expand into one or more Hair nodes, which lets the Hair nodes be
333 pub trait Mirror
<'tcx
> {
336 fn make_mirror
<'a
, 'gcx
>(self, cx
: &mut Cx
<'a
, 'gcx
, 'tcx
>) -> Self::Output
;
339 impl<'tcx
> Mirror
<'tcx
> for Expr
<'tcx
> {
340 type Output
= Expr
<'tcx
>;
342 fn make_mirror
<'a
, 'gcx
>(self, _
: &mut Cx
<'a
, 'gcx
, 'tcx
>) -> Expr
<'tcx
> {
347 impl<'tcx
> Mirror
<'tcx
> for ExprRef
<'tcx
> {
348 type Output
= Expr
<'tcx
>;
350 fn make_mirror
<'a
, 'gcx
>(self, hir
: &mut Cx
<'a
, 'gcx
, 'tcx
>) -> Expr
<'tcx
> {
352 ExprRef
::Hair(h
) => h
.make_mirror(hir
),
353 ExprRef
::Mirror(m
) => *m
,
358 impl<'tcx
> Mirror
<'tcx
> for Stmt
<'tcx
> {
359 type Output
= Stmt
<'tcx
>;
361 fn make_mirror
<'a
, 'gcx
>(self, _
: &mut Cx
<'a
, 'gcx
, 'tcx
>) -> Stmt
<'tcx
> {
366 impl<'tcx
> Mirror
<'tcx
> for StmtRef
<'tcx
> {
367 type Output
= Stmt
<'tcx
>;
369 fn make_mirror
<'a
, 'gcx
>(self, _
: &mut Cx
<'a
, 'gcx
, 'tcx
>) -> Stmt
<'tcx
> {
371 StmtRef
::Mirror(m
) => *m
,
376 impl<'tcx
> Mirror
<'tcx
> for Block
<'tcx
> {
377 type Output
= Block
<'tcx
>;
379 fn make_mirror
<'a
, 'gcx
>(self, _
: &mut Cx
<'a
, 'gcx
, 'tcx
>) -> Block
<'tcx
> {