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        // 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 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                        // ignore for purposes of the MIR
64                        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}