How to allow and expect a compiler warning in Rust? - rust

Sometimes during development I would like to allow warnings. For example, for dead_code. Yet, in CI and pre_commit git hooks, I have RUSTFLAGS="--deny warnings".
So I'm thinking that what I would like is an attribute such as
#[expect(dead_code)]
fn foo() {
todo!();
}
It would work similar to TypesScript's #ts-expect-error and yet be more specific, expecting a specific list of warnings.
Not sure whether it would make sense for expecting errors, as well.

This is supported experimentally. The RFC is called Lint Reasons. The form is exactly what you would expect: #[expect(lint)].
#![feature(lint_reasons)]
#[expect(dead_code)]
fn foo() {
todo!();
}
Playground.
If the expectation is not fulfilled, a warning is raised. You can #[deny(unfulfilled_lint_expectations)] to make it into an error.
If you only want to allow the warning (but not warn when it is not raised), use #[allow(lint)]:
#[allow(dead_code)]
fn foo() {
todo!();
}
Playground.

Related

Is a direct function call and a self::function call always the same in rust?

Recently, I started to learn rust. I'm currently at section 7.4 (bringing paths into scope). Tried hard, but I can't understand the purpose of self::some_sort_of_identifier in rust. Would you please explain what is the difference between use self::module_name::function_name and use module_name::function_name? I tried both and they both worked as expected in the example below:
mod my_mod {
pub fn func() {
print!("I'm here!");
}
}
use my_mod::func;
fn main() {
func();
}
Running this program, as expected, I can see this statement printed into the terminal:
I'm here
And this program here gives me exactly the same results and the rust compiler doesn't complain about anything:
mod my_mod {
pub fn func() {
print!("I'm here!");
}
}
use self::my_mod::func;
fn main() {
func();
}
So, is self:: useless in rust? Why should I even use self::my_mod::my_function(); when I can directly call it like so: my_mod::my_function();.
Are there any cases in which they might defer?
For your use-case, it's mainly a relict from the 2015 rust edition.
In this edition the following code would not compile:
use my_mod::func;
mod my_mod {
use my_mod2::func2;
pub fn func() {
func2();
}
mod my_mod2 {
pub fn func2() {
print!("I'm here!");
}
}
}
fn main() {
func();
}
The compiler complains:
error[E0432]: unresolved import my_mod2
--> src\main.rs:4:9
|
| use my_mod2::func2;
| ^^^^^^^ help: a similar path exists: self::my_mod2
Why did it change? You can see the note about the path and module system changes here.
Rust 2018 simplifies and unifies path handling compared to Rust 2015. In Rust
2015, paths work differently in use declarations than they do
elsewhere. In particular, paths in use declarations would always start
from the crate root, while paths in other code implicitly started from
the current scope. Those differences didn't have any effect in the
top-level module, which meant that everything would seem
straightforward until working on a project large enough to have
submodules.
In Rust 2018, paths in use declarations and in other code work the
same way, both in the top-level module and in any submodule. You can
use a relative path from the current scope, a path starting from an
external crate name, or a path starting with crate, super, or self.
The blog post Anchored and Uniform Paths from the language team also underlines this
The uniformity is a really big advantage, and the specific feature we’re changing -
no longer having to use self:: - is something I know is a big
stumbling block for new users and a big annoyance for advanced users
(I’m always having to edit and recompile because I tried to import
from a submodule without using self).
The keyword itself however is still useful in use statments to refer to the current module in the path itself. Like
use std::io::{self, Read};
being the same as
use std::io;
use std::io::Read;

Does String Literal Slice Usage with String references is Valid?

I have the following code block and it works as intended with no problem:
fn literal_taker(literals_slice: &[&str]){
println!("{:?}",literals_slice);
}
fn string_taker(string_value: String){
literal_taker(&[&string_value]);
}
fn main() {
let string_value = String::from("Hello");
string_taker(string_value);
}
Here, I pass the reference of String as a slice and it is compiling with no error and no clippy issue.
But the problem is, It is shown as warning in Clion Rust plugin:
Is it a bug of an plugin or am I doing something bad practice in Rust?
Playground
CLion Rust Plugin Version: 0.2.0.2106-182
The code does compile as written, as the playground clearly demonstrates. Therefore it is a bug in the IDEA Rust Plugin.
Unlike most other Rust plugins that use the Rust Language Server, which uses code from the compiler, and therefore generally provides diagnostics consistent with what the compiler will, IntelliJ IDEA has its own validator, which might get things wrong.

Is there a way to show a warning that a Result is redundant as a return type?

