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};
21 pub trait Hair: Sized+Debug+Clone+Eq+Hash { // (*)
23 // (*) the `Sized` and Debug` bounds are the only ones that really
24 // make sense. The rest are just there so that we can
25 // `#[derive(Clone)]` on things that are parameterized over
26 // `H:HAIR`. It's kind of lame.
28 type VarId: Copy+Debug+Eq+Hash; // e.g., NodeId for a variable
29 type DefId: Copy+Debug+Eq+Hash; // e.g., DefId
30 type AdtDef: Copy+Debug+Eq+Hash; // e.g., AdtDef<'tcx>
31 type Name: Copy+Debug+Eq+Hash; // e.g., ast::Name
32 type Ident: Copy+Debug+Eq+Hash; // e.g., ast::Ident
33 type InternedString: Clone+Debug+Eq+Hash; // e.g., InternedString
34 type Bytes: Clone+Debug+Eq+Hash; // e.g., Rc<Vec<u8>>
35 type Span: Copy+Debug+Eq; // e.g., syntax::codemap::Span
36 type Projection: Clone+Debug+Eq; // e.g., ty::ProjectionTy<'tcx>
37 type Substs: Clone+Debug+Eq; // e.g., substs::Substs<'tcx>
38 type ClosureSubsts: Clone+Debug+Eq; // e.g., ty::ClosureSubsts<'tcx>
39 type Ty: Clone+Debug+Eq; // e.g., ty::Ty<'tcx>
40 type Region: Copy+Debug; // e.g., ty::Region
41 type CodeExtent: Copy+Debug+Hash+Eq; // e.g., region::CodeExtent
42 type Pattern: Clone+Debug+Mirror<Self,Output=Pattern<Self>>; // e.g., &P<ast::Pat>
43 type Expr: Clone+Debug+Mirror<Self,Output=Expr<Self>>; // e.g., &P<ast::Expr>
44 type Stmt: Clone+Debug+Mirror<Self,Output=Stmt<Self>>; // e.g., &P<ast::Stmt>
45 type Block: Clone+Debug+Mirror<Self,Output=Block<Self>>; // e.g., &P<ast::Block>
46 type InlineAsm: Clone+Debug+Eq+Hash; // e.g., ast::InlineAsm
48 /// Normalizes `ast` into the appropriate `mirror` type.
49 fn mirror<M:Mirror<Self>>(&mut self, ast: M) -> M::Output {
53 /// Returns the unit type `()`
54 fn unit_ty(&mut self) -> Self::Ty;
56 /// Returns the type `usize`.
57 fn usize_ty(&mut self) -> Self::Ty;
59 /// Returns the type `bool`.
60 fn bool_ty(&mut self) -> Self::Ty;
62 /// Returns a reference to `PartialEq::<T,T>::eq`
63 fn partial_eq(&mut self, ty: Self::Ty) -> ItemRef<Self>;
65 /// Returns a reference to `PartialOrd::<T,T>::le`
66 fn partial_le(&mut self, ty: Self::Ty) -> ItemRef<Self>;
68 /// Returns the number of variants for the given enum
69 fn num_variants(&mut self, adt: Self::AdtDef) -> usize;
71 fn fields(&mut self, adt: Self::AdtDef, variant_index: usize) -> Vec<Field<Self>>;
73 /// true if a value of type `ty` (may) need to be dropped; this
74 /// may return false even for non-Copy types if there is no
75 /// destructor to execute. If correct result is not known, may be
76 /// approximated by returning `true`; this will result in more
77 /// drops but not incorrect code.
78 fn needs_drop(&mut self, ty: Self::Ty, span: Self::Span) -> bool;
80 /// Report an internal inconsistency.
81 fn span_bug(&mut self, span: Self::Span, message: &str) -> !;
84 #[derive(Clone, Debug)]
85 pub struct ItemRef<H:Hair> {
88 pub substs: H::Substs,
91 #[derive(Clone, Debug)]
92 pub struct Block<H:Hair> {
93 pub extent: H::CodeExtent,
95 pub stmts: Vec<StmtRef<H>>,
96 pub expr: Option<ExprRef<H>>,
99 #[derive(Clone, Debug)]
100 pub enum StmtRef<H:Hair> {
102 Mirror(Box<Stmt<H>>),
105 #[derive(Clone, Debug)]
106 pub struct Stmt<H:Hair> {
108 pub kind: StmtKind<H>,
111 #[derive(Clone, Debug)]
112 pub enum StmtKind<H:Hair> {
114 /// scope for this statement; may be used as lifetime of temporaries
115 scope: H::CodeExtent,
117 /// expression being evaluated in this statement
122 /// scope for variables bound in this let; covers this and
123 /// remaining statements in block
124 remainder_scope: H::CodeExtent,
126 /// scope for the initialization itself; might be used as
127 /// lifetime of temporaries
128 init_scope: H::CodeExtent,
131 pattern: PatternRef<H>,
133 /// let pat = <INIT> ...
134 initializer: Option<ExprRef<H>>,
136 /// let pat = init; <STMTS>
137 stmts: Vec<StmtRef<H>>
141 // The Hair trait implementor translates their expressions (`H::Expr`)
142 // into instances of this `Expr` enum. This translation can be done
143 // basically as lazilly or as eagerly as desired: every recursive
144 // reference to an expression in this enum is an `ExprRef<H>`, which
145 // may in turn be another instance of this enum (boxed), or else an
146 // untranslated `H::Expr`. Note that instances of `Expr` are very
147 // shortlived. They are created by `Hair::to_expr`, analyzed and
148 // converted into MIR, and then discarded.
150 // If you compare `Expr` to the full compiler AST, you will see it is
151 // a good bit simpler. In fact, a number of the more straight-forward
152 // MIR simplifications are already done in the impl of `Hair`. For
153 // example, method calls and overloaded operators are absent: they are
154 // expected to be converted into `Expr::Call` instances.
155 #[derive(Clone, Debug)]
156 pub struct Expr<H:Hair> {
157 // type of this expression
160 // lifetime of this expression if it should be spilled into a
161 // temporary; should be None only if in a constant context
162 pub temp_lifetime: Option<H::CodeExtent>,
164 // span of the expression in the source
167 // kind of expression
168 pub kind: ExprKind<H>,
171 #[derive(Clone, Debug)]
172 pub enum ExprKind<H:Hair> {
173 Scope { extent: H::CodeExtent, value: ExprRef<H> },
174 Paren { arg: ExprRef<H> }, // ugh. should be able to remove this!
175 Box { place: Option<ExprRef<H>>, value: ExprRef<H> },
176 Call { fun: ExprRef<H>, args: Vec<ExprRef<H>> },
177 Deref { arg: ExprRef<H> }, // NOT overloaded!
178 Binary { op: BinOp, lhs: ExprRef<H>, rhs: ExprRef<H> }, // NOT overloaded!
179 LogicalOp { op: LogicalOp, lhs: ExprRef<H>, rhs: ExprRef<H> },
180 Unary { op: UnOp, arg: ExprRef<H> }, // NOT overloaded!
181 Cast { source: ExprRef<H> },
182 ReifyFnPointer { source: ExprRef<H> },
183 UnsafeFnPointer { source: ExprRef<H> },
184 Unsize { source: ExprRef<H> },
185 If { condition: ExprRef<H>, then: ExprRef<H>, otherwise: Option<ExprRef<H>> },
186 Loop { condition: Option<ExprRef<H>>, body: ExprRef<H>, },
187 Match { discriminant: ExprRef<H>, arms: Vec<Arm<H>> },
188 Block { body: H::Block },
189 Assign { lhs: ExprRef<H>, rhs: ExprRef<H> },
190 AssignOp { op: BinOp, lhs: ExprRef<H>, rhs: ExprRef<H> },
191 Field { lhs: ExprRef<H>, name: Field<H> },
192 Index { lhs: ExprRef<H>, index: ExprRef<H> },
193 VarRef { id: H::VarId },
194 SelfRef, // first argument, used for self in a closure
195 StaticRef { id: H::DefId },
196 Borrow { region: H::Region, borrow_kind: BorrowKind, arg: ExprRef<H> },
197 Break { label: Option<H::CodeExtent> },
198 Continue { label: Option<H::CodeExtent> },
199 Return { value: Option<ExprRef<H>> },
200 Repeat { value: ExprRef<H>, count: ExprRef<H> },
201 Vec { fields: Vec<ExprRef<H>> },
202 Tuple { fields: Vec<ExprRef<H>> },
203 Adt { adt_def: H::AdtDef,
204 variant_index: usize,
206 fields: Vec<FieldExprRef<H>>,
207 base: Option<ExprRef<H>> },
208 Closure { closure_id: H::DefId, substs: H::ClosureSubsts,
209 upvars: Vec<ExprRef<H>> },
210 Literal { literal: Literal<H> },
211 InlineAsm { asm: H::InlineAsm },
214 #[derive(Clone, Debug)]
215 pub enum ExprRef<H:Hair> {
217 Mirror(Box<Expr<H>>),
220 #[derive(Clone, Debug)]
221 pub struct FieldExprRef<H:Hair> {
223 pub expr: ExprRef<H>,
226 #[derive(Clone, Debug)]
227 pub struct Arm<H:Hair> {
228 pub patterns: Vec<PatternRef<H>>,
229 pub guard: Option<ExprRef<H>>,
230 pub body: ExprRef<H>,
233 #[derive(Clone, Debug)]
234 pub struct Pattern<H:Hair> {
237 pub kind: PatternKind<H>,
240 #[derive(Copy, Clone, Debug)]
246 #[derive(Clone, Debug)]
247 pub enum PatternKind<H:Hair> {
250 // x, ref x, x @ P, etc
251 Binding { mutability: Mutability,
253 mode: BindingMode<H>,
256 subpattern: Option<PatternRef<H>> },
258 // Foo(...) or Foo{...} or Foo, where `Foo` is a variant name from an adt with >1 variants
259 Variant { adt_def: H::AdtDef, variant_index: usize, subpatterns: Vec<FieldPatternRef<H>> },
261 // (...), Foo(...), Foo{...}, or Foo, where `Foo` is a variant name from an adt with 1 variant
262 Leaf { subpatterns: Vec<FieldPatternRef<H>> },
264 Deref { subpattern: PatternRef<H> }, // box P, &P, &mut P, etc
266 Constant { expr: ExprRef<H> },
268 Range { lo: ExprRef<H>, hi: ExprRef<H> },
270 // matches against a slice, checking the length and extracting elements
271 Slice { prefix: Vec<PatternRef<H>>,
272 slice: Option<PatternRef<H>>,
273 suffix: Vec<PatternRef<H>> },
275 // fixed match against an array, irrefutable
276 Array { prefix: Vec<PatternRef<H>>,
277 slice: Option<PatternRef<H>>,
278 suffix: Vec<PatternRef<H>> },
281 #[derive(Copy, Clone, Debug)]
282 pub enum BindingMode<H:Hair> {
284 ByRef(H::Region, BorrowKind),
287 #[derive(Clone, Debug)]
288 pub enum PatternRef<H:Hair> {
290 Mirror(Box<Pattern<H>>),
293 #[derive(Clone, Debug)]
294 pub struct FieldPatternRef<H:Hair> {
296 pub pattern: PatternRef<H>,
299 ///////////////////////////////////////////////////////////////////////////
302 /// "Mirroring" is the process of converting from a Hair type into one
303 /// of the types in this file. For example, the mirror of a `H::Expr`
304 /// is an `Expr<H>`. Mirroring is the point at which the actual IR is
305 /// converting into the more idealized representation described in
306 /// this file. Mirroring is gradual: when you mirror an outer
307 /// expression like `e1 + e2`, the references to the inner expressions
308 /// `e1` and `e2` are `ExprRef<H>` instances, and they may or may not
309 /// be eagerly mirrored. This allows a single AST node from the
310 /// compiler to expand into one or more Hair nodes, which lets the Hair
311 /// nodes be simpler.
312 pub trait Mirror<H:Hair> {
315 fn make_mirror(self, hir: &mut H) -> Self::Output;
318 impl<H:Hair> Mirror<H> for Expr<H> {
319 type Output = Expr<H>;
321 fn make_mirror(self, _: &mut H) -> Expr<H> {
326 impl<H:Hair> Mirror<H> for ExprRef<H> {
327 type Output = Expr<H>;
329 fn make_mirror(self, hir: &mut H) -> Expr<H> {
331 ExprRef::Hair(h) => h.make_mirror(hir),
332 ExprRef::Mirror(m) => *m,
337 impl<H:Hair> Mirror<H> for Stmt<H> {
338 type Output = Stmt<H>;
340 fn make_mirror(self, _: &mut H) -> Stmt<H> {
345 impl<H:Hair> Mirror<H> for StmtRef<H> {
346 type Output = Stmt<H>;
348 fn make_mirror(self, hir: &mut H) -> Stmt<H> {
350 StmtRef::Hair(h) => h.make_mirror(hir),
351 StmtRef::Mirror(m) => *m,
356 impl<H:Hair> Mirror<H> for Pattern<H> {
357 type Output = Pattern<H>;
359 fn make_mirror(self, _: &mut H) -> Pattern<H> {
364 impl<H:Hair> Mirror<H> for PatternRef<H> {
365 type Output = Pattern<H>;
367 fn make_mirror(self, hir: &mut H) -> Pattern<H> {
369 PatternRef::Hair(h) => h.make_mirror(hir),
370 PatternRef::Mirror(m) => *m,
375 impl<H:Hair> Mirror<H> for Block<H> {
376 type Output = Block<H>;
378 fn make_mirror(self, _: &mut H) -> Block<H> {