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