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}
;
26 use syntax
::codemap
::Span
;
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
>,
146 source
: ExprRef
<'tcx
>,
149 source
: ExprRef
<'tcx
>,
152 condition
: ExprRef
<'tcx
>,
154 otherwise
: Option
<ExprRef
<'tcx
>>,
157 condition
: Option
<ExprRef
<'tcx
>>,
161 discriminant
: ExprRef
<'tcx
>,
162 arms
: Vec
<Arm
<'tcx
>>,
165 body
: &'tcx hir
::Block
,
182 index
: ExprRef
<'tcx
>,
187 /// first argument, used for self in a closure
194 borrow_kind
: BorrowKind
,
198 label
: Option
<CodeExtent
>,
201 label
: Option
<CodeExtent
>,
204 value
: Option
<ExprRef
<'tcx
>>,
207 value
: ExprRef
<'tcx
>,
208 count
: TypedConstVal
<'tcx
>,
211 fields
: Vec
<ExprRef
<'tcx
>>,
214 fields
: Vec
<ExprRef
<'tcx
>>,
217 adt_def
: AdtDef
<'tcx
>,
218 variant_index
: usize,
219 substs
: &'tcx Substs
<'tcx
>,
220 fields
: Vec
<FieldExprRef
<'tcx
>>,
221 base
: Option
<FruInfo
<'tcx
>>
225 substs
: &'tcx ClosureSubsts
<'tcx
>,
226 upvars
: Vec
<ExprRef
<'tcx
>>,
229 literal
: Literal
<'tcx
>,
232 asm
: &'tcx hir
::InlineAsm
,
233 outputs
: Vec
<ExprRef
<'tcx
>>,
234 inputs
: Vec
<ExprRef
<'tcx
>>
238 #[derive(Clone, Debug)]
239 pub enum ExprRef
<'tcx
> {
240 Hair(&'tcx hir
::Expr
),
241 Mirror(Box
<Expr
<'tcx
>>),
244 #[derive(Clone, Debug)]
245 pub struct FieldExprRef
<'tcx
> {
247 pub expr
: ExprRef
<'tcx
>,
250 #[derive(Clone, Debug)]
251 pub struct FruInfo
<'tcx
> {
252 pub base
: ExprRef
<'tcx
>,
253 pub field_types
: Vec
<Ty
<'tcx
>>
256 #[derive(Clone, Debug)]
257 pub struct Arm
<'tcx
> {
258 pub patterns
: Vec
<Pattern
<'tcx
>>,
259 pub guard
: Option
<ExprRef
<'tcx
>>,
260 pub body
: ExprRef
<'tcx
>,
263 #[derive(Clone, Debug)]
264 pub struct Pattern
<'tcx
> {
267 pub kind
: Box
<PatternKind
<'tcx
>>,
270 #[derive(Copy, Clone, Debug)]
276 #[derive(Clone, Debug)]
277 pub enum PatternKind
<'tcx
> {
280 /// x, ref x, x @ P, etc
282 mutability
: Mutability
,
287 subpattern
: Option
<Pattern
<'tcx
>>,
290 /// Foo(...) or Foo{...} or Foo, where `Foo` is a variant name from an adt with >1 variants
292 adt_def
: AdtDef
<'tcx
>,
293 variant_index
: usize,
294 subpatterns
: Vec
<FieldPattern
<'tcx
>>,
297 /// (...), Foo(...), Foo{...}, or Foo, where `Foo` is a variant name from an adt with 1 variant
299 subpatterns
: Vec
<FieldPattern
<'tcx
>>,
302 /// box P, &P, &mut P, etc
304 subpattern
: Pattern
<'tcx
>,
316 /// matches against a slice, checking the length and extracting elements
318 prefix
: Vec
<Pattern
<'tcx
>>,
319 slice
: Option
<Pattern
<'tcx
>>,
320 suffix
: Vec
<Pattern
<'tcx
>>,
323 /// fixed match against an array, irrefutable
325 prefix
: Vec
<Pattern
<'tcx
>>,
326 slice
: Option
<Pattern
<'tcx
>>,
327 suffix
: Vec
<Pattern
<'tcx
>>,
331 #[derive(Copy, Clone, Debug)]
332 pub enum BindingMode
{
334 ByRef(Region
, BorrowKind
),
337 #[derive(Clone, Debug)]
338 pub struct FieldPattern
<'tcx
> {
340 pub pattern
: Pattern
<'tcx
>,
343 ///////////////////////////////////////////////////////////////////////////
346 /// "Mirroring" is the process of converting from a HIR type into one
347 /// of the HAIR types defined in this file. This is basically a "on
348 /// the fly" desugaring step that hides a lot of the messiness in the
349 /// tcx. For example, the mirror of a `&'tcx hir::Expr` is an
352 /// Mirroring is gradual: when you mirror an outer expression like `e1
353 /// + e2`, the references to the inner expressions `e1` and `e2` are
354 /// `ExprRef<'tcx>` instances, and they may or may not be eagerly
355 /// mirrored. This allows a single AST node from the compiler to
356 /// expand into one or more Hair nodes, which lets the Hair nodes be
358 pub trait Mirror
<'tcx
> {
361 fn make_mirror
<'a
>(self, cx
: &mut Cx
<'a
, 'tcx
>) -> Self::Output
;
364 impl<'tcx
> Mirror
<'tcx
> for Expr
<'tcx
> {
365 type Output
= Expr
<'tcx
>;
367 fn make_mirror
<'a
>(self, _
: &mut Cx
<'a
, 'tcx
>) -> Expr
<'tcx
> {
372 impl<'tcx
> Mirror
<'tcx
> for ExprRef
<'tcx
> {
373 type Output
= Expr
<'tcx
>;
375 fn make_mirror
<'a
>(self, hir
: &mut Cx
<'a
, 'tcx
>) -> Expr
<'tcx
> {
377 ExprRef
::Hair(h
) => h
.make_mirror(hir
),
378 ExprRef
::Mirror(m
) => *m
,
383 impl<'tcx
> Mirror
<'tcx
> for Stmt
<'tcx
> {
384 type Output
= Stmt
<'tcx
>;
386 fn make_mirror
<'a
>(self, _
: &mut Cx
<'a
, 'tcx
>) -> Stmt
<'tcx
> {
391 impl<'tcx
> Mirror
<'tcx
> for StmtRef
<'tcx
> {
392 type Output
= Stmt
<'tcx
>;
394 fn make_mirror
<'a
>(self, _
: &mut Cx
<'a
,'tcx
>) -> Stmt
<'tcx
> {
396 StmtRef
::Mirror(m
) => *m
,
401 impl<'tcx
> Mirror
<'tcx
> for Block
<'tcx
> {
402 type Output
= Block
<'tcx
>;
404 fn make_mirror
<'a
>(self, _
: &mut Cx
<'a
, 'tcx
>) -> Block
<'tcx
> {