rust-lang / rfcs

RFCs for changes to Rust
https://rust-lang.github.io/rfcs/
Apache License 2.0
5.96k stars 1.57k forks source link

compile_warning! #3704

Open trueb2 opened 1 month ago

trueb2 commented 1 month ago

Related to https://github.com/rust-lang/rfcs/issues/2902 and https://internals.rust-lang.org/t/pre-rfc-add-compile-warning-macro/9370, I want a compile_warning! macro that is similar to compile_error! except that it is not a hard error.

Here is a motivating use case. Say I have two barely compatible features, I would expect to be able to emit a warning based on my knowledge as a developer and experience with interface symmetry. However, it is not possible to do this:

#[cfg(all(feature = "feature_a", feature = "feature_b"))]
compile_warning!("Using 'feature_a' and 'feature_b' together is not recommended.");

There are many reasons why it may not be possible to have truly mutually exclusive features in Rust. I hit this a lot when trying to divvy up the limited static memory on microcontrollers.

I think the #[allow] and #[deny] points in the threads very relevant. It would be good feedback to someone building the crate to see the warning once, then be able to silence the warning. For example: In a library crate:

#[cfg(all(feature = "feature_a", feature = "feature_b"))]
compile_warning!(foobar, "Using 'feature_a' and 'feature_b' together is not recommended.");

In the consuming crate:

// We checked we want this ill-advised configuration
#[allow(foobar)]
trueb2 commented 1 month ago

My workaround to generate the warnings at the moment looks like this

// Emit a warning if neither 'feature_a' nor 'feature_b' is enabled
#[cfg(not(any(feature = "feature_a", feature = "feature_b")))]
fn emit_warning() {
    let warning = "Warning: Neither 'feature_a' nor 'feature_b' feature is set";
}

This gives me a warning (which is more important than silence). On the downside, I don't have a way to override that this is acceptable, and the function names conflict with each copy paste.

warning: unused variable: `warning`
  --> src/bin/asdf:27:9
   |
27 |     let warning = "Warning: Neither 'feature_a' nor 'feature_b' feature is set";
   |         ^^^^^^^ help: if this is intentional, prefix it with an underscore: `_warning`
   |
   = note: `#[warn(unused_variables)]` on by default

warning: function `emit_warning` is never used
  --> src/bin/asdf:26:4
   |
26 | fn emit_warning() {
   |    ^^^^^^^^^^^^
   |
   = note: `#[warn(dead_code)]` on by default
LunarLambda commented 1 month ago

Worth noting that by default, cargo does not emit warnings in dependencies, so a compile_warning macro by itself would most likely not be useful for library authors, and I'm not sure if cargo install shows warnings for the binary crate(s) being installed either.

trueb2 commented 1 month ago

Good point. It does emit warnings if the library and binary target are in the same workspace, which I find common for embedded project structures.