Reputation: 1022
I'm starting to grasp Rust modules, but I have the following in a crate's src
directory. If I make a small modification (add some whitespace or rename the test function), save and then immediately run cargo test
I get a warning for an unused function, but if I wait a few seconds, and run it again, it runs with no warnings.
lib.rs
mod greet;
#[test]
pub fn it_greets_the_world_correctly() {
assert_eq!("Hello, world!", greet::greet("world"));
}
greet.rs
pub fn greet(name: &str) -> String {
format!("Hello, {}!", name)
}
But when I run cargo test
I get the following:
$ cargo test
Compiling hello v0.1.0 (file:///F:/workspace/hello_rust)
src\greet.rs:1:1: 3:2 warning: function is never used: `greet`, #[warn(dead_code)] on by default
src\greet.rs:1 pub fn greet (name: &str) -> String {
src\greet.rs:2 format!("Hello, {}!", name)
src\greet.rs:3 }
Running target\debug\hello-111b9369d8889475.exe
running 1 test
test it_greets_the_world_correctly ... ok
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured
Doc-tests hello
running 0 tests
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured
and then a few seconds later...
$ cargo test
Running target\debug\hello-111b9369d8889475.exe
running 1 test
test it_greets_the_world_correctly ... ok
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured
Doc-tests hello
running 0 tests
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured
I'm not interested in suppressing the warning, I'm curious as to how Rust can possibly think the function is not being used when it's obviously called, since the test passes in both runs of the test.
Upvotes: 2
Views: 1141
Reputation: 430671
Check the output closely:
$ cargo test
Compiling hello v0.1.0 (file:///F:/workspace/hello_rust)
Running target\debug\hello-111b9369d8889475.exe
$ cargo test
Running target\debug\hello-111b9369d8889475.exe
When you execute cargo test
the second time, nothing has changed with your code. Because nothing has changed, the code doesn't need to be recompiled.
Compiler warnings like unused functions are only generated when the compiler runs. If the compiler doesn't run, there won't be any warnings.
Changing the code will trigger a recompilation.
The followup question is, why does it think the function is unused? Simon Whitehead's answer covers that. Even though the function is marked pub
, the module it's in is not public. That means it's impossible to call the function outside of the library. Since there are no calls to it inside the library, it's unused.
Upvotes: 1
Reputation: 65079
Using cargo test --verbose
will give you some answers.
Firstly cargo test
will compile everything for the lib
with --crate-type lib
. This is what is causing your warning. greet::greet
is not actually called in your library code.
Next, cargo test
will run rustc --crate-type lib --test
against the library as a separate step. This one does call greet::greet
, and so you get no warning.
Now, if you touch the files again and change the test to this:
assert_eq!("Hello, world!", "Hello, world!");
You'll note you get two warnings of the same thing ... because both steps don't reference the greet::greet
function (the library doesn't call it.. and the tests don't call it).
I think this is a valid warning and is what you want: The warning is saying you have a method that isn't called in your library code.. even if a test calls it. I think, in a larger codebase, you would want to be warned and clean up your tests that are now testing functions that aren't used in the main codebase.
Upvotes: 2