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