rustc_mir_build/thir/cx/
block.rs
1use rustc_hir as hir;
2use rustc_index::Idx;
3use rustc_middle::middle::region;
4use rustc_middle::thir::*;
5use rustc_middle::ty;
6use rustc_middle::ty::CanonicalUserTypeAnnotation;
7use tracing::debug;
8
9use crate::thir::cx::ThirBuildCx;
10
11impl<'tcx> ThirBuildCx<'tcx> {
12 pub(crate) fn mirror_block(&mut self, block: &'tcx hir::Block<'tcx>) -> BlockId {
13 let stmts = self.mirror_stmts(block.hir_id.local_id, block.stmts);
16 let block = Block {
17 targeted_by_break: block.targeted_by_break,
18 region_scope: region::Scope {
19 local_id: block.hir_id.local_id,
20 data: region::ScopeData::Node,
21 },
22 span: block.span,
23 stmts,
24 expr: block.expr.map(|expr| self.mirror_expr(expr)),
25 safety_mode: match block.rules {
26 hir::BlockCheckMode::DefaultBlock => BlockSafety::Safe,
27 hir::BlockCheckMode::UnsafeBlock(hir::UnsafeSource::CompilerGenerated) => {
28 BlockSafety::BuiltinUnsafe
29 }
30 hir::BlockCheckMode::UnsafeBlock(hir::UnsafeSource::UserProvided) => {
31 BlockSafety::ExplicitUnsafe(block.hir_id)
32 }
33 },
34 };
35
36 self.thir.blocks.push(block)
37 }
38
39 fn mirror_stmts(
40 &mut self,
41 block_id: hir::ItemLocalId,
42 stmts: &'tcx [hir::Stmt<'tcx>],
43 ) -> Box<[StmtId]> {
44 stmts
45 .iter()
46 .enumerate()
47 .filter_map(|(index, stmt)| {
48 let hir_id = stmt.hir_id;
49 match stmt.kind {
50 hir::StmtKind::Expr(expr) | hir::StmtKind::Semi(expr) => {
51 let stmt = Stmt {
52 kind: StmtKind::Expr {
53 scope: region::Scope {
54 local_id: hir_id.local_id,
55 data: region::ScopeData::Node,
56 },
57 expr: self.mirror_expr(expr),
58 },
59 };
60 Some(self.thir.stmts.push(stmt))
61 }
62 hir::StmtKind::Item(..) => {
63 None
65 }
66 hir::StmtKind::Let(local) => {
67 let remainder_scope = region::Scope {
68 local_id: block_id,
69 data: region::ScopeData::Remainder(region::FirstStatementIndex::new(
70 index,
71 )),
72 };
73
74 let else_block = local.els.map(|els| self.mirror_block(els));
75
76 let mut pattern = self.pattern_from_hir(local.pat);
77 debug!(?pattern);
78
79 if let Some(ty) = &local.ty {
80 if let Some(&user_ty) =
81 self.typeck_results.user_provided_types().get(ty.hir_id)
82 {
83 debug!("mirror_stmts: user_ty={:?}", user_ty);
84 let annotation = CanonicalUserTypeAnnotation {
85 user_ty: Box::new(user_ty),
86 span: ty.span,
87 inferred_ty: self.typeck_results.node_type(ty.hir_id),
88 };
89 pattern = Box::new(Pat {
90 ty: pattern.ty,
91 span: pattern.span,
92 kind: PatKind::AscribeUserType {
93 ascription: Ascription {
94 annotation,
95 variance: ty::Covariant,
96 },
97 subpattern: pattern,
98 },
99 });
100 }
101 }
102
103 let span = match local.init {
104 Some(init) => local.span.with_hi(init.span.hi()),
105 None => local.span,
106 };
107 let stmt = Stmt {
108 kind: StmtKind::Let {
109 remainder_scope,
110 init_scope: region::Scope {
111 local_id: hir_id.local_id,
112 data: region::ScopeData::Node,
113 },
114 pattern,
115 initializer: local.init.map(|init| self.mirror_expr(init)),
116 else_block,
117 lint_level: LintLevel::Explicit(local.hir_id),
118 span,
119 },
120 };
121 Some(self.thir.stmts.push(stmt))
122 }
123 }
124 })
125 .collect()
126 }
127}