Why does this work with #[cfg(tests)] but not without? - rust

Recently, I've been playing with Rust and gRPC using the Tonic libraries. I started looking at how to create a custom Codec and I'm scratching my head over this...
Starting with this chunk of code, I copied the MockEncoder & MockDecoder and added all the same imports used here in the test module:
https://github.com/hyperium/tonic/blob/master/tonic/src/codec/prost.rs#L133-L158
Then I got stuck on this error:
no method named `bytes` found for mutable reference `&mut tonic::codec::DecodeBuf<'_>` in the current scope
method not found in `&mut tonic::codec::DecodeBuf<'_>`rustc(E0599)
codec.rs(55, 37): method not found in `&mut tonic::codec::DecodeBuf<'_>`
The error is complaining about let out = Vec::from(buf.bytes()); because DecodeBuf doesn't implement a bytes method.
Now, for some reason, if I wrap this code I copied in a module with #[cfg(tests)] (similar to how this originally appeared in Tonic) this error goes away. I can compile and run tests without any errors.
Curious, what is #[cfg(tests)] doing that makes buf.bytes() compile and is there something I can import in order to move MockDecoder outside of this test config?

The option is #[cfg(test)] (singular), not #[cfg(tests)] (plural). This is probably not failing because it's not being compiled or run at all, since the option is never set.

Related

avoid conflicting use paths, in rust

I have a module csv and am trying to use the external csv library (use csv::ReaderBuilder;). I am getting a conflict.
Minimal code that exhibits the error
mod csv {
use ::csv::ReaderBuilder;
}
Error message
--> src/csv.rs:4:5
|
4 | use csv::ReaderBuilder;
| ^^^ help: a similar path exists: `crate::csv`
|
= note: `use` statements changed in Rust 2018; read more at <https://doc.rust-lang.org/edition-guide/rust-2018/module-system/path-clarity.html>
My question is how do I avoid such conflicts?
When creating a module, knowing the name of all modules that I may use via use seems un-reasonable. What am I doing wrong? I could name all my modules starting with my_, but this is ugly, and almost not the best solution.
Sorry if some of my terminology is wrong, I am new to rust.
You can disambiguate these where you use them. A leading crate path element indicates that the module belongs to the current crate. A leading empty path element indicates that the module belongs to the namespace root, much like a leading / character makes a filesystem path absolute.
use ::csv::Foo; // Uses Foo from the external csv crate
use crate::csv::Foo; // Uses Foo from the csv module of the current crate
It seems that I did not add the dependency to the Cargo.toml file.
On farther inspection, I see that the error message explains. However, I was confused by the help. It assumes that there is a syntax error in the use command.
In future I need to realise that the help part is a suggestion, not a description of the problem.

run specific .rs file

quick introduction, I came from python I have studied it by myself, and now I'm trying to learn Rust. I find it a bit confusing.
I have a main.rs file and other .rs files in the src directory just to have cleaner and organized code, as each of these other files do specific tasks and the main.rs just put all together with a simple CLI.
I just wanna test a single of these .rs file, or even a single fn inside to check if the result is what I am expecting.
How can I do that? It's simple, it's stupid, but I have read around and found nothing that could help me in the end.
I read this, where it talks about making a tests folder and then using cargo test, I've done it, but it still runs the src/main.rs instead of what I have put in tests. BTW I'm using CLion with the Rust plugin.
Sorry if this is somewhat a duplicate, I looked around but I didn't found an answer.
This funcitonality is not really part of Rust itself, but there are some crates that do it. The one I'm most familiar with is rust-script. It works with a hashbang like #!/usr/bin/env rust-script at the top of your script, then run it with ./script.rs. You can even specify dependencies in the script which get parsed out of some special comments.
Edit: Sorry yes - it looks like you're trying to write/run tests. The page you linked in the book should cover what you're trying to do. I'm not sure what you mean by "it still runs the src/main.rs instead of what I have put in tests". Do you have mod tests in main.rs as well?
you can compile any .rs file using rustc your_file.rs command as long as the file contains main() function. rustc will fail if there isn't main function:
error[E0601]: `main` function not found in crate `abc`
--> abc.rs:5:2
|
5 | }
| ^ consider adding a `main` function to `abc.rs`
error: aborting due to previous error
For more information about this error, try `rustc --explain E0601`.
but you can skip this by marking the file as library crate instead of bin:
rustc you_file.rs --crate-type=lib

Get module resolution entry point in proc-macros

