Elegant way to prevent unused assignment? - rust

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.

Related

Is there a way to enforce correct spelling of features?

Let's assume I have the following feature defined in Cargo.toml:
[features]
my_feature = []
And the following code lives in src/lib.rs:
#[cfg(feature = "my_feature")]
fn f() { /* ... */ }
#[cfg(not(feature = "my_faeture"))] // <-- Mind the typo!
fn f() { /* ... */ }
How can I enforce, that the feature-strings are matched against the list of both explicitly defined and implicitly available features in Cargo.toml so that for instance typos could be avoided?
When RFC 3013, "Checking conditional compilation at compile time", is implemented, there will be warnings for a #[cfg] referring to a feature name that is not declared by Cargo, just as you're asking for. However, the implementation only just got started (Sep 28, 2021).
The means of operation described in the RFC is just as you suggested, ‘cargo would pass down the flags to rustc’.
It may be worth noting that this will not check all conditions appearing in the source text; as described in the RFC:
This lint will not be able to detect invalid #[cfg] tests that are within modules that are not compiled, presumably because an ancestor mod is disabled.
So, it will not confirm that all #[cfg(feature)] are valid on a single cargo check — you will need to test with your various features or combinations of features. But those are the same combinations that you would need anyway to check for compile errors in all of the regular source code that could be enabled; once you do that, the lint will assure you that you don't have any #[cfg(feature)] that are never enabled due to a typo.

Is there a way to silence output from dependencies in Rust?

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?

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.

node.js most performant way to skip a part of code

In compiling languages like C we have a preprocessor that can be used to skip parts of program without compiling them, effectively just excluding them from the source code:
#ifdef SHOULD_RUN_THIS
/* this code not always runs */
#endif
So that if SHOULD_RUN_THIS is not defined, then the code will never be run.
In node.js we don't have a direct equivalent of this, so the first thing I can imagine is
if (config.SHOULD_RUN_THIS) {
/* this code not always runs */
}
However in node there is no way to guarantee that config.SHOULD_RUN_THIS will never change, so if (...) check will be performed each time in vain.
What would be the most performant way to rewrite it? I can think of
a) create a separate function to allow v8-optimizations:
function f(args) {
if (config.SHOULD_RUN_THIS) {
/* this code not always runs */
}
}
// ...
f(args);
b) create a variable to store the function and set it to an empty function when not needed:
var f;
if (config.SHOULD_RUN_THIS) {
f = (args) => {
/* this code not always runs */
}
}
else {
f = function () {} // does nothing
}
// ...
f(args);
c) do not create a separate function, just leave it in place:
if (config.SHOULD_RUN_THIS) {
/* this code not always runs */
}
What is the most performant way? Maybe some other way...
i personally would adopt ...
if (config.SHOULD_RUN_THIS) {
require('/path/for/conditional/module');
}
the module code is only required where needed, otherwise it is not even loaded in memory let alone executed.
the only downside is that it is not readily clear which modules are being required since your require statements are not all positioned at the top of the file.
es6 modularity adopts this dynamic module request approach.
PS use of config like this is great since, you can for example, use an environment variable to determine your code path. Great when spinning up, for example, a bunch of docker containers that you want to behave differently depending on the env vars passed to the docker run statements.
apologies for this insight if you are not a docker fan :) apologies i am waffling now!
if you're looking for a preprocessor for your Javascript, why not use a preprocessor for your Javascript? It's node-compatible and appears to do what you need. You could also look into writing a plugin for Babel or some other JS mangling tool (or v8 itself!)
If you're looking for a way to do this inside the language itself, I'd avoid any optimizations which target a single engine like v8 unless you're sure that's the only place your code will ever run. Otherwise, as has been mentioned, try breaking out conditional code into a separate module so it's only loaded if necessary for it to run.

Is there any fast tool which performs constant substitution without stripping out comments in JavaScript source code?

For example, setting MYCONST = true would lead to the transformation of
if (MYCONST) {
console.log('MYCONST IS TRUE!'); // print important message
}
to
if (true) {
console.log('MYCONST IS TRUE!'); // print important message
}
This tool ideally has a fast node.js accessible API.
A better way to achieve what you want -
Settings.js
settings = {
MYCONST = true
};
MainCode.js
if (settings.MYCONST) {
console.log('MYCONST IS TRUE!'); // print important message
}
This way, you make a change to one single file.
google's closure compiler does, among other things, inlining of constants when annotated as such, leaving string content untouched but I am not sure if it's a viable option for you.
Patch a beautifier, for example
Get the JS Beautifier https://raw.github.com/einars/js-beautify/master/beautify.js written in JS.
Replace the last line of function print_token() by something like
output.push(token_text=="MYCONST"?"true":token_text);
Call js_beautify(your_code) from within nodejs.
The Apache Ant build system supports a replace task that could be used to achieve this.
Edit: Whoops. Gotta read title first. Ignore me.
Google Closure Compiler has such a feature:
You can combine the #define tag in your code with the --define parameter to change variables at "compile" time.
The closure compiler will also remove your if-statement, which is probably what you want.
Simply write your code like this:
/** #define {boolean} */
var MYCONST = false; // default value is necessary here
if (MYCONST) {
console.log('MYCONST IS TRUE!'); // print important message
}
And call the compiler with the parameter:
java -jar closure-compiler.jar --define=MYCONST=true --js pathto/file.js
Regarding you API request: Closure Compiler has a JSON API.

Resources