Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rollup of 6 pull requests #103083

Merged
merged 22 commits into from
Oct 15, 2022
Merged
Changes from 1 commit
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
99182dd
std: use semaphore for thread parking on Apple platforms
joboet Oct 6, 2022
0ad4dd4
std: add thread parking tests
joboet Oct 6, 2022
b4c8a7b
std: remove unused linker attribute
joboet Oct 8, 2022
c320ab9
std: do not use dispatch semaphore under miri (yet)
joboet Oct 8, 2022
ad8b242
Let chains should still drop temporaries
nathanwhit Oct 12, 2022
e8a6e60
resolve: Add some asserts for unexpected lifetime rib combinations
petrochenkov Oct 9, 2022
e94ec30
resolve: Remove redundant item lifetime ribs
petrochenkov Oct 10, 2022
f634106
resolve: Regroup lifetime rib kinds to account for their purpose
petrochenkov Oct 10, 2022
709a08a
Lower condition directly from AST to HIR
nathanwhit Oct 14, 2022
4e1c09d
Validate MIR in the `drop_order` test
nathanwhit Oct 14, 2022
b841848
check if the self type is `ty::Float` before getting second substs
TaKO8Ki Oct 13, 2022
5378677
normalize stderr
TaKO8Ki Oct 13, 2022
40bb4b7
Update cargo
weihanglo Oct 14, 2022
f528414
Add missing checks for `doc(cfg_hide(...))` attribute
GuillaumeGomez Oct 12, 2022
6f0c247
Add UI test for invalid `doc(cfg_hide(...))` attributes
GuillaumeGomez Oct 12, 2022
062ea9c
remove no_core feature
TaKO8Ki Oct 14, 2022
cbe5e7b
Rollup merge of #102773 - joboet:apple_parker, r=thomcc
Dylan-DPC Oct 15, 2022
39ff2a6
Rollup merge of #102884 - petrochenkov:liferib, r=cjgillot
Dylan-DPC Oct 15, 2022
59e0af6
Rollup merge of #102954 - GuillaumeGomez:cfg-hide-attr-checks, r=Mani…
Dylan-DPC Oct 15, 2022
b79ad57
Rollup merge of #102998 - nathanwhit:let-chains-drop-order, r=eholk
Dylan-DPC Oct 15, 2022
65dca11
Rollup merge of #103003 - TaKO8Ki:fix-102989, r=compiler-errors
Dylan-DPC Oct 15, 2022
ac23c9f
Rollup merge of #103041 - weihanglo:update-cargo, r=ehuss
Dylan-DPC Oct 15, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Let chains should still drop temporaries
by the end of the condition's execution
nathanwhit committed Oct 13, 2022
commit ad8b24272428b28770471f222c19fa3154a65819
45 changes: 34 additions & 11 deletions compiler/rustc_ast_lowering/src/expr.rs
Original file line number Diff line number Diff line change
@@ -388,7 +388,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
else_opt: Option<&Expr>,
) -> hir::ExprKind<'hir> {
let lowered_cond = self.lower_expr(cond);
let new_cond = self.manage_let_cond(lowered_cond);
let new_cond = self.wrap_cond_in_drop_scope(lowered_cond);
let then_expr = self.lower_block_expr(then);
if let Some(rslt) = else_opt {
hir::ExprKind::If(new_cond, self.arena.alloc(then_expr), Some(self.lower_expr(rslt)))
@@ -397,22 +397,45 @@ impl<'hir> LoweringContext<'_, 'hir> {
}
}

