Skip to content

Fix collapsible_else_if FP on conditionally compiled stmt #14906

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

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

profetia
Copy link
Contributor

@profetia profetia commented May 28, 2025

Closes #14799

changelog: [collapsible_else_if] fix FP on conditionally compiled stmt

@rustbot
Copy link
Collaborator

rustbot commented May 28, 2025

r? @llogiq

rustbot has assigned @llogiq.
They will have a look at your PR within the next two weeks and either review your PR or reassign to another reviewer.

Use r? to explicitly pick a reviewer

@rustbot rustbot added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties label May 28, 2025
@samueltardieu
Copy link
Contributor

r? samueltardieu

@rustbot rustbot assigned samueltardieu and unassigned llogiq May 28, 2025
Copy link
Contributor

@samueltardieu samueltardieu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After more thinking about it, I think we can do much better, fix more problems, and create a useful utility function that can be used by other lints in similar situations.

I noticed that we parse the beginning of the block two times: once to look for comments, and once to look for auto-removed code. This is not efficient, and we could have a function in clippy_utils that checks for both at the same time, or even one that allows comments but detects significant content:

/// Checks whether a given span has any significant token. A significant token is a non-whitespace
/// token, including comments unless `skip_comments` is set.
/// This is useful to determine if there are any actual code tokens in the span that are omitted in
/// the late pass, such as platform-specific code.
pub fn span_contains_non_whitespace(cx: &impl source::HasSession, span: Span, skip_comments: bool) -> bool {
    matches!(span.get_source_text(cx), Some(snippet) if tokenize_with_text(&snippet).any(|(token, _, _)|
        match token {
            TokenKind::Whitespace => false,
            TokenKind::BlockComment { .. } | TokenKind::LineComment { .. } => !skip_comments,
            _ => true,
        }
    ))
}

(that would supersede span_contains_no_comment() which can be removed)

This will be particularly useful in collapsible_if.rs as:

  • collapsible_if_if suffers the same problem about conditionally compiled statements
  • collapsible_if_if has an option lint_commented_code which triggers the lint even in the presence of commented code
  • collapsible_else_if would benefit from using the same option

If you create this method on CollapsibleIf:

    // Check that nothing significant can be found but whitespaces between the initial `{` of `block`
    // and the beginning of `stop_at`.
    fn block_starts_with_significant_tokens(
        &self,
        cx: &LateContext<'_>,
        block: &Block<'_>,
        stop_at: &Expr<'_>,
    ) -> bool {
        let span = block.span.split_at(1).1.until(stop_at.span);
        span_contains_non_whitespace(cx, span, self.lint_commented_code)
    }

then you can add a &self parameter to check_collapsible_else_if(), and call && !self.block_starts_with_significant_tokens(cx, else_block, else_). check_collapsible_if_if() can get a similar && !self.block_starts_with_significant_tokens(cx, then, inner). This way, the block_starts_with_comment function can be removed as it is no longer useful.

Also, you would need to:

  • register lint_commented_code as being an option of collapsible_else_if as well
  • create test code for collapsible_else_if in ui-toml with this option enabled – you might be able to share code with collapsible_if_if, which already tests for this
  • add test code for collapsible_if_if to ensure that #[cfg(…)] blocks prevent the lint from triggering as expected

All this started from your initial PR, which made me think more about it.

What do you think?

@rustbot rustbot added S-waiting-on-author Status: This is awaiting some action from the author. (Use `@rustbot ready` to update this status) and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties labels May 29, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-waiting-on-author Status: This is awaiting some action from the author. (Use `@rustbot ready` to update this status)
Projects
None yet
Development

Successfully merging this pull request may close these issues.

collapsible_else_if disregard platform code in else branch
4 participants