My question is: Is there a way to get the exact module resolution entry point in the proc-macro stage?
First off some background info on what I'm trying to achieve.
I'm in the process of writing a crate that can automatically implement various traits on a struct, such as PartialEq and Into.
This is somewhat special since these traits involve other structs that can theoretically be located anywhere else. I then need to get the actual tokens of that struct, so I can do some crude type checking and automatically map fields that have the same names.
For this reason, I'm doing some crude module resolution of my own by searching the file tree and parsing some files in the current crate.
Such an invocation currently looks like this:
#[derive(InterStruct)]
#[into("crate::into_test::IntoStruct")]
pub struct FromStruct {
...
}
This will now implement
impl From<FromStruct> for crate::into_test::IntoStruct {
fn from(from: FromStruct) -> Self {
...
}
}
This logic already works, if the module containing the struct is located in the $CARGO_MANIFEST_DIR/src folder.
However, if I would want to run this logic in an integration tests folder, this is where it gets tricky.
I couldn't find a way to detect the actual entry point for module resolution during the proc-macro stage. The only thing that's exposed is the $CARGO_MANIFEST_DIR, but there seems to be now way to detect whether we start at src/main.rs, src/lib.rs or tests/some_test.rs.
This get's even more complicated as I'm currently trying to test compile time errors via compiletest-rs.
compiletest-rs (if I understood correctly) creates a temporary directory, copies the file to test to $TEMPDIR/main.rs and directly calls rustc with the exact path to the dependency directories of your project (e.g. '-L target/debug').
Since there's no cargo involved, the rustc call inherits the $CARGO_MANIFEST_DIR environment variable from the parent process. This then points to the actual crate root instead of the $TEMPDIR.
I would really like to properly test the error cases of my crate, but I can't find a way to get the module resolution entry point in the proc-macro stage.

Rust: Cannot access functions in subdirectories [duplicate]

This question already has an answer here:
Can't understand Rust module system
(1 answer)
Closed 2 years ago.
I am learning rust and am going through the book and have run into a question. Is it possible to access files within a folder? I am currently having issues with this.
Here is a project which demonstrates the issue: https://github.com/joemspalding/rust-stack-overflow-file-example/tree/master/src
In this project, I can successfully import functions from a different file, however, trying to access a file from a different folder is where I lose understanding syntactically. I feel I've tried nearly every combination of
mod foo;
mod foo::bar;
use foo;
use foo::bar;
Currently, running cargo run produces the following compile time error
Compiling my-project v0.1.0 (J:\Projects\rust\the_book\ch7\my-project)
error[E0432]: unresolved import `foo`
--> src\main.rs:1:5
|
1 | use foo::bar;
| ^^^ use of undeclared type or module `foo`
error: aborting due to previous error
For more information about this error, try `rustc --explain E0432`.
error: could not compile `my-project`.
To learn more, run the command again with --verbose.
I've been reading into this for hours and all of the resources I can find have great examples of reading code from a file on the same level, but not on reading code through folders.
Another common line I've seen is with the use of folder/mod.rs This seems unstylistic of rust after an update in 2018 and I'd like to avoid it if possible.
You must use mod.rs. It is the preferred option in rust 2018 and above. Module definitions aren't file paths and shouldn't be treated as such. Think of them more as C++ namespaces.
You could also choose to rename your mod.rs to match the name of the folder it is in (Ex: example_a/mod.rs -> example_a/example_a.rs). However I almost never this done and I find its much easier to navigate code with mod.rs.
If your mod.rs doesn't have any useful code, maybe you don't need a submodule.
A mod.rs should have code which relates to its sub modules. If it is only a couple lines long, you may want to skip adding the folder entirely since it doesn't sound like it has any purpose in your specific use case. This isn't like the empty __init__.py files of python 2.

rustdoc no_main "crate-level attribute should be in the root module"

When using the no_main outer attribute in Rust, cargo doc complains about unused attribute and that crate-level attribute should be in the root module.
I am using Cargo 1.42.0-nightly.
Relevant code:
// main.rs
#![no_main]
This only happens when invoking cargo doc; cargo build works as expected.
I have seen https://github.com/rust-lang/rust/issues/62184, which however does not contain any answer.
I have also seen https://github.com/rust-lang/rust/issues/43144, from where I followed to https://github.com/rust-lang/rust/pull/64471, but even though that merge request is already merged, the problem remains.
How to solve this warning?
This warning is caused by known bug in cargo/rustdoc which has however not yet been fixed.
As of now, this can be easily worked around by using the cfg_attr attribute in combination with the rustdoc's cfg(doc) in the following way:
// main.rs
#![cfg_attr(not(doc), no_main)]
This code applies the no_main attribute in all cases, except when the documentation is building.

Resources