]> git.proxmox.com Git - rustc.git/blob - src/librustc_mir/hair/cx/block.rs
New upstream version 1.41.1+dfsg1
[rustc.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
5 use rustc::middle::region;
6 use rustc::hir;
7 use rustc::ty;
8
9 use rustc_index::vec::Idx;
10
11 impl<'tcx> Mirror<'tcx> for &'tcx hir::Block {
12 type Output = Block<'tcx>;
13
14 fn make_mirror(self, cx: &mut Cx<'_, 'tcx>) -> Block<'tcx> {
15 // We have to eagerly lower the "spine" of the statements
16 // in order to get the lexical scoping correctly.
17 let stmts = mirror_stmts(cx, self.hir_id.local_id, &*self.stmts);
18 let opt_destruction_scope =
19 cx.region_scope_tree.opt_destruction_scope(self.hir_id.local_id);
20 Block {
21 targeted_by_break: self.targeted_by_break,
22 region_scope: region::Scope {
23 id: self.hir_id.local_id,
24 data: region::ScopeData::Node
25 },
26 opt_destruction_scope,
27 span: self.span,
28 stmts,
29 expr: self.expr.to_ref(),
30 safety_mode: match self.rules {
31 hir::BlockCheckMode::DefaultBlock =>
32 BlockSafety::Safe,
33 hir::BlockCheckMode::UnsafeBlock(..) =>
34 BlockSafety::ExplicitUnsafe(self.hir_id),
35 hir::BlockCheckMode::PushUnsafeBlock(..) =>
36 BlockSafety::PushUnsafe,
37 hir::BlockCheckMode::PopUnsafeBlock(..) =>
38 BlockSafety::PopUnsafe
39 },
40 }
41 }
42 }
43
44 fn mirror_stmts<'a, 'tcx>(
45 cx: &mut Cx<'a, 'tcx>,
46 block_id: hir::ItemLocalId,
47 stmts: &'tcx [hir::Stmt],
48 ) -> Vec<StmtRef<'tcx>> {
49 let mut result = vec![];
50 for (index, stmt) in stmts.iter().enumerate() {
51 let hir_id = stmt.hir_id;
52 let opt_dxn_ext = cx.region_scope_tree.opt_destruction_scope(hir_id.local_id);
53 match stmt.kind {
54 hir::StmtKind::Expr(ref expr) |
55 hir::StmtKind::Semi(ref expr) => {
56 result.push(StmtRef::Mirror(Box::new(Stmt {
57 kind: StmtKind::Expr {
58 scope: region::Scope {
59 id: hir_id.local_id,
60 data: region::ScopeData::Node
61 },
62 expr: expr.to_ref(),
63 },
64 opt_destruction_scope: opt_dxn_ext,
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 = Pat {
83 ty: pattern.ty,
84 span: pattern.span,
85 kind: Box::new(PatKind::AscribeUserType {
86 ascription: hair::pattern::Ascription {
87 user_ty: PatTyProj::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: LintLevel::Explicit(local.hir_id),
107 },
108 opt_destruction_scope: opt_dxn_ext,
109 })));
110 }
111 }
112 }
113 return result;
114 }
115
116 pub fn to_expr_ref<'a, 'tcx>(
117 cx: &mut Cx<'a, '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 }