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, TypedConstVal}
;
18 use rustc
::hir
::def_id
::DefId
;
19 use rustc
::middle
::region
::CodeExtent
;
20 use rustc
::ty
::subst
::Substs
;
21 use rustc
::ty
::{self, AdtDef, ClosureSubsts, Region, Ty}
;
29 pub use rustc_const_eval
::pattern
::{BindingMode, Pattern, PatternKind, FieldPattern}
;
31 #[derive(Clone, Debug)]
32 pub struct Block
<'tcx
> {
33 pub extent
: CodeExtent
,
35 pub stmts
: Vec
<StmtRef
<'tcx
>>,
36 pub expr
: Option
<ExprRef
<'tcx
>>,
39 #[derive(Clone, Debug)]
40 pub enum StmtRef
<'tcx
> {
41 Mirror(Box
<Stmt
<'tcx
>>),
44 #[derive(Clone, Debug)]
45 pub struct Stmt
<'tcx
> {
47 pub kind
: StmtKind
<'tcx
>,
50 #[derive(Clone, Debug)]
51 pub enum StmtKind
<'tcx
> {
53 /// scope for this statement; may be used as lifetime of temporaries
56 /// expression being evaluated in this statement
61 /// scope for variables bound in this let; covers this and
62 /// remaining statements in block
63 remainder_scope
: CodeExtent
,
65 /// scope for the initialization itself; might be used as
66 /// lifetime of temporaries
67 init_scope
: CodeExtent
,
70 pattern
: Pattern
<'tcx
>,
72 /// let pat = <INIT> ...
73 initializer
: Option
<ExprRef
<'tcx
>>
77 /// The Hair trait implementor translates their expressions (`&'tcx H::Expr`)
78 /// into instances of this `Expr` enum. This translation can be done
79 /// basically as lazilly or as eagerly as desired: every recursive
80 /// reference to an expression in this enum is an `ExprRef<'tcx>`, which
81 /// may in turn be another instance of this enum (boxed), or else an
82 /// untranslated `&'tcx H::Expr`. Note that instances of `Expr` are very
83 /// shortlived. They are created by `Hair::to_expr`, analyzed and
84 /// converted into MIR, and then discarded.
86 /// If you compare `Expr` to the full compiler AST, you will see it is
87 /// a good bit simpler. In fact, a number of the more straight-forward
88 /// MIR simplifications are already done in the impl of `Hair`. For
89 /// example, method calls and overloaded operators are absent: they are
90 /// expected to be converted into `Expr::Call` instances.
91 #[derive(Clone, Debug)]
92 pub struct Expr
<'tcx
> {
93 /// type of this expression
96 /// lifetime of this expression if it should be spilled into a
97 /// temporary; should be None only if in a constant context
98 pub temp_lifetime
: Option
<CodeExtent
>,
100 /// span of the expression in the source
103 /// kind of expression
104 pub kind
: ExprKind
<'tcx
>,
107 #[derive(Clone, Debug)]
108 pub enum ExprKind
<'tcx
> {
111 value
: ExprRef
<'tcx
>,
114 value
: ExprRef
<'tcx
>,
115 value_extents
: CodeExtent
,
120 args
: Vec
<ExprRef
<'tcx
>>,
124 }, // NOT overloaded!
129 }, // NOT overloaded!
138 }, // NOT overloaded!
140 source
: ExprRef
<'tcx
>,
143 source
: ExprRef
<'tcx
>,
144 }, // Use a lexpr to get a vexpr.
146 source
: ExprRef
<'tcx
>,
149 source
: ExprRef
<'tcx
>,
152 source
: ExprRef
<'tcx
>,
155 source
: ExprRef
<'tcx
>,
158 condition
: ExprRef
<'tcx
>,
160 otherwise
: Option
<ExprRef
<'tcx
>>,
163 condition
: Option
<ExprRef
<'tcx
>>,
167 discriminant
: ExprRef
<'tcx
>,
168 arms
: Vec
<Arm
<'tcx
>>,
171 body
: &'tcx hir
::Block
,
188 index
: ExprRef
<'tcx
>,
193 /// first argument, used for self in a closure
199 region
: &'tcx Region
,
200 borrow_kind
: BorrowKind
,
204 label
: Option
<CodeExtent
>,
207 label
: Option
<CodeExtent
>,
210 value
: Option
<ExprRef
<'tcx
>>,
213 value
: ExprRef
<'tcx
>,
214 count
: TypedConstVal
<'tcx
>,
217 fields
: Vec
<ExprRef
<'tcx
>>,
220 fields
: Vec
<ExprRef
<'tcx
>>,
223 adt_def
: AdtDef
<'tcx
>,
224 variant_index
: usize,
225 substs
: &'tcx Substs
<'tcx
>,
226 fields
: Vec
<FieldExprRef
<'tcx
>>,
227 base
: Option
<FruInfo
<'tcx
>>
231 substs
: ClosureSubsts
<'tcx
>,
232 upvars
: Vec
<ExprRef
<'tcx
>>,
235 literal
: Literal
<'tcx
>,
238 asm
: &'tcx hir
::InlineAsm
,
239 outputs
: Vec
<ExprRef
<'tcx
>>,
240 inputs
: Vec
<ExprRef
<'tcx
>>
244 #[derive(Clone, Debug)]
245 pub enum ExprRef
<'tcx
> {
246 Hair(&'tcx hir
::Expr
),
247 Mirror(Box
<Expr
<'tcx
>>),
250 #[derive(Clone, Debug)]
251 pub struct FieldExprRef
<'tcx
> {
253 pub expr
: ExprRef
<'tcx
>,
256 #[derive(Clone, Debug)]
257 pub struct FruInfo
<'tcx
> {
258 pub base
: ExprRef
<'tcx
>,
259 pub field_types
: Vec
<Ty
<'tcx
>>
262 #[derive(Clone, Debug)]
263 pub struct Arm
<'tcx
> {
264 pub patterns
: Vec
<Pattern
<'tcx
>>,
265 pub guard
: Option
<ExprRef
<'tcx
>>,
266 pub body
: ExprRef
<'tcx
>,
269 #[derive(Copy, Clone, Debug)]
275 ///////////////////////////////////////////////////////////////////////////
278 /// "Mirroring" is the process of converting from a HIR type into one
279 /// of the HAIR types defined in this file. This is basically a "on
280 /// the fly" desugaring step that hides a lot of the messiness in the
281 /// tcx. For example, the mirror of a `&'tcx hir::Expr` is an
284 /// Mirroring is gradual: when you mirror an outer expression like `e1
285 /// + e2`, the references to the inner expressions `e1` and `e2` are
286 /// `ExprRef<'tcx>` instances, and they may or may not be eagerly
287 /// mirrored. This allows a single AST node from the compiler to
288 /// expand into one or more Hair nodes, which lets the Hair nodes be
290 pub trait Mirror
<'tcx
> {
293 fn make_mirror
<'a
, 'gcx
>(self, cx
: &mut Cx
<'a
, 'gcx
, 'tcx
>) -> Self::Output
;
296 impl<'tcx
> Mirror
<'tcx
> for Expr
<'tcx
> {
297 type Output
= Expr
<'tcx
>;
299 fn make_mirror
<'a
, 'gcx
>(self, _
: &mut Cx
<'a
, 'gcx
, 'tcx
>) -> Expr
<'tcx
> {
304 impl<'tcx
> Mirror
<'tcx
> for ExprRef
<'tcx
> {
305 type Output
= Expr
<'tcx
>;
307 fn make_mirror
<'a
, 'gcx
>(self, hir
: &mut Cx
<'a
, 'gcx
, 'tcx
>) -> Expr
<'tcx
> {
309 ExprRef
::Hair(h
) => h
.make_mirror(hir
),
310 ExprRef
::Mirror(m
) => *m
,
315 impl<'tcx
> Mirror
<'tcx
> for Stmt
<'tcx
> {
316 type Output
= Stmt
<'tcx
>;
318 fn make_mirror
<'a
, 'gcx
>(self, _
: &mut Cx
<'a
, 'gcx
, 'tcx
>) -> Stmt
<'tcx
> {
323 impl<'tcx
> Mirror
<'tcx
> for StmtRef
<'tcx
> {
324 type Output
= Stmt
<'tcx
>;
326 fn make_mirror
<'a
, 'gcx
>(self, _
: &mut Cx
<'a
, 'gcx
, 'tcx
>) -> Stmt
<'tcx
> {
328 StmtRef
::Mirror(m
) => *m
,
333 impl<'tcx
> Mirror
<'tcx
> for Block
<'tcx
> {
334 type Output
= Block
<'tcx
>;
336 fn make_mirror
<'a
, 'gcx
>(self, _
: &mut Cx
<'a
, 'gcx
, 'tcx
>) -> Block
<'tcx
> {