forked from rust-lang/rust
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathblock.rs
123 lines (116 loc) · 5.17 KB
/
block.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
use crate::thir::cx::Cx;
use rustc_hir as hir;
use rustc_middle::middle::region;
use rustc_middle::thir::*;
use rustc_middle::ty;
use rustc_index::vec::Idx;
use rustc_middle::ty::CanonicalUserTypeAnnotation;
impl<'tcx> Cx<'tcx> {
pub(crate) fn mirror_block(&mut self, block: &'tcx hir::Block<'tcx>) -> Block {
// We have to eagerly lower the "spine" of the statements
// in order to get the lexical scoping correctly.
let stmts = self.mirror_stmts(block.hir_id.local_id, block.stmts);
let opt_destruction_scope =
self.region_scope_tree.opt_destruction_scope(block.hir_id.local_id);
Block {
targeted_by_break: block.targeted_by_break,
region_scope: region::Scope {
id: block.hir_id.local_id,
data: region::ScopeData::Node,
},
opt_destruction_scope,
span: block.span,
stmts,
expr: block.expr.map(|expr| self.mirror_expr(expr)),
safety_mode: match block.rules {
hir::BlockCheckMode::DefaultBlock => BlockSafety::Safe,
hir::BlockCheckMode::UnsafeBlock(hir::UnsafeSource::CompilerGenerated) => {
BlockSafety::BuiltinUnsafe
}
hir::BlockCheckMode::UnsafeBlock(hir::UnsafeSource::UserProvided) => {
BlockSafety::ExplicitUnsafe(block.hir_id)
}
},
}
}
fn mirror_stmts(
&mut self,
block_id: hir::ItemLocalId,
stmts: &'tcx [hir::Stmt<'tcx>],
) -> Box<[StmtId]> {
stmts
.iter()
.enumerate()
.filter_map(|(index, stmt)| {
let hir_id = stmt.hir_id;
let opt_dxn_ext = self.region_scope_tree.opt_destruction_scope(hir_id.local_id);
match stmt.kind {
hir::StmtKind::Expr(ref expr) | hir::StmtKind::Semi(ref expr) => {
let stmt = Stmt {
kind: StmtKind::Expr {
scope: region::Scope {
id: hir_id.local_id,
data: region::ScopeData::Node,
},
expr: self.mirror_expr(expr),
},
opt_destruction_scope: opt_dxn_ext,
};
Some(self.thir.stmts.push(stmt))
}
hir::StmtKind::Item(..) => {
// ignore for purposes of the MIR
None
}
hir::StmtKind::Local(ref local) => {
let remainder_scope = region::Scope {
id: block_id,
data: region::ScopeData::Remainder(region::FirstStatementIndex::new(
index,
)),
};
let mut pattern = self.pattern_from_hir(local.pat);
debug!(?pattern);
if let Some(ty) = &local.ty {
if let Some(&user_ty) =
self.typeck_results.user_provided_types().get(ty.hir_id)
{
debug!("mirror_stmts: user_ty={:?}", user_ty);
let annotation = CanonicalUserTypeAnnotation {
user_ty,
span: ty.span,
inferred_ty: self.typeck_results.node_type(ty.hir_id),
};
pattern = Pat {
ty: pattern.ty,
span: pattern.span,
kind: Box::new(PatKind::AscribeUserType {
ascription: Ascription {
annotation,
variance: ty::Variance::Covariant,
},
subpattern: pattern,
}),
};
}
}
let stmt = Stmt {
kind: StmtKind::Let {
remainder_scope,
init_scope: region::Scope {
id: hir_id.local_id,
data: region::ScopeData::Node,
},
pattern,
initializer: local.init.map(|init| self.mirror_expr(init)),
lint_level: LintLevel::Explicit(local.hir_id),
},
opt_destruction_scope: opt_dxn_ext,
};
Some(self.thir.stmts.push(stmt))
}
}
})
.collect()
}
}