1
Fork 0

preserve brackets around if-lets and skip while-lets

This commit is contained in:
Ding Xiang Fei 2024-09-30 03:40:48 +08:00
parent 329e7b4d4e
commit 6d1a25ad7e
No known key found for this signature in database
GPG key ID: 3CD748647EEF6359
4 changed files with 76 additions and 5 deletions

View file

@ -122,7 +122,11 @@ impl IfLetRescope {
}
let tcx = cx.tcx;
let source_map = tcx.sess.source_map();
let expr_end = expr.span.shrink_to_hi();
let expr_end = match expr.kind {
hir::ExprKind::If(_cond, conseq, None) => conseq.span.shrink_to_hi(),
hir::ExprKind::If(_cond, _conseq, Some(alt)) => alt.span.shrink_to_hi(),
_ => return,
};
let mut add_bracket_to_match_head = match_head_needs_bracket(tcx, expr);
let mut significant_droppers = vec![];
let mut lifetime_ends = vec![];
@ -145,7 +149,10 @@ impl IfLetRescope {
recovered: Recovered::No,
}) = cond.kind
{
let if_let_pat = expr.span.shrink_to_lo().between(init.span);
// Peel off round braces
let if_let_pat = source_map
.span_take_while(expr.span, |&ch| ch == '(' || ch.is_whitespace())
.between(init.span);
// The consequent fragment is always a block.
let before_conseq = conseq.span.shrink_to_lo();
let lifetime_end = source_map.end_point(conseq.span);
@ -159,6 +166,8 @@ impl IfLetRescope {
if ty_ascription.is_some()
|| !expr.span.can_be_used_for_suggestions()
|| !pat.span.can_be_used_for_suggestions()
|| !if_let_pat.can_be_used_for_suggestions()
|| !before_conseq.can_be_used_for_suggestions()
{
// Our `match` rewrites does not support type ascription,
// so we just bail.
@ -240,6 +249,22 @@ impl<'tcx> LateLintPass<'tcx> for IfLetRescope {
if let (Level::Allow, _) = cx.tcx.lint_level_at_node(IF_LET_RESCOPE, expr.hir_id) {
return;
}
if let hir::ExprKind::Loop(block, _label, hir::LoopSource::While, _span) = expr.kind
&& let Some(value) = block.expr
&& let hir::ExprKind::If(cond, _conseq, _alt) = value.kind
&& let hir::ExprKind::Let(..) = cond.kind
{
// Recall that `while let` is lowered into this:
// ```
// loop {
// if let .. { body } else { break; }
// }
// ```
// There is no observable from the `{ break; }` block so the edition change
// means nothing substantial to this `while` statement.
self.skip.insert(value.hir_id);
return;
}
if expr_parent_is_stmt(cx.tcx, expr.hir_id)
&& matches!(expr.kind, hir::ExprKind::If(_cond, _conseq, None))
{