use crate::hair::{self, *}; use crate::hair::cx::Cx; use crate::hair::cx::to_ref::ToRef; use rustc::middle::region; use rustc::hir; use rustc::ty; use rustc_index::vec::Idx; impl<'tcx> Mirror<'tcx> for &'tcx hir::Block { type Output = Block<'tcx>; fn make_mirror(self, cx: &mut Cx<'_, 'tcx>) -> Block<'tcx> { // We have to eagerly lower the "spine" of the statements // in order to get the lexical scoping correctly. let stmts = mirror_stmts(cx, self.hir_id.local_id, &*self.stmts); let opt_destruction_scope = cx.region_scope_tree.opt_destruction_scope(self.hir_id.local_id); Block { targeted_by_break: self.targeted_by_break, region_scope: region::Scope { id: self.hir_id.local_id, data: region::ScopeData::Node }, opt_destruction_scope, span: self.span, stmts, expr: self.expr.to_ref(), safety_mode: match self.rules { hir::BlockCheckMode::DefaultBlock => BlockSafety::Safe, hir::BlockCheckMode::UnsafeBlock(..) => BlockSafety::ExplicitUnsafe(self.hir_id), hir::BlockCheckMode::PushUnsafeBlock(..) => BlockSafety::PushUnsafe, hir::BlockCheckMode::PopUnsafeBlock(..) => BlockSafety::PopUnsafe }, } } } fn mirror_stmts<'a, 'tcx>( cx: &mut Cx<'a, 'tcx>, block_id: hir::ItemLocalId, stmts: &'tcx [hir::Stmt], ) -> Vec> { let mut result = vec![]; for (index, stmt) in stmts.iter().enumerate() { let hir_id = stmt.hir_id; let opt_dxn_ext = cx.region_scope_tree.opt_destruction_scope(hir_id.local_id); match stmt.kind { hir::StmtKind::Expr(ref expr) | hir::StmtKind::Semi(ref expr) => { result.push(StmtRef::Mirror(Box::new(Stmt { kind: StmtKind::Expr { scope: region::Scope { id: hir_id.local_id, data: region::ScopeData::Node }, expr: expr.to_ref(), }, opt_destruction_scope: opt_dxn_ext, }))) } hir::StmtKind::Item(..) => { // ignore for purposes of the MIR } hir::StmtKind::Local(ref local) => { let remainder_scope = region::Scope { id: block_id, data: region::ScopeData::Remainder( region::FirstStatementIndex::new(index)), }; let mut pattern = cx.pattern_from_hir(&local.pat); if let Some(ty) = &local.ty { if let Some(&user_ty) = cx.tables.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: hair::pattern::Ascription { user_ty: PatTyProj::from_user_type(user_ty), user_ty_span: ty.span, variance: ty::Variance::Covariant, }, subpattern: pattern, }) }; } } result.push(StmtRef::Mirror(Box::new(Stmt { kind: StmtKind::Let { remainder_scope: remainder_scope, init_scope: region::Scope { id: hir_id.local_id, data: region::ScopeData::Node }, pattern, initializer: local.init.to_ref(), lint_level: LintLevel::Explicit(local.hir_id), }, opt_destruction_scope: opt_dxn_ext, }))); } } } return result; } pub fn to_expr_ref<'a, 'tcx>( cx: &mut Cx<'a, 'tcx>, block: &'tcx hir::Block, ) -> ExprRef<'tcx> { let block_ty = cx.tables().node_type(block.hir_id); let temp_lifetime = cx.region_scope_tree.temporary_scope(block.hir_id.local_id); let expr = Expr { ty: block_ty, temp_lifetime, span: block.span, kind: ExprKind::Block { body: block }, }; expr.to_ref() }