// If `cond` kind is `let`, returns `let`. Otherwise, wraps and returns `cond`
// in a temporary block.
fn manage_let_cond(&mut self, cond: &'hir hir::Expr<'hir>) -> &'hir hir::Expr<'hir> {
// Wraps a condition (i.e. `cond` in `if cond` or `while cond`) in a terminating scope
// so that temporaries created in the condition don't live beyond it.
fn wrap_cond_in_drop_scope(&mut self, cond: &'hir hir::Expr<'hir>) -> &'hir hir::Expr<'hir> {
fn has_let_expr<'hir>(expr: &'hir hir::Expr<'hir>) -> bool {
match expr.kind {
hir::ExprKind::Binary(_, lhs, rhs) => has_let_expr(lhs) || has_let_expr(rhs),
hir::ExprKind::Let(..) => true,
_ => false,
}
}
if has_let_expr(cond) {
cond
} else {
let reason = DesugaringKind::CondTemporary;
let span_block = self.mark_span_with_reason(reason, cond.span, None);
self.expr_drop_temps(span_block, cond, AttrVec::new())

// We have to take special care for `let` exprs in the condition, e.g. in
// `if let pat = val` or `if foo && let pat = val`, as we _do_ want `val` to live beyond the
// condition in this case.
//
// In order to mantain the drop behavior for the non `let` parts of the condition,
// we still wrap them in terminating scopes, e.g. `if foo && let pat = val` essentially
// gets transformed into `if { let _t = foo; _t } && let pat = val`
match cond.kind {
hir::ExprKind::Binary(
op @ Spanned { node: hir::BinOpKind::And | hir::BinOpKind::Or, .. },
lhs,
rhs,
) if has_let_expr(cond) => {
let lhs = self.wrap_cond_in_drop_scope(lhs);
let rhs = self.wrap_cond_in_drop_scope(rhs);

self.arena.alloc(self.expr(
cond.span,
hir::ExprKind::Binary(op, lhs, rhs),
AttrVec::new(),
))
}
hir::ExprKind::Let(_) => cond,
_ => {
let reason = DesugaringKind::CondTemporary;
let span_block = self.mark_span_with_reason(reason, cond.span, None);
self.expr_drop_temps(span_block, cond, AttrVec::new())
}
}
}

@@ -440,7 +463,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
opt_label: Option<Label>,
) -> hir::ExprKind<'hir> {
let lowered_cond = self.with_loop_condition_scope(|t| t.lower_expr(cond));
let new_cond = self.manage_let_cond(lowered_cond);
let new_cond = self.wrap_cond_in_drop_scope(lowered_cond);
let then = self.lower_block_expr(body);
let expr_break = self.expr_break(span, AttrVec::new());
let stmt_break = self.stmt_expr(span, expr_break);
63 changes: 63 additions & 0 deletions src/test/ui/drop/drop_order.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// run-pass
#![feature(let_chains)]

use std::cell::RefCell;
use std::convert::TryInto;
@@ -116,6 +117,58 @@ impl DropOrderCollector {
}
}

fn let_chain(&self) {
// take the "then" branch
if self.option_loud_drop(2).is_some() // 2
&& self.option_loud_drop(1).is_some() // 1
&& let Some(_d) = self.option_loud_drop(4) { // 4
self.print(3); // 3
}

// take the "else" branch
if self.option_loud_drop(6).is_some() // 2
&& self.option_loud_drop(5).is_some() // 1
&& let None = self.option_loud_drop(7) { // 3
unreachable!();
} else {
self.print(8); // 4
}

// let exprs interspersed
if self.option_loud_drop(9).is_some() // 1
&& let Some(_d) = self.option_loud_drop(13) // 5
&& self.option_loud_drop(10).is_some() // 2
&& let Some(_e) = self.option_loud_drop(12) { // 4
self.print(11); // 3
}

// let exprs first
if let Some(_d) = self.option_loud_drop(18) // 5
&& let Some(_e) = self.option_loud_drop(17) // 4
&& self.option_loud_drop(14).is_some() // 1
&& self.option_loud_drop(15).is_some() { // 2
self.print(16); // 3
}

// let exprs last
if self.option_loud_drop(20).is_some() // 2
&& self.option_loud_drop(19).is_some() // 1
&& let Some(_d) = self.option_loud_drop(23) // 5
&& let Some(_e) = self.option_loud_drop(22) { // 4
self.print(21); // 3
}
}

fn while_(&self) {
let mut v = self.option_loud_drop(4);
while let Some(_d) = v
&& self.option_loud_drop(1).is_some()
&& self.option_loud_drop(2).is_some() {
self.print(3);
v = None;
}
}

fn assert_sorted(self) {
assert!(
self.0
@@ -142,4 +195,14 @@ fn main() {
let collector = DropOrderCollector::default();
collector.match_();
collector.assert_sorted();

println!("-- let chain --");
let collector = DropOrderCollector::default();
collector.let_chain();
collector.assert_sorted();

println!("-- while --");
let collector = DropOrderCollector::default();
collector.while_();
collector.assert_sorted();
}