Skip to content

Add --deny-warnings functionality for all commands. #8424

Closed

Description

@nathan-at-least

Tracking issue: #14802

Describe the problem you are trying to solve

I often automate cargo and I typically want any automation to halt when cargo emits warnings. AFAICT the only way to do this is to try to parse the output for the way warnings are typically produced.

(Related issue: there are two categories of warnings which is confusing and needs clarification, which I filed as #8423 .)

Describe the solution you'd like

Add a commandline flag called --deny-warnings and if set, if a warning is encountered, this ensures the process will exit with a non-zero status and that no "non-dry-run" operations proceed. For example, with cargo publish --deny-warnings any of the early local packaging-style lint warnings will cause cargo publish to avoid making any requests to
crates.io.

Notes

I'm not sure about the option name --deny-warnings which I took from the #![deny(warnings)] rust compilation attribute, but I can't think of anything clearer and concise. --treat-warnings-like-errors, --exit-with-error-when-encountering-warnings, --don't-just-warn-me-stop-me!, and --please-save-me-from-myself all are too cumbersome.

Related Tickets

This is related to #3591 because in some way these are opposites (disabling warnings versus escalating them to errors). There might be some common CLI magic that addresses both issues and is clear enough to users.

Even if they use separate cli and/or config specification, if both implemented, they might lead to nonsensical / confusing combinations which a good UX would complain-and-exit about, for example: cargo do-stuff --hide-warnings --deny-warnings or something similar should probably say "I can't tell what you meant to do."

Activity

  1. added
    C-feature-requestCategory: proposal for a feature. Before PR, ping rust-lang/cargo if this is not `Feature accepted`
    on Jun 26, 2020
  2. jrvanwhy commented on Dec 2, 2020

    @jrvanwhy

    Commenting to support this feature request.

    The project I work on has -D warnings in its .cargo/config:

    [target.'cfg(all())']
    rustflags = ["-D", "warnings"]

    This works great for CI, where it prevents us from merging code that has warnings. However, it is painful for local development. I frequently add a few lines, run cargo check, and get errors related to unused variables. I prepend _ to variable names and remove it extremely frequently, which is a waste of time.

    Adding a --deny-warnings flag to cargo would allow us to use --deny-warnings in our CI infrastructure to block on warnings but still allow iterative code development to proceed without the unnecessary toil caused by -D warnings.

  3. CPerezz commented on Feb 7, 2021

    @CPerezz
    Contributor

    You can already do this in your CI. It's just about setting your ENV variable RUSTFLAGS= -D warnings and run cargo.

    Cargo will fetch the ENV variables and pass them to rustc so that the warnings get denied without needing to add any extra stuff.

    This would be an example using actions-rs

    on: [push]
    
    name: CI
    
    jobs:
      build_and_test:
        name: Rust project
        runs-on: ubuntu-latest
        env:
          RUSTFLAGS: -D warnings
        steps:
          - uses: actions/checkout@v2
          - uses: actions-rs/toolchain@v1
            with:
              toolchain: stable
          - uses: actions-rs/cargo@v1
            with:
              command: build
              args: --release --all-features

    If you want to treat warnings as errors, or do any fancy stuff, check the docs about lint levels for rustc: https://doc.rust-lang.org/rustc/lints/levels.html

    I think this issue can be closed considering that --deny-warnings is already something that can be achieved setting up rustflags.

  4. jrvanwhy commented on Feb 7, 2021

    @jrvanwhy

    You can already do this in your CI. It's just about setting your ENV variable RUSTFLAGS= -D warnings and run cargo.

    That does not work for projects that need cargo to pass rust flags configured in .cargo/config. The cargo config documentation says the following about rust flag selection:

    There are three mutually exclusive sources of extra flags. They are checked in order, with the first one being used:

    1. RUSTFLAGS environment variable.
    2. All matching target.<triple>.rustflags and target.<cfg>.rustflags config entries joined together.
    3. build.rustflags config value.

    As an example, libtock-rs uses .cargo/config to configure relocation. Setting RUSTFLAGS while invoking cargo causes cargo to ignore this config and create broken binaries.

    It is possible deny warnings only in CI by including a ci feature to all our crates and adding #![cfg_attr(feature = "ci", deny(warnings)] to the top of all our crates, but that adds maintenance proportional to the number of crates in the project. Another way to do this is to write code to edit .cargo/config during CI (we are doing this in libtock-rs#271), but that is hacky and feels fragile.

  5. CPerezz commented on Feb 7, 2021

    @CPerezz
    Contributor

    I understand your point. With multiple crates things get out of control for maintenance.

    We're working on an RFC that might make this easier to manage. See: rust-lang/rust-clippy#6625

    Although the --deny-warnings would require a bit of design since it can have some edge cases IMO.

  6. wraithan commented on Jul 22, 2021

    @wraithan

    Another reason why RUSTFLAGS="-D warnings" is insufficient as a workaround, even for non-workspace, is that it doesn't account for commands like cargo doc which is how I stumbled upon this feature request, trying to get warnings when building docs in CI to be bubbled up as failures. I can add grep or rg or w/e to process the output and look for ^warning: this way bad links in docs get caught before merged (for example).

  7. stephenmartindale commented on Nov 4, 2021

    @stephenmartindale

    And yet another reason why RUSTFLAGS is a terrible, terrible way to control compiler warnings from rustc is rust-analyzer. If one's build script hacks about with RUSTFLAGS, rust-analyzer has no way of knowing and, because a full recompile gets triggered every single time RUSTFLAGS changes (even for seemingly cosmetic things like warning promotion & suppression), the result can be a complete nightmare as rust-analyzer and the build scripts fight over target.

    Hmm. Now that I write that, I realise that promoting warnings to build-failing errors actually is not a cosmetic thing and, perhaps, it actually should force a full recompile, following the same arguments behind cargo package's full recompile, because warnings-as-errors is typically something that gets employed in CI and for actual release builds.

  8. Anders429 commented on Mar 17, 2022

    @Anders429

    For the cargo doc use case specifically, it seems that using RUSTDOCFLAGS instead of RUSTFLAGS gets the job done. For example, running RUSTDOCFLAGS='-D warnings' cargo doc promotes all warnings to failures.

  9. veber-alex commented on Aug 8, 2023

    @veber-alex

    Is there anything new regarding this issue?

    I want to run cargo check with deny warnings as a precommit hook but the only way is to set RUSTFLAGS which causes a recompile of the crate and all the dependencies.

  10. epage commented on Aug 8, 2023

    @epage
    Contributor

    Is there anything new regarding this issue?

    If its not in this issue, likely not. The closest related work is #12115 which removes some reliance on RUSTFLAGS for dealing with warnings but not in this case.

    I want to run cargo check with deny warnings as a precommit hook but the only way is to set RUSTFLAGS which causes a recompile of the crate and all the dependencies.

    The hard thing here is that technically your dependencies are reporting warnings and deny-warnings could affect them, so we'd need to recompile to verify that. However, with caplints, most warnings from dependencies are dropped and with our caching of warnings between runs, rebuilds aren't needed.

    The challenge with RUSTFLAGS is that its opaque to us (and should remain so) and that it applies to all packages when you only care about workspace members. #8716 at least partially improves the RUSTFLAGS situation because we would generate separate files for each RUSTFLAGS, rather than overwriting, so a full rebuild would happen once and then we'd rebuild on top of that.

  11. veber-alex commented on Aug 8, 2023

    @veber-alex

    I don't think using RUSTFLAGS here is the correct solution, clippy has the option to control the lints directly using cargo clippy -- -Dwarnings.
    You can also do this with cargo rustc --lib -- -Dwarnings but that runs only for one target.
    I think cargo check and build need something like this.

  12. epage commented on Sep 26, 2023

    @epage
    Contributor

    Been thinking about this more in the context of "how do we rely on RUSTFLAGS less?"

    In a case like this, a cargo check -- -Dwarnings can cause things to rebuild because you are passing in a RUSTFLAGS and cargo has no idea what it will do.

    What if we added a flag --warnings <deny|allow> that was completely processed within cargo, relying on the cached output from rustc that cargo replays when a crate doesn't need rebuilding (#6933)

  13. noraa-july-stoke commented on Sep 26, 2023

    @noraa-july-stoke

    What if we added a flag --warnings <deny|allow> that was completely processed within cargo, relying on the cached output from rustc that cargo replays when a crate doesn't need rebuilding (#6933)

    That would be really useful for some of my use cases so I can just focus on looking at critical errors when I need to.

  14. 29 remaining items

  15. added a commit that references this issue on Dec 3, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

A-diagnosticsArea: Error and warning messages generated by Cargo itself.A-lintsArea: rustc lint configurationC-feature-requestCategory: proposal for a feature. Before PR, ping rust-lang/cargo if this is not `Feature accepted`

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions