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
::repr
::{BinOp
, BorrowKind
, Field
, Literal
, Mutability
, UnOp
,
19 use rustc
::middle
::const_val
::ConstVal
;
20 use rustc
::hir
::def_id
::DefId
;
21 use rustc
::middle
::region
::CodeExtent
;
22 use rustc
::ty
::subst
::Substs
;
23 use rustc
::ty
::{self, AdtDef, ClosureSubsts, Region, Ty}
;
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(Clone, Debug)]
270 pub struct Pattern
<'tcx
> {
273 pub kind
: Box
<PatternKind
<'tcx
>>,
276 #[derive(Copy, Clone, Debug)]
282 #[derive(Clone, Debug)]
283 pub enum PatternKind
<'tcx
> {
286 /// x, ref x, x @ P, etc
288 mutability
: Mutability
,
290 mode
: BindingMode
<'tcx
>,
293 subpattern
: Option
<Pattern
<'tcx
>>,
296 /// Foo(...) or Foo{...} or Foo, where `Foo` is a variant name from an adt with >1 variants
298 adt_def
: AdtDef
<'tcx
>,
299 variant_index
: usize,
300 subpatterns
: Vec
<FieldPattern
<'tcx
>>,
303 /// (...), Foo(...), Foo{...}, or Foo, where `Foo` is a variant name from an adt with 1 variant
305 subpatterns
: Vec
<FieldPattern
<'tcx
>>,
308 /// box P, &P, &mut P, etc
310 subpattern
: Pattern
<'tcx
>,
322 /// matches against a slice, checking the length and extracting elements
324 prefix
: Vec
<Pattern
<'tcx
>>,
325 slice
: Option
<Pattern
<'tcx
>>,
326 suffix
: Vec
<Pattern
<'tcx
>>,
329 /// fixed match against an array, irrefutable
331 prefix
: Vec
<Pattern
<'tcx
>>,
332 slice
: Option
<Pattern
<'tcx
>>,
333 suffix
: Vec
<Pattern
<'tcx
>>,
337 #[derive(Copy, Clone, Debug)]
338 pub enum BindingMode
<'tcx
> {
340 ByRef(&'tcx Region
, BorrowKind
),
343 #[derive(Clone, Debug)]
344 pub struct FieldPattern
<'tcx
> {
346 pub pattern
: Pattern
<'tcx
>,
349 ///////////////////////////////////////////////////////////////////////////
352 /// "Mirroring" is the process of converting from a HIR type into one
353 /// of the HAIR types defined in this file. This is basically a "on
354 /// the fly" desugaring step that hides a lot of the messiness in the
355 /// tcx. For example, the mirror of a `&'tcx hir::Expr` is an
358 /// Mirroring is gradual: when you mirror an outer expression like `e1
359 /// + e2`, the references to the inner expressions `e1` and `e2` are
360 /// `ExprRef<'tcx>` instances, and they may or may not be eagerly
361 /// mirrored. This allows a single AST node from the compiler to
362 /// expand into one or more Hair nodes, which lets the Hair nodes be
364 pub trait Mirror
<'tcx
> {
367 fn make_mirror
<'a
, 'gcx
>(self, cx
: &mut Cx
<'a
, 'gcx
, 'tcx
>) -> Self::Output
;
370 impl<'tcx
> Mirror
<'tcx
> for Expr
<'tcx
> {
371 type Output
= Expr
<'tcx
>;
373 fn make_mirror
<'a
, 'gcx
>(self, _
: &mut Cx
<'a
, 'gcx
, 'tcx
>) -> Expr
<'tcx
> {
378 impl<'tcx
> Mirror
<'tcx
> for ExprRef
<'tcx
> {
379 type Output
= Expr
<'tcx
>;
381 fn make_mirror
<'a
, 'gcx
>(self, hir
: &mut Cx
<'a
, 'gcx
, 'tcx
>) -> Expr
<'tcx
> {
383 ExprRef
::Hair(h
) => h
.make_mirror(hir
),
384 ExprRef
::Mirror(m
) => *m
,
389 impl<'tcx
> Mirror
<'tcx
> for Stmt
<'tcx
> {
390 type Output
= Stmt
<'tcx
>;
392 fn make_mirror
<'a
, 'gcx
>(self, _
: &mut Cx
<'a
, 'gcx
, 'tcx
>) -> Stmt
<'tcx
> {
397 impl<'tcx
> Mirror
<'tcx
> for StmtRef
<'tcx
> {
398 type Output
= Stmt
<'tcx
>;
400 fn make_mirror
<'a
, 'gcx
>(self, _
: &mut Cx
<'a
, 'gcx
, 'tcx
>) -> Stmt
<'tcx
> {
402 StmtRef
::Mirror(m
) => *m
,
407 impl<'tcx
> Mirror
<'tcx
> for Block
<'tcx
> {
408 type Output
= Block
<'tcx
>;
410 fn make_mirror
<'a
, 'gcx
>(self, _
: &mut Cx
<'a
, 'gcx
, 'tcx
>) -> Block
<'tcx
> {