]> git.proxmox.com Git - rustc.git/blob - src/librustc_mir/hair/cx/block.rs
New upstream version 1.29.0+dfsg1
[rustc.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::{self, BlockRemainder};
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::Node(self.hir_id.local_id),
31 opt_destruction_scope,
32 span: self.span,
33 stmts,
34 expr: self.expr.to_ref(),
35 safety_mode: match self.rules {
36 hir::BlockCheckMode::DefaultBlock =>
37 BlockSafety::Safe,
38 hir::BlockCheckMode::UnsafeBlock(..) =>
39 BlockSafety::ExplicitUnsafe(self.id),
40 hir::BlockCheckMode::PushUnsafeBlock(..) =>
41 BlockSafety::PushUnsafe,
42 hir::BlockCheckMode::PopUnsafeBlock(..) =>
43 BlockSafety::PopUnsafe
44 },
45 }
46 }
47 }
48
49 fn mirror_stmts<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
50 block_id: hir::ItemLocalId,
51 stmts: &'tcx [hir::Stmt])
52 -> Vec<StmtRef<'tcx>> {
53 let mut result = vec![];
54 for (index, stmt) in stmts.iter().enumerate() {
55 let hir_id = cx.tcx.hir.node_to_hir_id(stmt.node.id());
56 let opt_dxn_ext = cx.region_scope_tree.opt_destruction_scope(hir_id.local_id);
57 match stmt.node {
58 hir::StmtKind::Expr(ref expr, _) |
59 hir::StmtKind::Semi(ref expr, _) => {
60 result.push(StmtRef::Mirror(Box::new(Stmt {
61 kind: StmtKind::Expr {
62 scope: region::Scope::Node(hir_id.local_id),
63 expr: expr.to_ref(),
64 },
65 opt_destruction_scope: opt_dxn_ext,
66 })))
67 }
68 hir::StmtKind::Decl(ref decl, _) => {
69 match decl.node {
70 hir::DeclKind::Item(..) => {
71 // ignore for purposes of the MIR
72 }
73 hir::DeclKind::Local(ref local) => {
74 let remainder_scope = region::Scope::Remainder(BlockRemainder {
75 block: block_id,
76 first_statement_index: region::FirstStatementIndex::new(index),
77 });
78
79 let ty = local.ty.clone().map(|ty| ty.hir_id);
80 let pattern = cx.pattern_from_hir(&local.pat);
81 result.push(StmtRef::Mirror(Box::new(Stmt {
82 kind: StmtKind::Let {
83 remainder_scope: remainder_scope,
84 init_scope: region::Scope::Node(hir_id.local_id),
85 pattern,
86 ty,
87 initializer: local.init.to_ref(),
88 lint_level: cx.lint_level_of(local.id),
89 },
90 opt_destruction_scope: opt_dxn_ext,
91 })));
92 }
93 }
94 }
95 }
96 }
97 return result;
98 }
99
100 pub fn to_expr_ref<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
101 block: &'tcx hir::Block)
102 -> ExprRef<'tcx> {
103 let block_ty = cx.tables().node_id_to_type(block.hir_id);
104 let temp_lifetime = cx.region_scope_tree.temporary_scope(block.hir_id.local_id);
105 let expr = Expr {
106 ty: block_ty,
107 temp_lifetime,
108 span: block.span,
109 kind: ExprKind::Block { body: block },
110 };
111 expr.to_ref()
112 }