about summary refs log tree commit diff
diff options
context:
space:
mode:
authorSamuel Tardieu <sam@rfc1149.net>2025-02-16 16:05:02 +0100
committerSamuel Tardieu <sam@rfc1149.net>2025-03-22 15:12:42 +0100
commit82381608c993262b562e56b8b52ff47b42650c8e (patch)
treeb67f34a631f243eefb22bd65ce043acb31817df9
parente8e0126c1804d6c579ec747c32fe4200aaa49699 (diff)
downloadrust-82381608c993262b562e56b8b52ff47b42650c8e.tar.gz
rust-82381608c993262b562e56b8b52ff47b42650c8e.zip
Lint more cases in `collapsible_if`
Replace the use of `Sugg::ast()` which prevented combining `if`
together when they contained comments by span manipulation.

A new configuration option `lint_commented_code`, which is `true` by
default, opts out from this behavior.
-rw-r--r--CHANGELOG.md1
-rw-r--r--book/src/lint_configuration.md11
-rw-r--r--clippy_config/src/conf.rs4
-rw-r--r--clippy_lints/src/collapsible_if.rs186
-rw-r--r--clippy_lints/src/lib.rs2
-rw-r--r--tests/ui-toml/collapsible_if/clippy.toml1
-rw-r--r--tests/ui-toml/collapsible_if/collapsible_if.fixed34
-rw-r--r--tests/ui-toml/collapsible_if/collapsible_if.rs38
-rw-r--r--tests/ui-toml/collapsible_if/collapsible_if.stderr80
-rw-r--r--tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr3
-rw-r--r--tests/ui/collapsible_if.fixed102
-rw-r--r--tests/ui/collapsible_if.rs52
-rw-r--r--tests/ui/collapsible_if.stderr91
13 files changed, 410 insertions, 195 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 1bf4b51ff0f..1babf0bd614 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6362,6 +6362,7 @@ Released 2018-09-13
 [`future-size-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#future-size-threshold
 [`ignore-interior-mutability`]: https://doc.rust-lang.org/clippy/lint_configuration.html#ignore-interior-mutability
 [`large-error-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#large-error-threshold
+[`lint-commented-code`]: https://doc.rust-lang.org/clippy/lint_configuration.html#lint-commented-code
 [`lint-inconsistent-struct-field-initializers`]: https://doc.rust-lang.org/clippy/lint_configuration.html#lint-inconsistent-struct-field-initializers
 [`literal-representation-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#literal-representation-threshold
 [`matches-for-let-else`]: https://doc.rust-lang.org/clippy/lint_configuration.html#matches-for-let-else
diff --git a/book/src/lint_configuration.md b/book/src/lint_configuration.md
index 3726d6e8a86..36f3985fc02 100644
--- a/book/src/lint_configuration.md
+++ b/book/src/lint_configuration.md
@@ -613,6 +613,17 @@ The maximum size of the `Err`-variant in a `Result` returned from a function
 * [`result_large_err`](https://rust-lang.github.io/rust-clippy/master/index.html#result_large_err)
 
 
+## `lint-commented-code`
+Whether collapsible `if` chains are linted if they contain comments inside the parts
+that would be collapsed.
+
+**Default Value:** `false`
+
+---
+**Affected lints:**
+* [`collapsible_if`](https://rust-lang.github.io/rust-clippy/master/index.html#collapsible_if)
+
+
 ## `lint-inconsistent-struct-field-initializers`
 Whether to suggest reordering constructor fields when initializers are present.
 
diff --git a/clippy_config/src/conf.rs b/clippy_config/src/conf.rs
index 798f8b3aa5a..eeb462dedc9 100644
--- a/clippy_config/src/conf.rs
+++ b/clippy_config/src/conf.rs
@@ -549,6 +549,10 @@ define_Conf! {
     /// The maximum size of the `Err`-variant in a `Result` returned from a function
     #[lints(result_large_err)]
     large_error_threshold: u64 = 128,
+    /// Whether collapsible `if` chains are linted if they contain comments inside the parts
+    /// that would be collapsed.
+    #[lints(collapsible_if)]
+    lint_commented_code: bool = false,
     /// Whether to suggest reordering constructor fields when initializers are present.
     ///
     /// Warnings produced by this configuration aren't necessarily fixed by just reordering the fields. Even if the
diff --git a/clippy_lints/src/collapsible_if.rs b/clippy_lints/src/collapsible_if.rs
index e73bfc6ebf7..b100e2408de 100644
--- a/clippy_lints/src/collapsible_if.rs
+++ b/clippy_lints/src/collapsible_if.rs
@@ -1,10 +1,13 @@
+use clippy_config::Conf;
 use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then};
-use clippy_utils::source::{snippet, snippet_block, snippet_block_with_applicability};
-use clippy_utils::sugg::Sugg;
+use clippy_utils::source::{
+    HasSession, IntoSpan as _, SpanRangeExt, snippet, snippet_block, snippet_block_with_applicability,
+};
+use clippy_utils::span_contains_comment;
 use rustc_ast::ast;
 use rustc_errors::Applicability;
 use rustc_lint::{EarlyContext, EarlyLintPass};
-use rustc_session::declare_lint_pass;
+use rustc_session::impl_lint_pass;
 use rustc_span::Span;
 
 declare_clippy_lint! {
@@ -75,7 +78,95 @@ declare_clippy_lint! {
     "nested `else`-`if` expressions that can be collapsed (e.g., `else { if x { ... } }`)"
 }
 
-declare_lint_pass!(CollapsibleIf => [COLLAPSIBLE_IF, COLLAPSIBLE_ELSE_IF]);
+pub struct CollapsibleIf {
+    lint_commented_code: bool,
+}
+
+impl CollapsibleIf {
+    pub fn new(conf: &'static Conf) -> Self {
+        Self {
+            lint_commented_code: conf.lint_commented_code,
+        }
+    }
+
+    fn check_collapsible_else_if(cx: &EarlyContext<'_>, then_span: Span, else_: &ast::Expr) {
+        if let ast::ExprKind::Block(ref block, _) = else_.kind
+            && !block_starts_with_comment(cx, block)
+            && let Some(else_) = expr_block(block)
+            && else_.attrs.is_empty()
+            && !else_.span.from_expansion()
+            && let ast::ExprKind::If(..) = else_.kind
+        {
+            // Prevent "elseif"
+            // Check that the "else" is followed by whitespace
+            let up_to_else = then_span.between(block.span);
+            let requires_space = if let Some(c) = snippet(cx, up_to_else, "..").chars().last() {
+                !c.is_whitespace()
+            } else {
+                false
+            };
+
+            let mut applicability = Applicability::MachineApplicable;
+            span_lint_and_sugg(
+                cx,
+                COLLAPSIBLE_ELSE_IF,
+                block.span,
+                "this `else { if .. }` block can be collapsed",
+                "collapse nested if block",
+                format!(
+                    "{}{}",
+                    if requires_space { " " } else { "" },
+                    snippet_block_with_applicability(cx, else_.span, "..", Some(block.span), &mut applicability)
+                ),
+                applicability,
+            );
+        }
+    }
+
+    fn check_collapsible_if_if(&self, cx: &EarlyContext<'_>, expr: &ast::Expr, check: &ast::Expr, then: &ast::Block) {
+        if let Some(inner) = expr_block(then)
+            && inner.attrs.is_empty()
+            && let ast::ExprKind::If(check_inner, _, None) = &inner.kind
+            // Prevent triggering on `if c { if let a = b { .. } }`.
+            && !matches!(check_inner.kind, ast::ExprKind::Let(..))
+            && let ctxt = expr.span.ctxt()
+            && inner.span.ctxt() == ctxt
+            && let contains_comment = span_contains_comment(cx.sess().source_map(), check.span.to(check_inner.span))
+            && (!contains_comment || self.lint_commented_code)
+        {
+            span_lint_and_then(
+                cx,
+                COLLAPSIBLE_IF,
+                expr.span,
+                "this `if` statement can be collapsed",
+                |diag| {
+                    let then_open_bracket = then.span.split_at(1).0.with_leading_whitespace(cx).into_span();
+                    let then_closing_bracket = {
+                        let end = then.span.shrink_to_hi();
+                        end.with_lo(end.lo() - rustc_span::BytePos(1))
+                            .with_leading_whitespace(cx)
+                            .into_span()
+                    };
+                    let inner_if = inner.span.split_at(2).0;
+                    let mut sugg = vec![
+                        // Remove the outer then block `{`
+                        (then_open_bracket, String::new()),
+                        // Remove the outer then block '}'
+                        (then_closing_bracket, String::new()),
+                        // Replace inner `if` by `&&`
+                        (inner_if, String::from("&&")),
+                    ];
+                    sugg.extend(parens_around(check));
+                    sugg.extend(parens_around(check_inner));
+
+                    diag.multipart_suggestion("collapse nested if block", sugg, Applicability::MachineApplicable);
+                },
+            );
+        }
+    }
+}
+
+impl_lint_pass!(CollapsibleIf => [COLLAPSIBLE_IF, COLLAPSIBLE_ELSE_IF]);
 
 impl EarlyLintPass for CollapsibleIf {
     fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &ast::Expr) {
@@ -83,9 +174,10 @@ impl EarlyLintPass for CollapsibleIf {
             && !expr.span.from_expansion()
         {
             if let Some(else_) = else_ {
-                check_collapsible_maybe_if_let(cx, then.span, else_);
+                Self::check_collapsible_else_if(cx, then.span, else_);
             } else if !matches!(cond.kind, ast::ExprKind::Let(..)) {
-                check_collapsible_no_if_let(cx, expr, cond, then);
+                // Prevent triggering on `if c { if let a = b { .. } }`.
+                self.check_collapsible_if_if(cx, expr, cond, then);
             }
         }
     }
@@ -99,74 +191,6 @@ fn block_starts_with_comment(cx: &EarlyContext<'_>, expr: &ast::Block) -> bool {
     trimmed_block_text.starts_with("//") || trimmed_block_text.starts_with("/*")
 }
 
-fn check_collapsible_maybe_if_let(cx: &EarlyContext<'_>, then_span: Span, else_: &ast::Expr) {
-    if let ast::ExprKind::Block(ref block, _) = else_.kind
-        && !block_starts_with_comment(cx, block)
-        && let Some(else_) = expr_block(block)
-        && else_.attrs.is_empty()
-        && !else_.span.from_expansion()
-        && let ast::ExprKind::If(..) = else_.kind
-    {
-        // Prevent "elseif"
-        // Check that the "else" is followed by whitespace
-        let up_to_else = then_span.between(block.span);
-        let requires_space = if let Some(c) = snippet(cx, up_to_else, "..").chars().last() {
-            !c.is_whitespace()
-        } else {
-            false
-        };
-
-        let mut applicability = Applicability::MachineApplicable;
-        span_lint_and_sugg(
-            cx,
-            COLLAPSIBLE_ELSE_IF,
-            block.span,
-            "this `else { if .. }` block can be collapsed",
-            "collapse nested if block",
-            format!(
-                "{}{}",
-                if requires_space { " " } else { "" },
-                snippet_block_with_applicability(cx, else_.span, "..", Some(block.span), &mut applicability)
-            ),
-            applicability,
-        );
-    }
-}
-
-fn check_collapsible_no_if_let(cx: &EarlyContext<'_>, expr: &ast::Expr, check: &ast::Expr, then: &ast::Block) {
-    if !block_starts_with_comment(cx, then)
-        && let Some(inner) = expr_block(then)
-        && inner.attrs.is_empty()
-        && let ast::ExprKind::If(ref check_inner, ref content, None) = inner.kind
-        // Prevent triggering on `if c { if let a = b { .. } }`.
-        && !matches!(check_inner.kind, ast::ExprKind::Let(..))
-        && let ctxt = expr.span.ctxt()
-        && inner.span.ctxt() == ctxt
-    {
-        span_lint_and_then(
-            cx,
-            COLLAPSIBLE_IF,
-            expr.span,
-            "this `if` statement can be collapsed",
-            |diag| {
-                let mut app = Applicability::MachineApplicable;
-                let lhs = Sugg::ast(cx, check, "..", ctxt, &mut app);
-                let rhs = Sugg::ast(cx, check_inner, "..", ctxt, &mut app);
-                diag.span_suggestion(
-                    expr.span,
-                    "collapse nested if block",
-                    format!(
-                        "if {} {}",
-                        lhs.and(&rhs),
-                        snippet_block(cx, content.span, "..", Some(expr.span)),
-                    ),
-                    app, // snippet
-                );
-            },
-        );
-    }
-}
-
 /// If the block contains only one expression, return it.
 fn expr_block(block: &ast::Block) -> Option<&ast::Expr> {
     if let [stmt] = &*block.stmts
@@ -177,3 +201,17 @@ fn expr_block(block: &ast::Block) -> Option<&ast::Expr> {
         None
     }
 }
+
+/// If the expression is a `||`, suggest parentheses around it.
+fn parens_around(expr: &ast::Expr) -> Vec<(Span, String)> {
+    if let ast::ExprKind::Binary(op, _, _) = expr.kind
+        && op.node == ast::BinOpKind::Or
+    {
+        vec![
+            (expr.span.shrink_to_lo(), String::from("(")),
+            (expr.span.shrink_to_hi(), String::from(")")),
+        ]
+    } else {
+        vec![]
+    }
+}
diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs
index 3fe3cd67e16..2d390be5248 100644
--- a/clippy_lints/src/lib.rs
+++ b/clippy_lints/src/lib.rs
@@ -772,7 +772,7 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) {
     store.register_late_pass(|_| Box::new(redundant_closure_call::RedundantClosureCall));
     store.register_early_pass(|| Box::new(unused_unit::UnusedUnit));
     store.register_late_pass(|_| Box::new(returns::Return));
-    store.register_early_pass(|| Box::new(collapsible_if::CollapsibleIf));
+    store.register_early_pass(move || Box::new(collapsible_if::CollapsibleIf::new(conf)));
     store.register_late_pass(|_| Box::new(items_after_statements::ItemsAfterStatements));
     store.register_early_pass(|| Box::new(precedence::Precedence));
     store.register_late_pass(|_| Box::new(needless_parens_on_range_literals::NeedlessParensOnRangeLiterals));
diff --git a/tests/ui-toml/collapsible_if/clippy.toml b/tests/ui-toml/collapsible_if/clippy.toml
new file mode 100644
index 00000000000..592cea90cff
--- /dev/null
+++ b/tests/ui-toml/collapsible_if/clippy.toml
@@ -0,0 +1 @@
+lint-commented-code = true
diff --git a/tests/ui-toml/collapsible_if/collapsible_if.fixed b/tests/ui-toml/collapsible_if/collapsible_if.fixed
new file mode 100644
index 00000000000..f695f9804d5
--- /dev/null
+++ b/tests/ui-toml/collapsible_if/collapsible_if.fixed
@@ -0,0 +1,34 @@
+#![allow(clippy::eq_op, clippy::nonminimal_bool)]
+
+#[rustfmt::skip]
+#[warn(clippy::collapsible_if)]
+fn main() {
+    let (x, y) = ("hello", "world");
+
+    if x == "hello"
+        // Comment must be kept
+        && y == "world" {
+            println!("Hello world!");
+        }
+    //~^^^^^^ collapsible_if
+
+    // The following tests check for the fix of https://github.com/rust-lang/rust-clippy/issues/798
+    if x == "hello" // Inner comment
+        && y == "world" {
+            println!("Hello world!");
+        }
+    //~^^^^^ collapsible_if
+
+    if x == "hello"
+        /* Inner comment */
+        && y == "world" {
+            println!("Hello world!");
+        }
+    //~^^^^^^ collapsible_if
+
+    if x == "hello" /* Inner comment */
+        && y == "world" {
+            println!("Hello world!");
+        }
+    //~^^^^^ collapsible_if
+}
diff --git a/tests/ui-toml/collapsible_if/collapsible_if.rs b/tests/ui-toml/collapsible_if/collapsible_if.rs
new file mode 100644
index 00000000000..868b4adcde5
--- /dev/null
+++ b/tests/ui-toml/collapsible_if/collapsible_if.rs
@@ -0,0 +1,38 @@
+#![allow(clippy::eq_op, clippy::nonminimal_bool)]
+
+#[rustfmt::skip]
+#[warn(clippy::collapsible_if)]
+fn main() {
+    let (x, y) = ("hello", "world");
+
+    if x == "hello" {
+        // Comment must be kept
+        if y == "world" {
+            println!("Hello world!");
+        }
+    }
+    //~^^^^^^ collapsible_if
+
+    // The following tests check for the fix of https://github.com/rust-lang/rust-clippy/issues/798
+    if x == "hello" { // Inner comment
+        if y == "world" {
+            println!("Hello world!");
+        }
+    }
+    //~^^^^^ collapsible_if
+
+    if x == "hello" {
+        /* Inner comment */
+        if y == "world" {
+            println!("Hello world!");
+        }
+    }
+    //~^^^^^^ collapsible_if
+
+    if x == "hello" { /* Inner comment */
+        if y == "world" {
+            println!("Hello world!");
+        }
+    }
+    //~^^^^^ collapsible_if
+}
diff --git a/tests/ui-toml/collapsible_if/collapsible_if.stderr b/tests/ui-toml/collapsible_if/collapsible_if.stderr
new file mode 100644
index 00000000000..a12c2112f58
--- /dev/null
+++ b/tests/ui-toml/collapsible_if/collapsible_if.stderr
@@ -0,0 +1,80 @@
+error: this `if` statement can be collapsed
+  --> tests/ui-toml/collapsible_if/collapsible_if.rs:8:5
+   |
+LL | /     if x == "hello" {
+LL | |         // Comment must be kept
+LL | |         if y == "world" {
+LL | |             println!("Hello world!");
+LL | |         }
+LL | |     }
+   | |_____^
+   |
+   = note: `-D clippy::collapsible-if` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::collapsible_if)]`
+help: collapse nested if block
+   |
+LL ~     if x == "hello"
+LL |         // Comment must be kept
+LL ~         && y == "world" {
+LL |             println!("Hello world!");
+LL ~         }
+   |
+
+error: this `if` statement can be collapsed
+  --> tests/ui-toml/collapsible_if/collapsible_if.rs:17:5
+   |
+LL | /     if x == "hello" { // Inner comment
+LL | |         if y == "world" {
+LL | |             println!("Hello world!");
+LL | |         }
+LL | |     }
+   | |_____^
+   |
+help: collapse nested if block
+   |
+LL ~     if x == "hello" // Inner comment
+LL ~         && y == "world" {
+LL |             println!("Hello world!");
+LL ~         }
+   |
+
+error: this `if` statement can be collapsed
+  --> tests/ui-toml/collapsible_if/collapsible_if.rs:24:5
+   |
+LL | /     if x == "hello" {
+LL | |         /* Inner comment */
+LL | |         if y == "world" {
+LL | |             println!("Hello world!");
+LL | |         }
+LL | |     }
+   | |_____^
+   |
+help: collapse nested if block
+   |
+LL ~     if x == "hello"
+LL |         /* Inner comment */
+LL ~         && y == "world" {
+LL |             println!("Hello world!");
+LL ~         }
+   |
+
+error: this `if` statement can be collapsed
+  --> tests/ui-toml/collapsible_if/collapsible_if.rs:32:5
+   |
+LL | /     if x == "hello" { /* Inner comment */
+LL | |         if y == "world" {
+LL | |             println!("Hello world!");
+LL | |         }
+LL | |     }
+   | |_____^
+   |
+help: collapse nested if block
+   |
+LL ~     if x == "hello" /* Inner comment */
+LL ~         && y == "world" {
+LL |             println!("Hello world!");
+LL ~         }
+   |
+
+error: aborting due to 4 previous errors
+
diff --git a/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr b/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr
index fee5b01b689..de0eefc422e 100644
--- a/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr
+++ b/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr
@@ -49,6 +49,7 @@ error: error reading Clippy's configuration file: unknown field `foobar`, expect
            future-size-threshold
            ignore-interior-mutability
            large-error-threshold
+           lint-commented-code
            lint-inconsistent-struct-field-initializers
            literal-representation-threshold
            matches-for-let-else
@@ -142,6 +143,7 @@ error: error reading Clippy's configuration file: unknown field `barfoo`, expect
            future-size-threshold
            ignore-interior-mutability
            large-error-threshold
+           lint-commented-code
            lint-inconsistent-struct-field-initializers
            literal-representation-threshold
            matches-for-let-else
@@ -235,6 +237,7 @@ error: error reading Clippy's configuration file: unknown field `allow_mixed_uni
            future-size-threshold
            ignore-interior-mutability
            large-error-threshold
+           lint-commented-code
            lint-inconsistent-struct-field-initializers
            literal-representation-threshold
            matches-for-let-else
diff --git a/tests/ui/collapsible_if.fixed b/tests/ui/collapsible_if.fixed
index 6e994018aef..df281651ab1 100644
--- a/tests/ui/collapsible_if.fixed
+++ b/tests/ui/collapsible_if.fixed
@@ -12,34 +12,40 @@
 fn main() {
     let x = "hello";
     let y = "world";
-    if x == "hello" && y == "world" {
-        println!("Hello world!");
-    }
+    if x == "hello"
+        && y == "world" {
+            println!("Hello world!");
+        }
     //~^^^^^ collapsible_if
 
-    if (x == "hello" || x == "world") && (y == "world" || y == "hello") {
-        println!("Hello world!");
-    }
+    if (x == "hello" || x == "world")
+        && (y == "world" || y == "hello") {
+            println!("Hello world!");
+        }
     //~^^^^^ collapsible_if
 
-    if x == "hello" && x == "world" && (y == "world" || y == "hello") {
-        println!("Hello world!");
-    }
+    if x == "hello" && x == "world"
+        && (y == "world" || y == "hello") {
+            println!("Hello world!");
+        }
     //~^^^^^ collapsible_if
 
-    if (x == "hello" || x == "world") && y == "world" && y == "hello" {
-        println!("Hello world!");
-    }
+    if (x == "hello" || x == "world")
+        && y == "world" && y == "hello" {
+            println!("Hello world!");
+        }
     //~^^^^^ collapsible_if
 
-    if x == "hello" && x == "world" && y == "world" && y == "hello" {
-        println!("Hello world!");
-    }
+    if x == "hello" && x == "world"
+        && y == "world" && y == "hello" {
+            println!("Hello world!");
+        }
     //~^^^^^ collapsible_if
 
-    if 42 == 1337 && 'a' != 'A' {
-        println!("world!")
-    }
+    if 42 == 1337
+        && 'a' != 'A' {
+            println!("world!")
+        }
     //~^^^^^ collapsible_if
 
     // Works because any if with an else statement cannot be collapsed.
@@ -71,37 +77,17 @@ fn main() {
         assert!(true); // assert! is just an `if`
     }
 
-
-    // The following tests check for the fix of https://github.com/rust-lang/rust-clippy/issues/798
-    if x == "hello" {// Not collapsible
-        if y == "world" {
+    if x == "hello"
+        && y == "world" { // Collapsible
             println!("Hello world!");
         }
-    }
-
-    if x == "hello" { // Not collapsible
-        if y == "world" {
-            println!("Hello world!");
-        }
-    }
-
-    if x == "hello" {
-        // Not collapsible
-        if y == "world" {
-            println!("Hello world!");
-        }
-    }
-
-    if x == "hello" && y == "world" { // Collapsible
-        println!("Hello world!");
-    }
     //~^^^^^ collapsible_if
 
     if x == "hello" {
         print!("Hello ");
     } else {
         // Not collapsible
-        if y == "world" {
+        if let Some(42) = Some(42) {
             println!("world!")
         }
     }
@@ -110,21 +96,8 @@ fn main() {
         print!("Hello ");
     } else {
         // Not collapsible
-        if let Some(42) = Some(42) {
-            println!("world!")
-        }
-    }
-
-    if x == "hello" {
-        /* Not collapsible */
         if y == "world" {
-            println!("Hello world!");
-        }
-    }
-
-    if x == "hello" { /* Not collapsible */
-        if y == "world" {
-            println!("Hello world!");
+            println!("world!")
         }
     }
 
@@ -150,11 +123,13 @@ fn main() {
     }
 
     // Fix #5962
-    if matches!(true, true) && matches!(true, true) {}
+    if matches!(true, true)
+        && matches!(true, true) {}
     //~^^^ collapsible_if
 
     // Issue #9375
-    if matches!(true, true) && truth() && matches!(true, true) {}
+    if matches!(true, true) && truth()
+        && matches!(true, true) {}
     //~^^^ collapsible_if
 
     if true {
@@ -163,4 +138,17 @@ fn main() {
             println!("Hello world!");
         }
     }
+
+    if true
+        && true {
+            println!("No comment, linted");
+        }
+    //~^^^^^ collapsible_if
+
+    if true {
+        // Do not collapse because of this comment
+        if true {
+            println!("Hello world!");
+        }
+    }
 }
diff --git a/tests/ui/collapsible_if.rs b/tests/ui/collapsible_if.rs
index 5cf591a658c..ce979568cc8 100644
--- a/tests/ui/collapsible_if.rs
+++ b/tests/ui/collapsible_if.rs
@@ -83,27 +83,6 @@ fn main() {
         assert!(true); // assert! is just an `if`
     }
 
-
-    // The following tests check for the fix of https://github.com/rust-lang/rust-clippy/issues/798
-    if x == "hello" {// Not collapsible
-        if y == "world" {
-            println!("Hello world!");
-        }
-    }
-
-    if x == "hello" { // Not collapsible
-        if y == "world" {
-            println!("Hello world!");
-        }
-    }
-
-    if x == "hello" {
-        // Not collapsible
-        if y == "world" {
-            println!("Hello world!");
-        }
-    }
-
     if x == "hello" {
         if y == "world" { // Collapsible
             println!("Hello world!");
@@ -115,7 +94,7 @@ fn main() {
         print!("Hello ");
     } else {
         // Not collapsible
-        if y == "world" {
+        if let Some(42) = Some(42) {
             println!("world!")
         }
     }
@@ -124,21 +103,8 @@ fn main() {
         print!("Hello ");
     } else {
         // Not collapsible
-        if let Some(42) = Some(42) {
-            println!("world!")
-        }
-    }
-
-    if x == "hello" {
-        /* Not collapsible */
         if y == "world" {
-            println!("Hello world!");
-        }
-    }
-
-    if x == "hello" { /* Not collapsible */
-        if y == "world" {
-            println!("Hello world!");
+            println!("world!")
         }
     }
 
@@ -181,4 +147,18 @@ fn main() {
             println!("Hello world!");
         }
     }
+
+    if true {
+        if true {
+            println!("No comment, linted");
+        }
+    }
+    //~^^^^^ collapsible_if
+
+    if true {
+        // Do not collapse because of this comment
+        if true {
+            println!("Hello world!");
+        }
+    }
 }
diff --git a/tests/ui/collapsible_if.stderr b/tests/ui/collapsible_if.stderr
index 3cc3fe5534f..559db238cb1 100644
--- a/tests/ui/collapsible_if.stderr
+++ b/tests/ui/collapsible_if.stderr
@@ -12,9 +12,10 @@ LL | |     }
    = help: to override `-D warnings` add `#[allow(clippy::collapsible_if)]`
 help: collapse nested if block
    |
-LL ~     if x == "hello" && y == "world" {
-LL +         println!("Hello world!");
-LL +     }
+LL ~     if x == "hello"
+LL ~         && y == "world" {
+LL |             println!("Hello world!");
+LL ~         }
    |
 
 error: this `if` statement can be collapsed
@@ -29,9 +30,10 @@ LL | |     }
    |
 help: collapse nested if block
    |
-LL ~     if (x == "hello" || x == "world") && (y == "world" || y == "hello") {
-LL +         println!("Hello world!");
-LL +     }
+LL ~     if (x == "hello" || x == "world") {
+LL ~         && (y == "world" || y == "hello") {
+LL |             println!("Hello world!");
+LL ~         }
    |
 
 error: this `if` statement can be collapsed
@@ -46,9 +48,10 @@ LL | |     }
    |
 help: collapse nested if block
    |
-LL ~     if x == "hello" && x == "world" && (y == "world" || y == "hello") {
-LL +         println!("Hello world!");
-LL +     }
+LL ~     if x == "hello" && x == "world"
+LL ~         && (y == "world" || y == "hello") {
+LL |             println!("Hello world!");
+LL ~         }
    |
 
 error: this `if` statement can be collapsed
@@ -63,9 +66,10 @@ LL | |     }
    |
 help: collapse nested if block
    |
-LL ~     if (x == "hello" || x == "world") && y == "world" && y == "hello" {
-LL +         println!("Hello world!");
-LL +     }
+LL ~     if (x == "hello" || x == "world") {
+LL ~         && y == "world" && y == "hello" {
+LL |             println!("Hello world!");
+LL ~         }
    |
 
 error: this `if` statement can be collapsed
@@ -80,9 +84,10 @@ LL | |     }
    |
 help: collapse nested if block
    |
-LL ~     if x == "hello" && x == "world" && y == "world" && y == "hello" {
-LL +         println!("Hello world!");
-LL +     }
+LL ~     if x == "hello" && x == "world"
+LL ~         && y == "world" && y == "hello" {
+LL |             println!("Hello world!");
+LL ~         }
    |
 
 error: this `if` statement can be collapsed
@@ -97,13 +102,14 @@ LL | |     }
    |
 help: collapse nested if block
    |
-LL ~     if 42 == 1337 && 'a' != 'A' {
-LL +         println!("world!")
-LL +     }
+LL ~     if 42 == 1337
+LL ~         && 'a' != 'A' {
+LL |             println!("world!")
+LL ~         }
    |
 
 error: this `if` statement can be collapsed
-  --> tests/ui/collapsible_if.rs:107:5
+  --> tests/ui/collapsible_if.rs:86:5
    |
 LL | /     if x == "hello" {
 LL | |         if y == "world" { // Collapsible
@@ -114,26 +120,57 @@ LL | |     }
    |
 help: collapse nested if block
    |
-LL ~     if x == "hello" && y == "world" { // Collapsible
-LL +         println!("Hello world!");
-LL +     }
+LL ~     if x == "hello"
+LL ~         && y == "world" { // Collapsible
+LL |             println!("Hello world!");
+LL ~         }
    |
 
 error: this `if` statement can be collapsed
-  --> tests/ui/collapsible_if.rs:167:5
+  --> tests/ui/collapsible_if.rs:133:5
    |
 LL | /     if matches!(true, true) {
 LL | |         if matches!(true, true) {}
 LL | |     }
-   | |_____^ help: collapse nested if block: `if matches!(true, true) && matches!(true, true) {}`
+   | |_____^
+   |
+help: collapse nested if block
+   |
+LL ~     if matches!(true, true)
+LL ~         && matches!(true, true) {}
+   |
 
 error: this `if` statement can be collapsed
-  --> tests/ui/collapsible_if.rs:173:5
+  --> tests/ui/collapsible_if.rs:139:5
    |
 LL | /     if matches!(true, true) && truth() {
 LL | |         if matches!(true, true) {}
 LL | |     }
-   | |_____^ help: collapse nested if block: `if matches!(true, true) && truth() && matches!(true, true) {}`
+   | |_____^
+   |
+help: collapse nested if block
+   |
+LL ~     if matches!(true, true) && truth()
+LL ~         && matches!(true, true) {}
+   |
+
+error: this `if` statement can be collapsed
+  --> tests/ui/collapsible_if.rs:151:5
+   |
+LL | /     if true {
+LL | |         if true {
+LL | |             println!("No comment, linted");
+LL | |         }
+LL | |     }
+   | |_____^
+   |
+help: collapse nested if block
+   |
+LL ~     if true
+LL ~         && true {
+LL |             println!("No comment, linted");
+LL ~         }
+   |
 
-error: aborting due to 9 previous errors
+error: aborting due to 10 previous errors