Is there an attribute like #[warn(redundant_result_as_return_type)] to show a warning that Result is redundant as a return type?
#[derive(Debug)]
struct SomeError();
fn process_some() -> Result<(), SomeError> {
Ok(())
}
fn main() {
process_some().unwrap();
}
(playground)
This code produces no warnings despite the fact that Result is not needed as the return type at all.
I've been deciding how to properly implement error handling of a function from the crate used in my project. After digging into the function implementation, it turned out that no errors are generated.
Since then, I want to prevent such cases in my own code. Ideally it would be great to get such warnings from inside of imported crates too, when utilizing methods with redundant Results, but as far as I understand such checking is impossible for used crates without adjusting their code.
The question is in some way the opposite of Possible to declare functions that will warn on unused results in Rust?.
No, there is no such warning, either in the compiler or in Clippy. You could submit an issue to Clippy suggesting they add it, of course.
I challenge that this is a common occurrence or even one that is actually a problem. Even if it was, I'd believe such a warning will have many disadvantages:
I use this pattern to scaffold out functions that I'm pretty sure will return an error once I've implemented them.
A method that is part of a trait cannot change the return type.
You might be passing the function as a function pointer or closure argument and the return type cannot be changed.
Changing the return type breaks API backwards compatibility, so you have to wait until a major version bump.

Why does #[derive(Show)] not work anymore?

With today's Rust nightly the following code doesn't compile anymore:
#[derive(Show)]
enum S {
A,
B
}
fn main() {
println!("{}", S::A);
}
Instead it gives me the following error message:
error: the trait `core::fmt::String` is not implemented for the type `S`
Is there a way to get the old behaviour? Surely it can't be required to implement this by hand for each type.
The old Show trait was split into Display and Debug.
Display is designed for user-facing output, and uses the blank/default format specifier (e.g. {}, {:.10} {foo:} are all using Display)
Debug is designed for debugging/internal output and uses the ? format specifier (e.g. {:?}, {:.10?}, {foo:?} are all using Debug)
Hence, to use the implementation created by #[derive(Debug)] one should write println!("{:?}", ...), instead of the old println!("{}", ...).
Only Debug can be #[derive]d since output like Foo { x: 1, y: 2 } is unlikely to be the correct user-facing output, for most situations (I'm sure it is for some, but then the programmer can write the implementation of Display to do that themselves, or even call directly into the #[derive]d Debug implementation).
This was originally described in RFC 504 and there is ongoing discussion in RFC 565, making the guidelines stated above more concrete.
The answer is to use {:?} instead of {} in format!.

How to disable unused code warnings in Rust?

struct SemanticDirection;
fn main() {}
warning: struct is never used: `SemanticDirection`
--> src/main.rs:1:1
|
1 | struct SemanticDirection;
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: #[warn(dead_code)] on by default
I will turn these warnings back on for anything serious, but I am just tinkering with the language and this is driving me bats.
I tried adding #[allow(dead_code)] to my code, but that did not work.
You can either:
Add an allow attribute on a struct, module, function, etc.:
#[allow(dead_code)]
struct SemanticDirection;
Add a crate-level allow attribute; notice the !:
#![allow(dead_code)]
Pass it to rustc:
rustc -A dead_code main.rs
Pass it using cargo via the RUSTFLAGS environment variable:
RUSTFLAGS="$RUSTFLAGS -A dead_code" cargo build
Another way to disable this warning is to prefix the identifier by _:
struct _UnusedStruct {
_unused_field: i32,
}
fn main() {
let _unused_variable = 10;
}
This can be useful, for instance, with an SDL window:
let _window = video_subsystem.window("Rust SDL2 demo", 800, 600);
Prefixing with an underscore is different from using a lone underscore as the name. Doing the following will immediately destroy the window, which is unlikely to be the intended behavior.
let _ = video_subsystem.window("Rust SDL2 demo", 800, 600);
Put these two lines on the top of the file.
#![allow(dead_code)]
#![allow(unused_variables)]
Making the code public also stops the warnings; you'll need to make the enclosing mod's public too.
This makes sense when you're writing a library: your code is "unused" internally because it's intended to be used by client code.
also as an addition: rust provides four levels of lints (allow, warn, deny, forbid).
https://doc.rust-lang.org/rustc/lints/levels.html#lint-levels
For unused functions, you should make the function public, but watch out. If the struct isn't public, then you'll still get the error as in here:
//this should be public also
struct A{
A{}
}
impl A {
pub fn new() -> A {
}
}
Or if you don't want it to be public, you should put #[allow(unused)]
Directly way to just put the following in the head of the file
#![allow(dead_code, unused_variables)]
The dead_code lint detects unused, unexported items.
The unused_variables lint detects variables which are not used in any way.
More simple way is to put the following in the head of the file
#![allow(unused)]
Ref: rust lint list
You can always disable unused variables/functions by adding an (_) to the variable name, like so:
let _variable = vec![0; 10];
You can add the #[allow(dead_code)] attribute to the struct definition like so:
#[allow(dead_code)]
struct SemanticDirection;
Or you can disable the warning for the entire file by adding the attribute at the top of the file, like so:
#![allow(dead_code)]
struct SemanticDirection;
But these attributes only work if you have the dead_code lint enabled. By default, the dead_code lint is enabled in Rust, but you can disable it by adding the following to the top of your code:
#![deny(dead_code)]
This will disable the dead_code lint for the entire file.
It's generally a good idea to keep the dead_code lint enabled, as it can help you catch mistakes in your code and ensure that you are not introducing unnecessary code into your project. However, it can be annoying when you are just experimenting and trying out different things, so it's understandable if you want to disable it in those cases.
At the top of *.rs file:
#![allow(unused)] // FIXME
using features
#[cfg(feature = "dead_code")]
note: "dead_code" can be replaced by any word.

Resources