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
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;

impl<'tcx> Cx<'tcx> {
    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);

                        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);
                                pattern = Pat {
                                    ty: pattern.ty,
                                    span: pattern.span,
                                    kind: Box::new(PatKind::AscribeUserType {
                                        ascription: Ascription {
                                            user_ty: PatTyProj::from_user_type(user_ty),
                                            user_ty_span: ty.span,
                                            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()
    }
}