One of my dependencies has a few println! scattered around that seem to be debugging artifacts and I'm trying to find a way to suppress them, but haven't had any success so far.
I've been looking at macros, and tried putting one inside the function where the imported struct is instantiated but with no success, likewise when giving it a global scope.
macro_rules! println {
($($rest:tt)*) => { }
}
Is there any way I can use a macro to target an external crate, or any other solution short of forking the codebase?
Related
How do you look up a macro in Rust?
E.g., I was reading the source code for serde_json and encountered the macro tri!.
I ended up downloading the code and running spinning up VS Code. But this isn't always feasible. And sometimes it's a different version, etc. I should be able to read code without running it.
But this is only a specific example. How do you look up any macro in Rust, in any codebase"?
Macros have different lookup rules than normal items. You can find details in the Scoping, Exporting, and Importing section for Macros by Example in the Rust Reference.
Basically there are two kinds of scopes to lookup macros:
path based scoping: which is the same as normal item lookup where it can be imported by use statement or by path:
use macros::a;
a!();
macros::b!();
textual scoping: a non-path-qualified macro will first look at macro definitions in the current module and all parent modules. I think this is better shown with an example:
mod a {
macro_rules! macro_a { () => {}; }
mod b {
macro_rules! macro_b { () => {}; }
mod c {
macro_rules! macro_c { () => {}; }
macro_a!(); // these all work
macro_b!(); // without any
macro_c!(); // explicit imports
}
}
}
This will work across files as well. However, keep in mind that macro definitions are ordered, meaning a macro defined after its use is not considered.
So when looking at source code, I generally search for macros in this order:
Look in the current module for any macro_rules! definitions or matching import statements. This can get hairy if there are wild-card imports, but that's just how it goes sometimes; use your best judgement if the macro could be there.
Look in the crate root (usually main.rs or lib.rs) for similar definitions or imports. This is because often crate-internal macros are designed to be used crate-wide, and following textual lookup above, any macro in the crate root is available everywhere. This is also the likely place where you'll find #[macro_use] definitions either for some internal macros module (as is the case with serde-json), or on extern crate ...; declarations (where they must be at the crate root).
Then look in intermediate modules. I don't think I've ever had to do this personally, but its possible.
Context
Sometimes I find strict typing warnings more distracting than useful while still putting some idea into code, and before having reviewed it for sanity.
I'm looking for a quick programmatic way to prevent "unused declaration" warning, in order to boost my workflow.
Example
I'll try to illustrate what I mean by an example.
// use rand::Rng;
fn breaking_out_of_nested_loops_using_labels() {
let mut innermost_loop_reached: bool = false;
'outermost_loop: loop {
loop {
// if rand::thread_rng().gen::<u8>() >= u8::MAX / 2 {
// break;
// }
loop {
innermost_loop_reached = true;
break 'outermost_loop;
}
}
}
println!(
"Inner loop was {}reached",
if innermost_loop_reached { "" } else { "not " }
)
}
The code results with the following warning:
Obviously the compiler is correct.
Question
I'm curious if there is a quick way to "trick" or ignore unused assignment warnings during typing some initial code, when all you want to know is if the code still compiles.
How do experienced rust programmers go about this? or do you just learn to ignore the warnings until you're ready to process them?
Please note
The commented out code is what I used to prevent the warning from popping up, while still trying the code. Obviously importing a crate and using a random condition is a lot of work, so it's not ideal.
At that point I might as well put the #[allow(unused_assignments)]-allow-rule above my function. But that's what I'm trying to prevent having to do, because;
I might forget to remove it.
It would already interrupt my workflow if I have to copy warnings from the compiler output.
You can try naming the variable _innermost_loop_reached instead.
Adding an underscore in the beginning of the name of a variable prevents the compiler from showing the unused_assignments warning.
You can control lint levels via rustc flags - so for example -A unused_assignments would banish the unused assignments warning.
You can configure Cargo so that it applys specific flags when it calls rustc using a config.toml file, which you can place in the project, or your in ~/.cargo/config.toml, or a number of other places - refer to the cargo documentation.
You place the desired rust flags inside the [build] section like this:
[build]
rustflags = ["-A", "unused_assignments"]
Of course you still need to remember to remove this when you are finished the initial experimental coding phase, but at least it is not sprinkled throughout your code.
Unfortunately it is not possible yet to set the rustflags per profile - it might be great to be able to dampen down the warnings for debug but keep them all for release. There is a feature request open for this so maybe it will be possible in the future.
You can also control the rust arguments with the RUSTFLAGS environment variable. I generally find this less useful for environments like IDEs though, which might make it hard to control the environment variables under which cargo is running.
One solution is to avoid the problem altogether by making using of the fact that loop can be an expression, and assign that expresion to innermost_loop_reached:
fn breaking_out_of_nested_loops_using_labels() {
// Directly assign to `innermost_loop_reached`
let innermost_loop_reached: bool = 'outermost_loop: loop {
loop {
if rand::thread_rng().gen::<u8>() >= u8::MAX / 2 {
break;
}
loop {
// break directly to the top-loop, "returning" `true`
break 'outermost_loop true;
}
}
// "return" `false`
break false;
};
println!(
"Inner loop was {}reached",
if innermost_loop_reached { "" } else { "not " }
)
}
This has the added benefit that all exits from the loop (via break) must be of type bool because innermost_loop_reached is a bool. That is, you avoid most cases where innermost_loop_reached should get a value in the loops but doesn't, wrongfully leaving the default false from your example in place.
https://pastebin.com/2TXGSDLw
Perform the action.
match action {
Add { text } => tasks::add_task(journal_file, Task::new(text)),
List => tasks::list_tasks(journal_file),
Done { position } => tasks::complete_task(journal_file, position),
https://pastebin.com/zb0CCDWT
I've been working on this CLI for what seems like 8 hours. One more error seems to get in my way and while it seems simple enough I can't fix it. Unresolved module and it can't find the path to my task.rs file.
Based from the screenshots you’ve uploaded. It seems the problem might be the name of your struct.
You have a code under task.rs:
pub struct tasks {...}
and then below it
impl Task {...}
I think it’s also recommended having structs with names starting with a capital letter.
PS.
Perhaps copy and paste the code in your post next time? Others might easily see the problem you’re facing. Or perhaps they can copy and paste the codes you’ve posted with the fix as well.
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.
I am using assert_cli crate to test a command line application. While it is very helpful with simple use cases (see some examples in this article), sometimes I want to get the raw output of the command I am testing as a String to do more sophisticated checks (regex, json or just more complex logic in the output).
For that I need to get a copy of the command output verbatim. Here is an example:
extern crate assert_cli;
fn main() {
let a = assert_cli::Assert::command(&["echo", "foo-bar-foo"]);
a.execute();
println!("{:?}", a.expect_output);
}
Somewhat predictably it gives me the following error:
error[E0616]: field `expect_output` of struct `assert_cli::Assert` is private
--> src/main.rs:14:22
|
14 | println!("{:?}", a.expect_output);
| ^^^^^^^^^^^^^^^
It also has a .stdout() method, but that requires OutputAssertionBuilder and there it is also not obvious how to access the actual contents of stdout. You can only do some simple checks using predicates syntax.
assert_cli does internally get the full output of the command during execute as seen in the source code of assert.rs
let output = spawned.wait_with_output()?;
All the internal Command and output variables seem to be private and are never exposed to retrieve the raw stdout. This functionality seems to be too basic to be omitted from assert_cli library. I am probably missing something very obvious...
Q: Is there any way to get raw stdout back as contents of a variable?
This is what I want to achieve ideally:
extern crate assert_cli;
fn main() {
// do simple checkign with assert_cli
let a = assert_cli::Assert::command(&["echo", "foo-bar-foo"])
.stdout().contains("foo-bar-foo")
.unwrap();
// get raw stdout
let cmd_stdout = a.get_raw_stdout(); // how to do it?
// do some additional complex checking
assert_eq!(cmd_stdout, "foo-bar-foo");
}
P.S.: I know I can use std::process::Command separately to achieve this. I wonder if I can still stick to assert_cli since I do 80% of the testing with it.
The library defines only 3 types. None of which allow to access the output directly.
This functionality seems to be too basic to be omitted from assert_cli library. I am probably missing something very obvious...
The library is called assert* and it has all the functions you need to assert stuffs on the output of your command. Getting the actual output is outside the domain of "assertions".
Other people have opened an issue on the repository asking for this exact feature. I suggest you to go there, and tell the author that this feature interests you.