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 repr
::{BinOp, BorrowKind, Field, Literal, Mutability, UnOp}
;
18 use rustc
::middle
::def_id
::DefId
;
19 use rustc
::middle
::region
::CodeExtent
;
20 use rustc
::middle
::subst
::Substs
;
21 use rustc
::middle
::ty
::{AdtDef, ClosureSubsts, Region, Ty}
;
24 use syntax
::codemap
::Span
;
25 use tcx
::{Cx, PatNode}
;
27 #[derive(Clone, Debug)]
28 pub struct ItemRef
<'tcx
> {
31 pub substs
: &'tcx Substs
<'tcx
>,
34 #[derive(Clone, Debug)]
35 pub struct Block
<'tcx
> {
36 pub extent
: CodeExtent
,
38 pub stmts
: Vec
<StmtRef
<'tcx
>>,
39 pub expr
: Option
<ExprRef
<'tcx
>>,
42 #[derive(Clone, Debug)]
43 pub enum StmtRef
<'tcx
> {
44 Hair(&'tcx hir
::Stmt
),
45 Mirror(Box
<Stmt
<'tcx
>>),
48 #[derive(Clone, Debug)]
49 pub struct Stmt
<'tcx
> {
51 pub kind
: StmtKind
<'tcx
>,
54 #[derive(Clone, Debug)]
55 pub enum StmtKind
<'tcx
> {
57 /// scope for this statement; may be used as lifetime of temporaries
60 /// expression being evaluated in this statement
65 /// scope for variables bound in this let; covers this and
66 /// remaining statements in block
67 remainder_scope
: CodeExtent
,
69 /// scope for the initialization itself; might be used as
70 /// lifetime of temporaries
71 init_scope
: CodeExtent
,
74 pattern
: PatternRef
<'tcx
>,
76 /// let pat = <INIT> ...
77 initializer
: Option
<ExprRef
<'tcx
>>,
79 /// let pat = init; <STMTS>
80 stmts
: Vec
<StmtRef
<'tcx
>>,
84 // The Hair trait implementor translates their expressions (`&'tcx H::Expr`)
85 // into instances of this `Expr` enum. This translation can be done
86 // basically as lazilly or as eagerly as desired: every recursive
87 // reference to an expression in this enum is an `ExprRef<'tcx>`, which
88 // may in turn be another instance of this enum (boxed), or else an
89 // untranslated `&'tcx H::Expr`. Note that instances of `Expr` are very
90 // shortlived. They are created by `Hair::to_expr`, analyzed and
91 // converted into MIR, and then discarded.
93 // If you compare `Expr` to the full compiler AST, you will see it is
94 // a good bit simpler. In fact, a number of the more straight-forward
95 // MIR simplifications are already done in the impl of `Hair`. For
96 // example, method calls and overloaded operators are absent: they are
97 // expected to be converted into `Expr::Call` instances.
98 #[derive(Clone, Debug)]
99 pub struct Expr
<'tcx
> {
100 // type of this expression
103 // lifetime of this expression if it should be spilled into a
104 // temporary; should be None only if in a constant context
105 pub temp_lifetime
: Option
<CodeExtent
>,
107 // span of the expression in the source
110 // kind of expression
111 pub kind
: ExprKind
<'tcx
>,
114 #[derive(Clone, Debug)]
115 pub enum ExprKind
<'tcx
> {
118 value
: ExprRef
<'tcx
>,
121 value
: ExprRef
<'tcx
>,
125 args
: Vec
<ExprRef
<'tcx
>>,
129 }, // NOT overloaded!
134 }, // NOT overloaded!
143 }, // NOT overloaded!
145 source
: ExprRef
<'tcx
>,
148 source
: ExprRef
<'tcx
>,
151 source
: ExprRef
<'tcx
>,
154 source
: ExprRef
<'tcx
>,
157 condition
: ExprRef
<'tcx
>,
159 otherwise
: Option
<ExprRef
<'tcx
>>,
162 condition
: Option
<ExprRef
<'tcx
>>,
166 discriminant
: ExprRef
<'tcx
>,
167 arms
: Vec
<Arm
<'tcx
>>,
170 body
: &'tcx hir
::Block
,
187 index
: ExprRef
<'tcx
>,
192 SelfRef
, // first argument, used for self in a closure
198 borrow_kind
: BorrowKind
,
202 label
: Option
<CodeExtent
>,
205 label
: Option
<CodeExtent
>,
208 value
: Option
<ExprRef
<'tcx
>>,
211 value
: ExprRef
<'tcx
>,
212 count
: ExprRef
<'tcx
>,
215 fields
: Vec
<ExprRef
<'tcx
>>,
218 fields
: Vec
<ExprRef
<'tcx
>>,
221 adt_def
: AdtDef
<'tcx
>,
222 variant_index
: usize,
223 substs
: &'tcx Substs
<'tcx
>,
224 fields
: Vec
<FieldExprRef
<'tcx
>>,
225 base
: Option
<ExprRef
<'tcx
>>,
229 substs
: &'tcx ClosureSubsts
<'tcx
>,
230 upvars
: Vec
<ExprRef
<'tcx
>>,
233 literal
: Literal
<'tcx
>,
236 asm
: &'tcx hir
::InlineAsm
,
240 #[derive(Clone, Debug)]
241 pub enum ExprRef
<'tcx
> {
242 Hair(&'tcx hir
::Expr
),
243 Mirror(Box
<Expr
<'tcx
>>),
246 #[derive(Clone, Debug)]
247 pub struct FieldExprRef
<'tcx
> {
249 pub expr
: ExprRef
<'tcx
>,
252 #[derive(Clone, Debug)]
253 pub struct Arm
<'tcx
> {
254 pub patterns
: Vec
<PatternRef
<'tcx
>>,
255 pub guard
: Option
<ExprRef
<'tcx
>>,
256 pub body
: ExprRef
<'tcx
>,
259 #[derive(Clone, Debug)]
260 pub struct Pattern
<'tcx
> {
263 pub kind
: PatternKind
<'tcx
>,
266 #[derive(Copy, Clone, Debug)]
272 #[derive(Clone, Debug)]
273 pub enum PatternKind
<'tcx
> {
276 // x, ref x, x @ P, etc
278 mutability
: Mutability
,
283 subpattern
: Option
<PatternRef
<'tcx
>>,
286 // Foo(...) or Foo{...} or Foo, where `Foo` is a variant name from an adt with >1 variants
288 adt_def
: AdtDef
<'tcx
>,
289 variant_index
: usize,
290 subpatterns
: Vec
<FieldPatternRef
<'tcx
>>,
293 // (...), Foo(...), Foo{...}, or Foo, where `Foo` is a variant name from an adt with 1 variant
295 subpatterns
: Vec
<FieldPatternRef
<'tcx
>>,
299 subpattern
: PatternRef
<'tcx
>,
300 }, // box P, &P, &mut P, etc
303 value
: Literal
<'tcx
>,
311 // matches against a slice, checking the length and extracting elements
313 prefix
: Vec
<PatternRef
<'tcx
>>,
314 slice
: Option
<PatternRef
<'tcx
>>,
315 suffix
: Vec
<PatternRef
<'tcx
>>,
318 // fixed match against an array, irrefutable
320 prefix
: Vec
<PatternRef
<'tcx
>>,
321 slice
: Option
<PatternRef
<'tcx
>>,
322 suffix
: Vec
<PatternRef
<'tcx
>>,
326 #[derive(Copy, Clone, Debug)]
327 pub enum BindingMode
{
329 ByRef(Region
, BorrowKind
),
332 #[derive(Clone, Debug)]
333 pub enum PatternRef
<'tcx
> {
335 Mirror(Box
<Pattern
<'tcx
>>),
338 #[derive(Clone, Debug)]
339 pub struct FieldPatternRef
<'tcx
> {
341 pub pattern
: PatternRef
<'tcx
>,
344 ///////////////////////////////////////////////////////////////////////////
347 /// "Mirroring" is the process of converting from a HIR type into one
348 /// of the HAIR types defined in this file. This is basically a "on
349 /// the fly" desugaring step that hides a lot of the messiness in the
350 /// tcx. For example, the mirror of a `&'tcx hir::Expr` is an
353 /// Mirroring is gradual: when you mirror an outer expression like `e1
354 /// + e2`, the references to the inner expressions `e1` and `e2` are
355 /// `ExprRef<'tcx>` instances, and they may or may not be eagerly
356 /// mirrored. This allows a single AST node from the compiler to
357 /// expand into one or more Hair nodes, which lets the Hair nodes be
359 pub trait Mirror
<'tcx
> {
362 fn make_mirror
<'a
>(self, cx
: &mut Cx
<'a
, 'tcx
>) -> Self::Output
;
365 impl<'tcx
> Mirror
<'tcx
> for Expr
<'tcx
> {
366 type Output
= Expr
<'tcx
>;
368 fn make_mirror
<'a
>(self, _
: &mut Cx
<'a
, 'tcx
>) -> Expr
<'tcx
> {
373 impl<'tcx
> Mirror
<'tcx
> for ExprRef
<'tcx
> {
374 type Output
= Expr
<'tcx
>;
376 fn make_mirror
<'a
>(self, hir
: &mut Cx
<'a
, 'tcx
>) -> Expr
<'tcx
> {
378 ExprRef
::Hair(h
) => h
.make_mirror(hir
),
379 ExprRef
::Mirror(m
) => *m
,
384 impl<'tcx
> Mirror
<'tcx
> for Stmt
<'tcx
> {
385 type Output
= Stmt
<'tcx
>;
387 fn make_mirror
<'a
>(self, _
: &mut Cx
<'a
, 'tcx
>) -> Stmt
<'tcx
> {
392 impl<'tcx
> Mirror
<'tcx
> for StmtRef
<'tcx
> {
393 type Output
= Stmt
<'tcx
>;
395 fn make_mirror
<'a
>(self, hir
: &mut Cx
<'a
, 'tcx
>) -> Stmt
<'tcx
> {
397 StmtRef
::Hair(h
) => h
.make_mirror(hir
),
398 StmtRef
::Mirror(m
) => *m
,
403 impl<'tcx
> Mirror
<'tcx
> for Pattern
<'tcx
> {
404 type Output
= Pattern
<'tcx
>;
406 fn make_mirror
<'a
>(self, _
: &mut Cx
<'a
, 'tcx
>) -> Pattern
<'tcx
> {
411 impl<'tcx
> Mirror
<'tcx
> for PatternRef
<'tcx
> {
412 type Output
= Pattern
<'tcx
>;
414 fn make_mirror
<'a
>(self, hir
: &mut Cx
<'a
, 'tcx
>) -> Pattern
<'tcx
> {
416 PatternRef
::Hair(h
) => h
.make_mirror(hir
),
417 PatternRef
::Mirror(m
) => *m
,
422 impl<'tcx
> Mirror
<'tcx
> for Block
<'tcx
> {
423 type Output
= Block
<'tcx
>;
425 fn make_mirror
<'a
>(self, _
: &mut Cx
<'a
, 'tcx
>) -> Block
<'tcx
> {