Skip to content

use statements anywhere but top of module #259

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
llogiq opened this issue Aug 30, 2015 · 20 comments · May be fixed by #14985
Open

use statements anywhere but top of module #259

llogiq opened this issue Aug 30, 2015 · 20 comments · May be fixed by #14985
Assignees
Labels
A-lint Area: New lints good first issue These issues are a good way to get started with Clippy T-AST Type: Requires working with the AST

Comments

@llogiq
Copy link
Contributor

llogiq commented Aug 30, 2015

In an earlier version of sokoban-rs, the author included a use statement in the middle of a loop.

Let's catch such stuff and propose putting it at the top of the file.

@Manishearth
Copy link
Member

Meh, this is actually a pattern I've seen used often and it's okay IMO (esp. for test imports).

Allow fine though

@Manishearth Manishearth added good first issue These issues are a good way to get started with Clippy T-AST Type: Requires working with the AST A-lint Area: New lints labels Aug 31, 2015
@birkenfeld
Copy link
Contributor

I feel that at least function-local should be allowed if at the top of the function.

@llogiq
Copy link
Contributor Author

llogiq commented Aug 31, 2015

(esp. for test imports).

We probably should ignore use statements within #cfg(test) (or perhaps any #cfg).

I'm fine with Allow.

And again, we can have multiple lints ranging from pedantic to lenient.

@birkenfeld
Copy link
Contributor

Turns out use isn't even allowed in blocks if not at the start...

@llogiq
Copy link
Contributor Author

llogiq commented Sep 1, 2015

Yeah, but there can be a lot of blocks within a function...

@sanmai-NL
Copy link
Contributor

sanmai-NL commented Nov 14, 2016

@llogiq: what is the undesirable effect of a use inside e.g. a loop block?

Is it possible to elaborate a bit why this is bad? Doing it could enhance self-containedness of functions. Not to say I don't empathize with your apprehension ...

@BenjaminBrienen
Copy link

We'll focus on "module-level use statements should not come after other items"

@utkrsharmaa
Copy link

Hey, I wanted to work on this as a first issue, if this is still wanted and no one else is working on it; I'd be glad to. Please let me know the current status of this issue.

@samueltardieu
Copy link
Contributor

Sure, feel free to claim the issue (see the CONTRIBUTING.md file) if you want to work on it!

@utkrsharmaa
Copy link

@rustbot claim

@utkrsharmaa
Copy link

running TESTNAME=items_before_use cargo uibless or TESTNAME=items_before_use cargo bless generating stderr file as visible in the full stderr section of the output. But when i run TESTNAME=items_before_use cargo test it fails.

As i can notice the test run emits diagnostic labels like Error[clippy::items_before_use], and "unmatched diagnostics" which might be causing the test to fail. But I'm not sure since this is my first time writing a lint for clippy.

I apologize if this was a dumb question but it has really been bugging me. Any guidance will be much appreciated.

Output:

error: there were 1 unmatched diagnostics
 --> tests/ui/items_before_use.rs:6:1
  |
6 | use std::fmt; // Should trigger lint
  | ^^^^^^^^^^^^^ Error[clippy::items_before_use]: module level use statements should precede all items
  |

error: there were 1 unmatched diagnostics
 --> tests/ui/items_before_use.rs:7:1
  |
7 | use std::io; // Should also trigger lint
  | ^^^^^^^^^^^^ Error[clippy::items_before_use]: module level use statements should precede all items
  |

error: there were 1 unmatched diagnostics
  --> tests/ui/items_before_use.rs:12:5
   |
12 |     use std::fs; // Should trigger lint
   |     ^^^^^^^^^^^^ Error[clippy::items_before_use]: module level use statements should precede all ite
ms
   |

error: expected error patterns, but found none

full stderr:
error: module level use statements should precede all items
  --> tests/ui/items_before_use.rs:6:1
   |
LL | use std::fmt; // Should trigger lint
   | ^^^^^^^^^^^^^
   |
   = note: consider moving this statement to the top of the module.
   = note: `-D clippy::items-before-use` implied by `-D warnings`
   = help: to override `-D warnings` add `#[allow(clippy::items_before_use)]`

error: module level use statements should precede all items
  --> tests/ui/items_before_use.rs:7:1
   |
LL | use std::io; // Should also trigger lint
   | ^^^^^^^^^^^^
   |
   = note: consider moving this statement to the top of the module.

error: module level use statements should precede all items
  --> tests/ui/items_before_use.rs:12:5
   |
LL |     use std::fs; // Should trigger lint
   |     ^^^^^^^^^^^^
   |
   = note: consider moving this statement to the top of the module.

