Hello, awesome tool and using it has been helping me learn Rust!
I've been trying to automate executing clippy from some scripts I run across a number of crates I'm maintaining at the moment, and it's tricky to check if there was any warnings from clippy from a Bash script.
I'd love if there was a flag I could set to trigger non-zero exit statuses for any warnings so I can use clippy meaningfully from my scripts. Apologies if something like this already exists and I've just missed it, running clippy --help doesn't appear to show anything relevant though.
The return code is handled by rustc itself. However in a script, it would be much easier to use JSON output:
% rustc a.rs
warning: unused variable: `a`, #[warn(unused_variables)] on by default
--> a.rs:2:9
|
2 | let a = 42;
| ^
% rustc --error-format json a.rs
{"message":"unused variable: `a`, #[warn(unused_variables)] on by default","code":null,"level":"warning","spans":[{"file_name":"a.rs","byte_start":20,"byte_end":21,"line_start":2,"line_end":2,"column_start":9,"column_end":10,"is_primary":true,"text":[{"text":" let a = 42;","highlight_start":9,"highlight_end":10}],"label":null,"suggested_replacement":null,"expansion":null}],"children":[],"rendered":null}
(you get one line per error/warning, which is a json object describing the error)
@mcarton: that does not clearly separate between messages generated by Clippy and other messages. For instance, the compiler aborting due to previous Clippy-induced errors is considered an error in itself.
Moreover, Cargo writes these machine readable JSON messages on standard error instead of standard output, resulting in unparseable about (a mixture of exclusively human and machine readable output).
You can pass -Dwarnings to ensure that warnings are treated as errors. This way you'll also get the non-zero exit code.
@oli-obk: Does that work if you set the lint level to warn for _every_ lint (group), via attributes?
@sanmai-NL yes
@oli-obk:
It doesn鈥檛 work for me. something is a crate with one bin target, member of a virtual workspace.
something/src/main.rs:
#![feature(stmt_expr_attributes)]
#![warn(bad_style)]
#![warn(future_incompatible)]
#![warn(unused)]
#![warn(warnings)]
#![allow(missing_docs)]
#![cfg_attr(feature = "cargo-clippy", warn(clippy))]
#![cfg_attr(feature = "cargo-clippy", warn(clippy_pedantic))]
#![cfg_attr(feature = "cargo-clippy", allow(missing_docs_in_private_items))]
// ...
cargo +nightly clippy --frozen --all-features --package something -- -Dwarnings
Compiling something v0.1.0 (file:///tmp/something)
warning: used unwrap() on a Result value. If you don't want to handle the Err case gracefully, consider using expect() to provide a better panic message
--> something/src/main.rs:19:41
|
19 | let service = const_service(create_new_service(data).unwrap());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: lint level defined here
--> something/src/main.rs:8:44
|
8 | #![cfg_attr(feature = "cargo-clippy", warn(clippy_pedantic))]
| ^^^^^^^^^^^^^^^
= note: #[warn(result_unwrap_used)] implied by #[warn(clippy_pedantic)]
= help: for further information visit https://rust-lang-nursery.github.io/rust-clippy/v0.0.186/index.html#result_unwrap_used
Finished dev [unoptimized + debuginfo] target(s) in 48.81 secs
echo $?
It works fine on my machine :/
oliver@iai-matthes1:~/Projects/rust/cargo_metadata$ cargo +nightly clippy --frozen --all-features --package cargo_metadata -- -Dwarnings
lib: cargo_metadata
Compiling cargo_metadata v0.5.0 (file:///home/oliver/Projects/rust/cargo_metadata)
error: this expression borrows a reference that is immediately dereferenced by the compiler
--> src/lib.rs:199:46
|
199 | let version = semver::Version::parse(&version).map_err(de::Error::custom)?;
| ^^^^^^^^ help: change this to: `version`
|
= note: `-D needless-borrow` implied by `-D warnings`
= help: for further information visit https://rust-lang-nursery.github.io/rust-clippy/v0.0.186/index.html#needless_borrow
error: redundant field names in struct initialization
--> src/lib.rs:204:13
|
204 | version: version,
| ^^^^^^^^^^^^^^^^ help: replace it with: `version`
|
= note: `-D redundant-field-names` implied by `-D warnings`
= help: for further information visit https://rust-lang-nursery.github.io/rust-clippy/v0.0.186/index.html#redundant_field_names
error: aborting due to 2 previous errors
error: Could not compile `cargo_metadata`.
To learn more, run the command again with --verbose.
oliver@iai-matthes1:~/Projects/rust/cargo_metadata$ echo $?
101
It was in a lib project without workspaces though.
@oli-obk: what can we do here? Can you or someone else who wishes to confirm take some more time to test with a virtual workspace? If this snag is resolved then this GitHub issue could, as far as I am concerned, be closed. So it seems worthwhile to test and even add a test case if there turns out to be a bug.
@sanmai-NL If you give me a repro example (upload your example to github?) I can investigate further
@oli-obk I had the same problem as @sanmai-NL , the output said
error: aborting due to 12 previous errors, which followed by Finished dev [unoptimized + debuginfo] target(s) in 1m 18s, and the returned status is 0 (checked on my machine). here is the ci job link https://travis-ci.org/niedhui/rust-prometheus/jobs/394541190#L1948
I ran into this as well.
I can reproduce with the following Dockerfile:
FROM rust:1.26
RUN USER='root' cargo init --vcs=none --name=foo \
&& echo 'fn unused() {}' >> src/main.rs \
&& rustup --version \
&& rustup toolchain install nightly \
&& cargo +nightly install clippy \
&& cargo --version && cargo +nightly clippy --version \
&& cargo +nightly clippy -- -D warnings
Which when built with sudo docker build . erroneously succeeds:
...
Installing /usr/local/cargo/bin/cargo-clippy
Installing /usr/local/cargo/bin/clippy-driver
cargo 1.26.0 (0e7c5a931 2018-04-06)
0.0.209
Checking foo v0.1.0 (file:///)
error: function is never used: `unused`
--> src/main.rs:4:1
|
4 | fn unused() {}
| ^^^^^^^^^^^
|
= note: `-D dead-code` implied by `-D warnings`
error: aborting due to previous error
Finished dev [unoptimized + debuginfo] target(s) in 0.21s
Removing intermediate container 2255f616fd2c
---> a0b758bbad36
Successfully built a0b758bbad36
Fixed in https://github.com/rust-lang-nursery/rust-clippy/pull/2863
Now we just need a regression test. Probably just adding something to travis is enough.
I don't think forbidding warnings is enough. For example, when I have two packages in workspace, -D warnings causes clippy to stop after some warnings are encountered in first package, thus not checking the second one at all.
Moreover this is awkward to use in CI in non-blocking mode. I'd like to know number of hard errors and number of warnings. Hard errors should block CI, but not the warnings.
I'm on macOS 10.15.6 x86 and clippy will not exit with non-zero status.
$ cargo clippy -- -D warnings ; echo $?
...
warning: 3 warnings emitted
Finished dev [unoptimized + debuginfo] target(s) in 0.02s
0
$ cargo version
cargo 1.47.0-beta (f3c7e066a 2020-08-28)
$ rustup toolchain list
beta-x86_64-apple-darwin (default)
$ rustc --version
rustc 1.47.0-beta.3 (aa30bf344 2020-09-10)
I'm trying to make my local dev tools work the same as the project's continuous integration scripts on GitHub.
I tried configuring CLion 2020.2.4 with a single run configuration that runs both cargo clippy and cargo test. I made a cargo test run configuration. Then I made a cargo clippy run configuration and added it to the "Before launch" section of the cargo test config. Executing the cargo test config does execute the cargo clippy, but doesn't stop on clippy errors because the exit value is always zero.
I would really appreciate advice on setting this up.
Strangely, the problem just went away:
$ cargo clippy -- -D warnings ; echo $?
...
error: aborting due to 2 previous errors
error: could not compile `fixed-buffer`.
To learn more, run the command again with --verbose.
101
$
And the cargo test CLion run config is now properly failing when cargo clippy fails.
Perhaps clippy is caching some results on disk and returning 0 in some strange edge case?
Maybe we can try RUSTFLAGS="-D warnings" cargo build ....
Most helpful comment
@oli-obk:
It doesn鈥檛 work for me.
somethingis a crate with onebintarget, member of a virtual workspace.something/src/main.rs: