1
Fork 0

reorder nesting scopes and declare bindings without drop schedule

This commit is contained in:
Ding Xiang Fei 2022-09-04 23:17:43 +08:00
parent 750bd1a7ff
commit 1b87ce0d40
No known key found for this signature in database
GPG key ID: 3CD748647EEF6359
5 changed files with 122 additions and 65 deletions

View file

@ -109,13 +109,99 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
)
);
}
StmtKind::Let {
remainder_scope,
init_scope,
pattern,
initializer: Some(initializer),
lint_level,
else_block: Some(else_block),
} => {
let ignores_expr_result = matches!(pattern.kind, PatKind::Wild);
this.block_context.push(BlockFrame::Statement { ignores_expr_result });
// This place is not really used because this destination place
// should never be used to take values at the end of the failure
// block.
let else_block_span = this.thir[*else_block].span;
let dummy_place = this.temp(this.tcx.types.never, else_block_span);
let failure_entry = this.cfg.start_new_block();
let failure_block;
unpack!(
failure_block = this.ast_block(
dummy_place,
failure_entry,
*else_block,
this.source_info(else_block_span),
)
);
this.cfg.terminate(
failure_block,
this.source_info(else_block_span),
TerminatorKind::Unreachable,
);
// Declare the bindings, which may create a source scope.
let remainder_span = remainder_scope.span(this.tcx, this.region_scope_tree);
this.push_scope((*remainder_scope, source_info));
let_scope_stack.push(remainder_scope);
let visibility_scope =
Some(this.new_source_scope(remainder_span, LintLevel::Inherited, None));
let init = &this.thir[*initializer];
let initializer_span = init.span;
this.declare_bindings(
visibility_scope,
remainder_span,
pattern,
ArmHasGuard(false),
Some((None, initializer_span)),
);
this.visit_primary_bindings(
pattern,
UserTypeProjections::none(),
&mut |this, _, _, _, node, span, _, _| {
this.storage_live_binding(block, node, span, OutsideGuard, false);
},
);
let failure = unpack!(
block = this.in_opt_scope(
opt_destruction_scope.map(|de| (de, source_info)),
|this| {
let scope = (*init_scope, source_info);
this.in_scope(scope, *lint_level, |this| {
this.ast_let_else(
block,
init,
initializer_span,
*else_block,
&last_remainder_scope,
pattern,
)
})
}
)
);
this.cfg.goto(failure, source_info, failure_entry);
if let Some(source_scope) = visibility_scope {
this.source_scope = source_scope;
}
last_remainder_scope = *remainder_scope;
}
StmtKind::Let { init_scope, initializer: None, else_block: Some(_), .. } => {
span_bug!(
init_scope.span(this.tcx, this.region_scope_tree),
"initializer is missing, but else block is present in this let binding",
)
}
StmtKind::Let {
remainder_scope,
init_scope,
ref pattern,
initializer,
lint_level,
else_block,
else_block: None,
} => {
let ignores_expr_result = matches!(pattern.kind, PatKind::Wild);
this.block_context.push(BlockFrame::Statement { ignores_expr_result });
@ -141,27 +227,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|this| {
let scope = (*init_scope, source_info);
this.in_scope(scope, *lint_level, |this| {
if let Some(else_block) = else_block {
this.ast_let_else(
block,
init,
initializer_span,
*else_block,
visibility_scope,
last_remainder_scope,
remainder_span,
pattern,
)
} else {
this.declare_bindings(
visibility_scope,
remainder_span,
pattern,
ArmHasGuard(false),
Some((None, initializer_span)),
);
this.expr_into_pattern(block, pattern, init) // irrefutable pattern
}
this.declare_bindings(
visibility_scope,
remainder_span,
pattern,
ArmHasGuard(false),
Some((None, initializer_span)),
);
this.expr_into_pattern(block, &pattern, init) // irrefutable pattern
})
},
)

View file

@ -699,7 +699,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
self.cfg.push(block, Statement { source_info, kind: StatementKind::StorageLive(local_id) });
// Although there is almost always scope for given variable in corner cases
// like #92893 we might get variable with no scope.
if let Some(region_scope) = self.region_scope_tree.var_scope(var.0.local_id) && schedule_drop{
if let Some(region_scope) = self.region_scope_tree.var_scope(var.0.local_id) && schedule_drop {
self.schedule_drop(span, region_scope, local_id, DropKind::Storage);
}
Place::from(local_id)
@ -2274,23 +2274,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
init: &Expr<'tcx>,
initializer_span: Span,
else_block: BlockId,
visibility_scope: Option<SourceScope>,
remainder_scope: region::Scope,
remainder_span: Span,
let_else_scope: &region::Scope,
pattern: &Pat<'tcx>,
) -> BlockAnd<()> {
) -> BlockAnd<BasicBlock> {
let else_block_span = self.thir[else_block].span;
let (matching, failure) = self.in_if_then_scope(remainder_scope, |this| {
let (matching, failure) = self.in_if_then_scope(*let_else_scope, |this| {
let scrutinee = unpack!(block = this.lower_scrutinee(block, init, initializer_span));
let pat = Pat { ty: init.ty, span: else_block_span, kind: PatKind::Wild };
let mut wildcard = Candidate::new(scrutinee.clone(), &pat, false);
this.declare_bindings(
visibility_scope,
remainder_span,
pattern,
ArmHasGuard(false),
Some((None, initializer_span)),
);
let mut candidate = Candidate::new(scrutinee.clone(), pattern, false);
let fake_borrow_temps = this.lower_match_tree(
block,
@ -2321,28 +2312,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
None,
None,
);
this.break_for_else(failure, remainder_scope, this.source_info(initializer_span));
this.break_for_else(failure, *let_else_scope, this.source_info(initializer_span));
matching.unit()
});
// This place is not really used because this destination place
// should never be used to take values at the end of the failure
// block.
let dummy_place = self.temp(self.tcx.types.never, else_block_span);
let failure_block;
unpack!(
failure_block = self.ast_block(
dummy_place,
failure,
else_block,
self.source_info(else_block_span),
)
);
self.cfg.terminate(
failure_block,
self.source_info(else_block_span),
TerminatorKind::Unreachable,
);
matching.unit()
matching.and(failure)
}
}