error: aborting due to 3 previous errors


full stdout:


FAILURES:
    tests/ui/items_before_use.rs

test result: FAIL. 1 failed; 1086 filtered out


thread 'main' panicked at tests/compile-test.rs:222:6:
called `Result::unwrap()` on an `Err` value: tests failed

Location:
    /home/kin/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/ui_test-0.29.2/src/lib.rs:369:13
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
error: test failed, to rerun pass `--test compile-test`
[kin@arch rust-clippy]$ 

@sanmai-NL
Copy link
Contributor

I think this is a solution without a problem.

@llogiq: what is the undesirable effect of a use inside e.g. a loop block?

Is it possible to elaborate a bit why this is bad? Doing it could enhance self-containedness of functions. Not to say I don't empathize with your apprehension ...

@BenjaminBrienen
Copy link

If imports come after their usage, that would be unintuitive. I believe that is only possible with module-level imports.

@y21
Copy link
Member

y21 commented May 27, 2025

Could the arbitrary_source_item_ordering lint help with this? The lint can enforce that all use items appear before functions, const, statics, ...

@BenjaminBrienen
Copy link

imports are items, so that would make sense!

@utkrsharmaa
Copy link

Any guidance will be much appreciated.

If this issue/lint is no longer required or seems a redundant add, I'm happy to drop this issue.

But if not, any help as to why my test was doing that would be appreciated. Any maintainer reading this issue can pass the final verdict, Thanks again.

@y21
Copy link
Member

y21 commented May 27, 2025

As for your error, try adding proper error markers to the lines where you expect your lint to emit. So for example on line 6 (based on your stderr output), write use std::fmt; //~ items_before_use (instead of a normal comment saying "should trigger lint").

That said, IMHO it does sound like the lint arbitrary_source_item_ordering already pretty much covers the use case "module-level use statements should not come after other items". With that lint you can specify an item order that clippy should enforce, so it's a more general version of this.
I think it's also pretty standard for mod and extern crate items to appear before use items, I'm not sure if this lint would make an exception and allow those?

@utkrsharmaa
Copy link

Thanks for the help @y21, The tests all passed and I've declared two lints, one pedantic that is opt-in and stricter which will ask for use statements to be at the absolute top while the other is a style which will ignore mod and extern crates as you mentioned.

We probably should ignore use statements within #cfg(test) (or perhaps any #cfg).
And again, we can have multiple lints ranging from pedantic to lenient.

I still struggled to figure out a solution for the cfg blocks as the author of this issue asked. I've tried multiple methods under cx.tcx. Multiple ways (get_attrs, matches, hir_attrs). But my test for the cfg block still failed

mod test2 {
    fn name() {}
    // use inside cfg block, should be ignored
    #[cfg(feature = "foo")]
    fn baz() {}
    use std::collections::HashMap;
}

error: there were 1 unmatched diagnostics
  --> tests/ui/items_before_use.rs:14:5
   |
14 |     use std::collections::HashMap;
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Error[clippy::items_before_use]: module level use statements shou
ld precede all items
   |

All other tests passed and behaved as expected.
Is anyone aware of methods to accurately check for attributes of items under a cfg block? Thanks.

@BenjaminBrienen
Copy link

BenjaminBrienen commented May 28, 2025

Module-level use statements are items.
Screenshot_20250528-101300_Iceraven_1.png

@utkrsharmaa
Copy link

utkrsharmaa commented May 28, 2025

Module-level use statements are items.

I'm aware.. The lint should be "module level use statements should precede all other items". The error says "all items" because it's still WIP, My apologies for that.

I used ItemKind enum to do the basic work

            match item.kind {
                ItemKind::Use(..) => {
                    if saw_non_use {
                        span_lint_and_note(
                            cx,
                            ITEMS_BEFORE_USE,
                            item.span,
                            "module level use statements should precede all other items",
                            None,
                            "consider moving this statement to the top of the module.",
                        );
                    }
                },
                _ => saw_non_use = true,
            }

utkrsharmaa added a commit to utkrsharmaa/rust-clippy that referenced this issue Jun 5, 2025
utkrsharmaa added a commit to utkrsharmaa/rust-clippy that referenced this issue Jun 5, 2025
@utkrsharmaa utkrsharmaa linked a pull request Jun 5, 2025 that will close this issue
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-lint Area: New lints good first issue These issues are a good way to get started with Clippy T-AST Type: Requires working with the AST
Projects
None yet
Development

Successfully merging a pull request may close this issue.

9 participants