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 built 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, UserTypeAnnotation, Field, UnOp}
;
18 use rustc
::hir
::def_id
::DefId
;
19 use rustc
::middle
::region
;
20 use rustc
::ty
::subst
::Substs
;
21 use rustc
::ty
::{AdtDef, UpvarSubsts, Region, Ty, Const}
;
30 pub use self::pattern
::{BindingMode, Pattern, PatternKind, FieldPattern}
;
31 pub(crate) use self::pattern
::{PatternTypeProjection, PatternTypeProjections}
;
35 #[derive(Copy, Clone, Debug)]
42 pub fn is_explicit(self) -> bool
{
44 LintLevel
::Inherited
=> false,
45 LintLevel
::Explicit(_
) => true
50 #[derive(Clone, Debug)]
51 pub struct Block
<'tcx
> {
52 pub targeted_by_break
: bool
,
53 pub region_scope
: region
::Scope
,
54 pub opt_destruction_scope
: Option
<region
::Scope
>,
56 pub stmts
: Vec
<StmtRef
<'tcx
>>,
57 pub expr
: Option
<ExprRef
<'tcx
>>,
58 pub safety_mode
: BlockSafety
,
61 #[derive(Copy, Clone, Debug)]
62 pub enum BlockSafety
{
64 ExplicitUnsafe(ast
::NodeId
),
69 #[derive(Clone, Debug)]
70 pub enum StmtRef
<'tcx
> {
71 Mirror(Box
<Stmt
<'tcx
>>),
74 #[derive(Clone, Debug)]
75 pub struct Stmt
<'tcx
> {
76 pub kind
: StmtKind
<'tcx
>,
77 pub opt_destruction_scope
: Option
<region
::Scope
>,
80 #[derive(Clone, Debug)]
81 pub enum StmtKind
<'tcx
> {
83 /// scope for this statement; may be used as lifetime of temporaries
86 /// expression being evaluated in this statement
91 /// scope for variables bound in this let; covers this and
92 /// remaining statements in block
93 remainder_scope
: region
::Scope
,
95 /// scope for the initialization itself; might be used as
96 /// lifetime of temporaries
97 init_scope
: region
::Scope
,
101 /// if a type is included, it is added as an ascription pattern
102 pattern
: Pattern
<'tcx
>,
104 /// let pat: ty = <INIT> ...
105 initializer
: Option
<ExprRef
<'tcx
>>,
107 /// the lint level for this let-statement
108 lint_level
: LintLevel
,
112 /// The Hair trait implementor lowers their expressions (`&'tcx H::Expr`)
113 /// into instances of this `Expr` enum. This lowering can be done
114 /// basically as lazily or as eagerly as desired: every recursive
115 /// reference to an expression in this enum is an `ExprRef<'tcx>`, which
116 /// may in turn be another instance of this enum (boxed), or else an
117 /// unlowered `&'tcx H::Expr`. Note that instances of `Expr` are very
118 /// shortlived. They are created by `Hair::to_expr`, analyzed and
119 /// converted into MIR, and then discarded.
121 /// If you compare `Expr` to the full compiler AST, you will see it is
122 /// a good bit simpler. In fact, a number of the more straight-forward
123 /// MIR simplifications are already done in the impl of `Hair`. For
124 /// example, method calls and overloaded operators are absent: they are
125 /// expected to be converted into `Expr::Call` instances.
126 #[derive(Clone, Debug)]
127 pub struct Expr
<'tcx
> {
128 /// type of this expression
131 /// lifetime of this expression if it should be spilled into a
132 /// temporary; should be None only if in a constant context
133 pub temp_lifetime
: Option
<region
::Scope
>,
135 /// span of the expression in the source
138 /// kind of expression
139 pub kind
: ExprKind
<'tcx
>,
142 #[derive(Clone, Debug)]
143 pub enum ExprKind
<'tcx
> {
145 region_scope
: region
::Scope
,
146 lint_level
: LintLevel
,
147 value
: ExprRef
<'tcx
>,
150 value
: ExprRef
<'tcx
>,
155 args
: Vec
<ExprRef
<'tcx
>>,
156 // Whether this is from a call in HIR, rather than from an overloaded
157 // operator. True for overloaded function call.
162 }, // NOT overloaded!
167 }, // NOT overloaded!
172 }, // NOT overloaded!
173 // LogicalOp is distinct from BinaryOp because of lazy evaluation of the operands.
177 }, // NOT overloaded!
179 source
: ExprRef
<'tcx
>,
182 source
: ExprRef
<'tcx
>,
183 }, // Use a lexpr to get a vexpr.
185 source
: ExprRef
<'tcx
>,
188 source
: ExprRef
<'tcx
>,
191 source
: ExprRef
<'tcx
>,
194 source
: ExprRef
<'tcx
>,
197 source
: ExprRef
<'tcx
>,
200 condition
: ExprRef
<'tcx
>,
202 otherwise
: Option
<ExprRef
<'tcx
>>,
205 condition
: Option
<ExprRef
<'tcx
>>,
209 discriminant
: ExprRef
<'tcx
>,
210 arms
: Vec
<Arm
<'tcx
>>,
213 body
: &'tcx hir
::Block
,
230 index
: ExprRef
<'tcx
>,
235 /// first argument, used for self in a closure
241 region
: Region
<'tcx
>,
242 borrow_kind
: BorrowKind
,
246 label
: region
::Scope
,
247 value
: Option
<ExprRef
<'tcx
>>,
250 label
: region
::Scope
,
253 value
: Option
<ExprRef
<'tcx
>>,
256 value
: ExprRef
<'tcx
>,
260 fields
: Vec
<ExprRef
<'tcx
>>,
263 fields
: Vec
<ExprRef
<'tcx
>>,
266 adt_def
: &'tcx AdtDef
,
267 variant_index
: usize,
268 substs
: &'tcx Substs
<'tcx
>,
270 /// Optional user-given substs: for something like `let x =
271 /// Bar::<T> { ... }`.
272 user_ty
: Option
<UserTypeAnnotation
<'tcx
>>,
274 fields
: Vec
<FieldExprRef
<'tcx
>>,
275 base
: Option
<FruInfo
<'tcx
>>
277 PlaceTypeAscription
{
278 source
: ExprRef
<'tcx
>,
279 /// Type that the user gave to this expression
280 user_ty
: Option
<UserTypeAnnotation
<'tcx
>>,
282 ValueTypeAscription
{
283 source
: ExprRef
<'tcx
>,
284 /// Type that the user gave to this expression
285 user_ty
: Option
<UserTypeAnnotation
<'tcx
>>,
289 substs
: UpvarSubsts
<'tcx
>,
290 upvars
: Vec
<ExprRef
<'tcx
>>,
291 movability
: Option
<hir
::GeneratorMovability
>,
294 literal
: &'tcx Const
<'tcx
>,
295 user_ty
: Option
<UserTypeAnnotation
<'tcx
>>,
298 asm
: &'tcx hir
::InlineAsm
,
299 outputs
: Vec
<ExprRef
<'tcx
>>,
300 inputs
: Vec
<ExprRef
<'tcx
>>
303 value
: ExprRef
<'tcx
>,
307 #[derive(Clone, Debug)]
308 pub enum ExprRef
<'tcx
> {
309 Hair(&'tcx hir
::Expr
),
310 Mirror(Box
<Expr
<'tcx
>>),
313 #[derive(Clone, Debug)]
314 pub struct FieldExprRef
<'tcx
> {
316 pub expr
: ExprRef
<'tcx
>,
319 #[derive(Clone, Debug)]
320 pub struct FruInfo
<'tcx
> {
321 pub base
: ExprRef
<'tcx
>,
322 pub field_types
: Vec
<Ty
<'tcx
>>
325 #[derive(Clone, Debug)]
326 pub struct Arm
<'tcx
> {
327 pub patterns
: Vec
<Pattern
<'tcx
>>,
328 pub guard
: Option
<Guard
<'tcx
>>,
329 pub body
: ExprRef
<'tcx
>,
330 pub lint_level
: LintLevel
,
333 #[derive(Clone, Debug)]
334 pub enum Guard
<'tcx
> {
338 #[derive(Copy, Clone, Debug)]
344 impl<'tcx
> ExprRef
<'tcx
> {
345 pub fn span(&self) -> Span
{
347 ExprRef
::Hair(expr
) => expr
.span
,
348 ExprRef
::Mirror(expr
) => expr
.span
,
353 ///////////////////////////////////////////////////////////////////////////
356 /// "Mirroring" is the process of converting from a HIR type into one
357 /// of the HAIR types defined in this file. This is basically a "on
358 /// the fly" desugaring step that hides a lot of the messiness in the
359 /// tcx. For example, the mirror of a `&'tcx hir::Expr` is an
362 /// Mirroring is gradual: when you mirror an outer expression like `e1
363 /// + e2`, the references to the inner expressions `e1` and `e2` are
364 /// `ExprRef<'tcx>` instances, and they may or may not be eagerly
365 /// mirrored. This allows a single AST node from the compiler to
366 /// expand into one or more Hair nodes, which lets the Hair nodes be
368 pub trait Mirror
<'tcx
> {
371 fn make_mirror
<'a
, 'gcx
>(self, cx
: &mut Cx
<'a
, 'gcx
, 'tcx
>) -> Self::Output
;
374 impl<'tcx
> Mirror
<'tcx
> for Expr
<'tcx
> {
375 type Output
= Expr
<'tcx
>;
377 fn make_mirror
<'a
, 'gcx
>(self, _
: &mut Cx
<'a
, 'gcx
, 'tcx
>) -> Expr
<'tcx
> {
382 impl<'tcx
> Mirror
<'tcx
> for ExprRef
<'tcx
> {
383 type Output
= Expr
<'tcx
>;
385 fn make_mirror
<'a
, 'gcx
>(self, hir
: &mut Cx
<'a
, 'gcx
, 'tcx
>) -> Expr
<'tcx
> {
387 ExprRef
::Hair(h
) => h
.make_mirror(hir
),
388 ExprRef
::Mirror(m
) => *m
,
393 impl<'tcx
> Mirror
<'tcx
> for Stmt
<'tcx
> {
394 type Output
= Stmt
<'tcx
>;
396 fn make_mirror
<'a
, 'gcx
>(self, _
: &mut Cx
<'a
, 'gcx
, 'tcx
>) -> Stmt
<'tcx
> {
401 impl<'tcx
> Mirror
<'tcx
> for StmtRef
<'tcx
> {
402 type Output
= Stmt
<'tcx
>;
404 fn make_mirror
<'a
, 'gcx
>(self, _
: &mut Cx
<'a
, 'gcx
, 'tcx
>) -> Stmt
<'tcx
> {
406 StmtRef
::Mirror(m
) => *m
,
411 impl<'tcx
> Mirror
<'tcx
> for Block
<'tcx
> {
412 type Output
= Block
<'tcx
>;
414 fn make_mirror
<'a
, 'gcx
>(self, _
: &mut Cx
<'a
, 'gcx
, 'tcx
>) -> Block
<'tcx
> {