Auto merge of #4123 - Centril:rustup-let-chains-ast, r=Manishearth
Fix fallout from rust-lang/rust PR 60861 Fixes incoming breakage for unlanded https://github.com/rust-lang/rust/pull/60861. Tests are passing locally; the Rust PR now needs to land first. @Manishearth also says we'll want to split out to a `collapsible_if_let` once we have let-chains working in Rust nightly or something.
This commit is contained in:
@@ -84,18 +84,14 @@ impl EarlyLintPass for CollapsibleIf {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn check_if(cx: &EarlyContext<'_>, expr: &ast::Expr) {
|
fn check_if(cx: &EarlyContext<'_>, expr: &ast::Expr) {
|
||||||
match expr.node {
|
if let ast::ExprKind::If(check, then, else_) = &expr.node {
|
||||||
ast::ExprKind::If(ref check, ref then, ref else_) => {
|
if let Some(else_) = else_ {
|
||||||
if let Some(ref else_) = *else_ {
|
|
||||||
check_collapsible_maybe_if_let(cx, else_);
|
|
||||||
} else {
|
|
||||||
check_collapsible_no_if_let(cx, expr, check, then);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
ast::ExprKind::IfLet(_, _, _, Some(ref else_)) => {
|
|
||||||
check_collapsible_maybe_if_let(cx, else_);
|
check_collapsible_maybe_if_let(cx, else_);
|
||||||
},
|
} else if let ast::ExprKind::Let(..) = check.node {
|
||||||
_ => (),
|
// Prevent triggering on `if let a = b { if c { .. } }`.
|
||||||
|
} else {
|
||||||
|
check_collapsible_no_if_let(cx, expr, check, then);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -113,22 +109,18 @@ fn check_collapsible_maybe_if_let(cx: &EarlyContext<'_>, else_: &ast::Expr) {
|
|||||||
if !block_starts_with_comment(cx, block);
|
if !block_starts_with_comment(cx, block);
|
||||||
if let Some(else_) = expr_block(block);
|
if let Some(else_) = expr_block(block);
|
||||||
if !in_macro_or_desugar(else_.span);
|
if !in_macro_or_desugar(else_.span);
|
||||||
|
if let ast::ExprKind::If(..) = else_.node;
|
||||||
then {
|
then {
|
||||||
match else_.node {
|
let mut applicability = Applicability::MachineApplicable;
|
||||||
ast::ExprKind::If(..) | ast::ExprKind::IfLet(..) => {
|
span_lint_and_sugg(
|
||||||
let mut applicability = Applicability::MachineApplicable;
|
cx,
|
||||||
span_lint_and_sugg(
|
COLLAPSIBLE_IF,
|
||||||
cx,
|
block.span,
|
||||||
COLLAPSIBLE_IF,
|
"this `else { if .. }` block can be collapsed",
|
||||||
block.span,
|
"try",
|
||||||
"this `else { if .. }` block can be collapsed",
|
snippet_block_with_applicability(cx, else_.span, "..", &mut applicability).into_owned(),
|
||||||
"try",
|
applicability,
|
||||||
snippet_block_with_applicability(cx, else_.span, "..", &mut applicability).into_owned(),
|
);
|
||||||
applicability,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
_ => (),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -139,6 +131,11 @@ fn check_collapsible_no_if_let(cx: &EarlyContext<'_>, expr: &ast::Expr, check: &
|
|||||||
if let Some(inner) = expr_block(then);
|
if let Some(inner) = expr_block(then);
|
||||||
if let ast::ExprKind::If(ref check_inner, ref content, None) = inner.node;
|
if let ast::ExprKind::If(ref check_inner, ref content, None) = inner.node;
|
||||||
then {
|
then {
|
||||||
|
if let ast::ExprKind::Let(..) = check_inner.node {
|
||||||
|
// Prevent triggering on `if c { if let a = b { .. } }`.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if expr.span.ctxt() != inner.span.ctxt() {
|
if expr.span.ctxt() != inner.span.ctxt() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -248,9 +248,7 @@ fn is_block(expr: &ast::Expr) -> bool {
|
|||||||
/// Match `if` or `if let` expressions and return the `then` and `else` block.
|
/// Match `if` or `if let` expressions and return the `then` and `else` block.
|
||||||
fn unsugar_if(expr: &ast::Expr) -> Option<(&P<ast::Block>, &Option<P<ast::Expr>>)> {
|
fn unsugar_if(expr: &ast::Expr) -> Option<(&P<ast::Block>, &Option<P<ast::Expr>>)> {
|
||||||
match expr.node {
|
match expr.node {
|
||||||
ast::ExprKind::If(_, ref then, ref else_) | ast::ExprKind::IfLet(_, _, ref then, ref else_) => {
|
ast::ExprKind::If(_, ref then, ref else_) => Some((then, else_)),
|
||||||
Some((then, else_))
|
|
||||||
},
|
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,8 +50,6 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for IdentityConversion {
|
|||||||
};
|
};
|
||||||
if let ExprKind::Call(_, ref args) = e.node {
|
if let ExprKind::Call(_, ref args) = e.node {
|
||||||
self.try_desugar_arm.push(args[0].hir_id);
|
self.try_desugar_arm.push(args[0].hir_id);
|
||||||
} else {
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
@@ -209,12 +209,11 @@ fn with_loop_block<F>(expr: &ast::Expr, mut func: F)
|
|||||||
where
|
where
|
||||||
F: FnMut(&ast::Block, Option<&ast::Label>),
|
F: FnMut(&ast::Block, Option<&ast::Label>),
|
||||||
{
|
{
|
||||||
match expr.node {
|
if let ast::ExprKind::While(_, loop_block, label)
|
||||||
ast::ExprKind::While(_, ref loop_block, ref label)
|
| ast::ExprKind::ForLoop(_, _, loop_block, label)
|
||||||
| ast::ExprKind::WhileLet(_, _, ref loop_block, ref label)
|
| ast::ExprKind::Loop(loop_block, label) = &expr.node
|
||||||
| ast::ExprKind::ForLoop(_, _, ref loop_block, ref label)
|
{
|
||||||
| ast::ExprKind::Loop(ref loop_block, ref label) => func(loop_block, label.as_ref()),
|
func(loop_block, label.as_ref());
|
||||||
_ => {},
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -135,7 +135,7 @@ impl<'a> Sugg<'a> {
|
|||||||
| ast::ExprKind::Box(..)
|
| ast::ExprKind::Box(..)
|
||||||
| ast::ExprKind::Closure(..)
|
| ast::ExprKind::Closure(..)
|
||||||
| ast::ExprKind::If(..)
|
| ast::ExprKind::If(..)
|
||||||
| ast::ExprKind::IfLet(..)
|
| ast::ExprKind::Let(..)
|
||||||
| ast::ExprKind::Unary(..)
|
| ast::ExprKind::Unary(..)
|
||||||
| ast::ExprKind::Match(..) => Sugg::MaybeParen(snippet),
|
| ast::ExprKind::Match(..) => Sugg::MaybeParen(snippet),
|
||||||
ast::ExprKind::Async(..)
|
ast::ExprKind::Async(..)
|
||||||
@@ -162,7 +162,6 @@ impl<'a> Sugg<'a> {
|
|||||||
| ast::ExprKind::Tup(..)
|
| ast::ExprKind::Tup(..)
|
||||||
| ast::ExprKind::Array(..)
|
| ast::ExprKind::Array(..)
|
||||||
| ast::ExprKind::While(..)
|
| ast::ExprKind::While(..)
|
||||||
| ast::ExprKind::WhileLet(..)
|
|
||||||
| ast::ExprKind::Await(..)
|
| ast::ExprKind::Await(..)
|
||||||
| ast::ExprKind::Err => Sugg::NonParen(snippet),
|
| ast::ExprKind::Err => Sugg::NonParen(snippet),
|
||||||
ast::ExprKind::Range(.., RangeLimits::HalfOpen) => Sugg::BinOp(AssocOp::DotDot, snippet),
|
ast::ExprKind::Range(.., RangeLimits::HalfOpen) => Sugg::BinOp(AssocOp::DotDot, snippet),
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ pub fn is_potentially_mutated<'a, 'tcx>(variable: &'tcx Path, expr: &'tcx Expr,
|
|||||||
if let Res::Local(id) = variable.res {
|
if let Res::Local(id) = variable.res {
|
||||||
mutated_variables(expr, cx).map_or(true, |mutated| mutated.contains(&id))
|
mutated_variables(expr, cx).map_or(true, |mutated| mutated.contains(&id))
|
||||||
} else {
|
} else {
|
||||||
return true;
|
true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -172,4 +172,25 @@ else {
|
|||||||
println!("Hello world!");
|
println!("Hello world!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Test behavior wrt. `let_chains`.
|
||||||
|
// None of the cases below should be collapsed.
|
||||||
|
fn truth() -> bool { true }
|
||||||
|
|
||||||
|
// Prefix:
|
||||||
|
if let 0 = 1 {
|
||||||
|
if truth() {}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Suffix:
|
||||||
|
if truth() {
|
||||||
|
if let 0 = 1 {}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Midfix:
|
||||||
|
if truth() {
|
||||||
|
if let 0 = 1 {
|
||||||
|
if truth() {}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -200,4 +200,25 @@ fn main() {
|
|||||||
println!("Hello world!");
|
println!("Hello world!");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Test behavior wrt. `let_chains`.
|
||||||
|
// None of the cases below should be collapsed.
|
||||||
|
fn truth() -> bool { true }
|
||||||
|
|
||||||
|
// Prefix:
|
||||||
|
if let 0 = 1 {
|
||||||
|
if truth() {}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Suffix:
|
||||||
|
if truth() {
|
||||||
|
if let 0 = 1 {}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Midfix:
|
||||||
|
if truth() {
|
||||||
|
if let 0 = 1 {
|
||||||
|
if truth() {}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user