- Feature Name: compile_warning - Start Date: 2019-02-05 - RFC PR: - Rust Issue: # Summary [summary]: #summary A compile_warning! macro to be added to libcore to allow custom user warnings at compile time, similar to core::compile_error. `compile_warning!($lint_name:tt, $warning:tt)` The lint name specified is able to be `#[allow]`'d. # Motivation [motivation]: #motivation As Rust creates a bigger emphasis on compile time evaluation with features like procedural macros and `const fn`, the need for custom compile-time warnings becomes ever more prevalent. Right now, this is impossible without weird hacks or compiler plugins. Possibilities for use cases include: * Warning for not officially supported/deprecated OS targets * Warning for deprecated macros * Warning for code still in development * Warning for unstable, but technically working, code # Guide-level explanation [guide-level-explanation]: #guide-level-explanation The `compile_warning!` macro lets you create warnings at compile time, similar to `compile_error!`. Say that you wanted to make code to write elements from a vector to a log, then do something with them. You may write this code: ```rs fn code(things: Vec<Thing>) { for thing in things { write_to_log(&thing); // rest of your code } } ``` However, at your point in development, it's not necessary for it to log, it's just something you want later on. You might not want to comment out the code completely since a developer later on might expect it to write to the log, only to realize you commented out the code. You also might not want to comment out the code because you don't want to forget later on that was a behavior you wanted, only to remember after reading the comment. You could define write_to_log with a TODO comment. ```rs fn write_to_log(_thing: &Thing) { // TODO: Write to log. } ``` However, you and other developers may not realize or forget this function was never implemented. You can solve this problem with `compile_warning!` if you define the code like: ```rs fn write_to_log(_thing: &Thing) { compile_warning!("write_to_log_not_implemented", "TODO: Write to log."); } ``` When you compile this code, you'll get a warning during compile time that reads: "TODO: Write to log.", making it obvious that the function is not implemented yet to the developer. # Reference-level explanation [reference-level-explanation]: #reference-level-explanation To stay consistent and because of its intuitiveness, warnings generated by `compile_warning!` will treat `compile_warning!` warnings like any other when `#[deny(warnings)]` is in effect, and deny. TODO, not sure what other technical stuff to put here. # Drawbacks [drawbacks]: #drawbacks - Using `compile_warning!` a lot for TODO code makes developers more likely to miss rustc warnings. - `compile_warning!` is harder to grep than `unimplemented!`, as the former is meant to be used in a more generic fashion. - TODO # Rationale and alternatives [rationale-and-alternatives]: #rationale-and-alternatives - Don't allow users to specify lint names. This would prevent name clashing and make #[allow] behavior more intuitive, at the cost of not being able to allow/deny specific compiler warnings. - Allow lint names to be specified as identities instead of literals. - Stomp out most likely use cases for custom warnings, such as making `unimplemented!` warn instead of panic. - Do nothing, and continue to let users use compiler plugins and hacks like those brought up in Prior art. # Prior art [prior-art]: #prior-art Some C and C++ compilers have support for `#pragma message` and `#warning`, something that provides a similar functionality. [#pragma message in MSVC](https://docs.microsoft.com/en-us/cpp/preprocessor/message?view=vs-2017) [#warning in GCC](https://gcc.gnu.org/onlinedocs/cpp/Diagnostics.html) While GCC's `#warning` is the closer to what this RFC proposes than `#pragma message`, it is hard to find uses of it as it is not supported in other compilers and thus developers stay wary of it. C# provides compile time warning functionality through [#warning](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/preprocessor-directives/preprocessor-warning). The document linked states its common use case of being inside conditional directives (something constant Rust evaluation will make use of). C# allows ignoring custom warnings by assigning all custom warnings the same code, meaning to disable a custom warning you'd need to disable ALL custom warnings. This is arguably not ideal, as it would be preferred for developers to be more explicit. In the Rust world, compile warnings are done through hacks, such as creating an unused variable and changing the warning message: ``` macro_rules! compile_warning {( $name:ident, $message:expr $(,)* ) => ( mod $name { #[must_use = $message] struct compile_warning; #[allow(dead_code)] fn trigger_warning () { compile_warning; } } )} ``` This creates warnings that don't give the expected initial warning text and displace the actual warning text. ``` warning: unused `main::example::compile_warning` that must be used --> src/main.rs:4:5 | 4 | compile_warning!(example, "Memento buggy"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: #[warn(unused_must_use)] on by default = note: Memento buggy = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) ``` # Unresolved questions [unresolved-questions]: #unresolved-questions <!-- - How to ignore warnings with #[allow]? C# does this by assigning all custom warnings the same code, meaning to disable a custom warning you'd need to disable ALL custom warnings. This is arguably not ideal, as it would be preferred for developers to be more explicit. --> - How to stop name conflicts with lints? If users are allowed to name their lints, then it is possible for them to conflict with both other Rust developers and with future warnings to the language. A solution could be namespacing warnings, similar to how clippy does it. - Should warnings be able to specify rustfix suggestions? How? # Future possibilities [future-possibilities]: #future-possibilities Unknown.