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

Enable Clippy nesting limit #10896

Closed
wants to merge 1 commit into from
Closed

Conversation

Nilirad
Copy link
Contributor

@Nilirad Nilirad commented Dec 6, 2023

Objective

Some areas of the codebase are excessively nested. I think we should at least put a limit to it to prevent exacerbating the already critical situation.

Solution

Update clippy.toml to set the excessive-nesting-threshold option to 9, which is the highest level of nesting so far.

Tested by doing cargo +stable clippy --all-features --all-targets

@Nilirad Nilirad added A-Build-System Related to build systems or continuous integration C-Code-Quality A section of code that is hard to understand or change X-Controversial There is active debate or serious implications around merging this PR labels Dec 6, 2023
Copy link
Member

@alice-i-cecile alice-i-cecile left a comment

Choose a reason for hiding this comment

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

This seems sensible as a style guidance (ideally we can bring it down a bit further later). Config is correct.

Note: Even though this lint is warn-by-default, it will only trigger if a maximum nesting level is defined in the clippy.toml file.

From the Clippy docs.

@Nilirad
Copy link
Contributor Author

Nilirad commented Dec 7, 2023

Yes, the idea is to progressively bring it down to an acceptable level. It's common practice in C to not exceed 3 levels, most notably in the Linux kernel.
In the case of Bevy, that goal is much more difficult to attain, since Rust code tends to nest more than C, with mod and impl blocks, and with closures (that can be factored out into functions anyway). Using let-else statements tends to flatten the code by a considerable amount by keeping the happy path of the function to the first level, and bail out on error. I think we can achieve a nesting limit of 5 (even 4 as a stretch goal) in a relatively short amount of time without recurring to excessively controversial techniques.

In my personal Bevy project I've been able to reach level 3, even with UI code. Also, I've started doing some experiments refactoring the most nested functions in the Bevy codebase to see how low we can push the limit.

@rlidwka
Copy link
Contributor

rlidwka commented Dec 7, 2023

This should be handled by humans during code review on case-by-case basis.

Refactoring existing code to reduce nesting level is a good idea. But enforcing it on CI is very much not: if someone needs to fix a simple bug by adding a condition into already-at-nesting-limit function, would she have to refactor the entire function just to make CI error go away?

@Nilirad
Copy link
Contributor Author

Nilirad commented Dec 7, 2023

I think we should still move forward. The fact that we've reached level 9 proves that we shouldn't rely on manual code review.

Yes, this may make a bugfix PR more complex, but the benefits greatly outweigh the drawbacks. If a bug can be lazily fixed by adding just one more indentation level, we worsen an already critical situation, accumulating technical debt over time, making further changes progressively more and more difficult, paradoxically.

As I mentioned before, Linus Torvalds highly encourages a strict 3 nesting levels policy on the Linux kernel codebase, but that doesn't prevent it from having arguably the most active open source community in the world. If a project with 30M lines of code thrives with 3 levels of indentation, I doubt we'll encounter problems by enforcing 9.

@rlidwka
Copy link
Contributor

rlidwka commented Dec 7, 2023

As I mentioned before, Linus Torvalds highly encourages a strict 3 nesting levels policy on the Linux kernel codebase

That's great! I believe we should also highly encourage 3 nesting levels policy.

I suggest to add a mention in the contributing guide that "don't use more than 3 nesting levels pretty please", and close this issue, because I'm sure we're going to have as much luck enforcing this as linux kernel does.


PS:
here's 6:
https://github.com/torvalds/linux/blob/bee0e7762ad2c6025b9f5245c040fcc36ef2bde8/fs/posix_acl.c#L409-L417
here's 7:
https://github.com/torvalds/linux/blob/bee0e7762ad2c6025b9f5245c040fcc36ef2bde8/lib/raid6/test/test.c#L135-L137
here's 7 again (or 8, depending on how you count):
https://github.com/torvalds/linux/blob/bee0e7762ad2c6025b9f5245c040fcc36ef2bde8/drivers/net/ethernet/dec/tulip/interrupt.c#L180-L187

@tim-blackbird
Copy link
Contributor

The Linux project failing to enforce their style guide in CI doesn't seem like a reason for us to make the same mistake.

@alice-i-cecile alice-i-cecile added the S-Ready-For-Final-Review This PR has been approved by the community. It's ready for a maintainer to consider merging it label Dec 7, 2023
github-merge-queue bot pushed a commit that referenced this pull request Dec 9, 2023
# Objective

- Improve readability.
- Somewhat relates to #10896.

## Solution

- Use early returns to minimize nesting.
- Change `emitter_translation` to use `if let` instead of `map`.
github-merge-queue bot pushed a commit that referenced this pull request Dec 10, 2023
# Objective

`update_accessibility_nodes` is one of the most nested functions in the
entire Bevy repository, with a maximum of 9 levels of indentations. This
PR refactors it down to 3 levels of indentations, while improving
readability on other fronts. The result is a function that is actually
understandable at a first glance.

- This is a proof of concept to demonstrate that it is possible to
gradually lower the nesting limit proposed by #10896.

PS: I read AccessKit's documentation, but I don't have experience with
it. Therefore, naming of variables and subroutines may be a bit off.

PS2: I don't know if the test suite covers the functionality of this
system, but since I've spent quite some time on it and the changes were
simple, I'm pretty confident the refactor is functionally equivalent to
the original.

## Solution

I documented each change with a commit, but as a summary I did the
following to reduce nesting:

- I moved from `if-let` blocks to `let-else` statements where
appropriate to reduce rightward shift
- I extracted the closure body to a new function `update_adapter`
- I factored out parts of `update_adapter` into new functions
`queue_node_for_update` and `add_children_nodes`

**Note for reviewers:** GitHub's diff viewer is not the greatest in
showing horizontal code shifts, therefore you may want to use a
different tool like VSCode to review some commits, especially the second
one (anyway, that commit is very straightforward, despite changing many
lines).
github-merge-queue bot pushed a commit that referenced this pull request Dec 12, 2023
# Objective

- Reduce nesting in `process_handle_drop_internal()`.
- Related to #10896.

## Solution

- Use early returns when possible.
- Reduced from 9 levels of indents to 4.
@doonv
Copy link
Contributor

doonv commented Jan 1, 2024

Heres an example of nesting for up to 10 levels (4 spaces):

// 0
fn example() {
    // 1
    { // 2
        { // 3
            { // 4
                { // 5
                    { // 6
                        { // 7
                            { // 8
                                { // 9
                                    // 10
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}

In my opinion you shouldn't ever go beyond 7 idents.

@alice-i-cecile alice-i-cecile added S-Needs-SME Decision or review from an SME is required and removed S-Ready-For-Final-Review This PR has been approved by the community. It's ready for a maintainer to consider merging it labels Sep 22, 2024
@alice-i-cecile
Copy link
Member

Closing; I don't think there's appetite for this currently.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-Build-System Related to build systems or continuous integration C-Code-Quality A section of code that is hard to understand or change S-Needs-SME Decision or review from an SME is required X-Controversial There is active debate or serious implications around merging this PR
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants