]> git.lizzy.rs Git - rust.git/blob - src/librustc_mir/hair/cx/block.rs
b63bf4bc2468480b952afc5dfa9af502f7430fb9
[rust.git] / src / librustc_mir / hair / cx / block.rs
1 use crate::hair::{self, *};
2 use crate::hair::cx::Cx;
3 use crate::hair::cx::to_ref::ToRef;
4 use rustc::middle::region;
5 use rustc::hir;
6 use rustc::ty;
7
8 use rustc_data_structures::indexed_vec::Idx;
9
10 impl<'tcx> Mirror<'tcx> for &'tcx hir::Block {
11     type Output = Block<'tcx>;
12
13     fn make_mirror<'a, 'gcx>(self, cx: &mut Cx<'a, 'gcx, 'tcx>) -> Block<'tcx> {
14         // We have to eagerly lower the "spine" of the statements
15         // in order to get the lexical scoping correctly.
16         let stmts = mirror_stmts(cx, self.hir_id.local_id, &*self.stmts);
17         let opt_destruction_scope =
18             cx.region_scope_tree.opt_destruction_scope(self.hir_id.local_id);
19         Block {
20             targeted_by_break: self.targeted_by_break,
21             region_scope: region::Scope {
22                 id: self.hir_id.local_id,
23                 data: region::ScopeData::Node
24             },
25             opt_destruction_scope,
26             span: self.span,
27             stmts,
28             expr: self.expr.to_ref(),
29             safety_mode: match self.rules {
30                 hir::BlockCheckMode::DefaultBlock =>
31                     BlockSafety::Safe,
32                 hir::BlockCheckMode::UnsafeBlock(..) =>
33                     BlockSafety::ExplicitUnsafe(self.hir_id),
34                 hir::BlockCheckMode::PushUnsafeBlock(..) =>
35                     BlockSafety::PushUnsafe,
36                 hir::BlockCheckMode::PopUnsafeBlock(..) =>
37                     BlockSafety::PopUnsafe
38             },
39         }
40     }
41 }
42
43 fn mirror_stmts<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
44                                 block_id: hir::ItemLocalId,
45                                 stmts: &'tcx [hir::Stmt])
46                                 -> Vec<StmtRef<'tcx>> {
47     let mut result = vec![];
48     for (index, stmt) in stmts.iter().enumerate() {
49         let hir_id = stmt.hir_id;
50         let opt_dxn_ext = cx.region_scope_tree.opt_destruction_scope(hir_id.local_id);
51         let stmt_span = StatementSpan(cx.tcx.hir().span_by_hir_id(hir_id));
52         match stmt.node {
53             hir::StmtKind::Expr(ref expr) |
54             hir::StmtKind::Semi(ref expr) => {
55                 result.push(StmtRef::Mirror(Box::new(Stmt {
56                     kind: StmtKind::Expr {
57                         scope: region::Scope {
58                             id: hir_id.local_id,
59                             data: region::ScopeData::Node
60                         },
61                         expr: expr.to_ref(),
62                     },
63                     opt_destruction_scope: opt_dxn_ext,
64                     span: stmt_span,
65                 })))
66             }
67             hir::StmtKind::Item(..) => {
68                 // ignore for purposes of the MIR
69             }
70             hir::StmtKind::Local(ref local) => {
71                 let remainder_scope = region::Scope {
72                     id: block_id,
73                     data: region::ScopeData::Remainder(
74                         region::FirstStatementIndex::new(index)),
75                 };
76
77                 let mut pattern = cx.pattern_from_hir(&local.pat);
78
79                 if let Some(ty) = &local.ty {
80                     if let Some(&user_ty) = cx.tables.user_provided_types().get(ty.hir_id) {
81                         debug!("mirror_stmts: user_ty={:?}", user_ty);
82                         pattern = Pattern {
83                             ty: pattern.ty,
84                             span: pattern.span,
85                             kind: Box::new(PatternKind::AscribeUserType {
86                                 ascription: hair::pattern::Ascription {
87                                     user_ty: PatternTypeProjection::from_user_type(user_ty),
88                                     user_ty_span: ty.span,
89                                     variance: ty::Variance::Covariant,
90                                 },
91                                 subpattern: pattern,
92                             })
93                         };
94                     }
95                 }
96
97                 result.push(StmtRef::Mirror(Box::new(Stmt {
98                     kind: StmtKind::Let {
99                         remainder_scope: remainder_scope,
100                         init_scope: region::Scope {
101                             id: hir_id.local_id,
102                             data: region::ScopeData::Node
103                         },
104                         pattern,
105                         initializer: local.init.to_ref(),
106                         lint_level: cx.lint_level_of(local.id),
107                     },
108                     opt_destruction_scope: opt_dxn_ext,
109                     span: stmt_span,
110                 })));
111             }
112         }
113     }
114     return result;
115 }
116
117 pub fn to_expr_ref<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
118                                    block: &'tcx hir::Block)
119                                    -> ExprRef<'tcx> {
120     let block_ty = cx.tables().node_type(block.hir_id);
121     let temp_lifetime = cx.region_scope_tree.temporary_scope(block.hir_id.local_id);
122     let expr = Expr {
123         ty: block_ty,
124         temp_lifetime,
125         span: block.span,
126         kind: ExprKind::Block { body: block },
127     };
128     expr.to_ref()
129 }