If you want to see assembly output to check how #Rust optimizes a function, you can use https://rust.godbolt.org/
MIR-based borrow check (NLL) status update by Niko Matsakis: http://smallcultfollowing.com/babysteps/blog/2018/06/15/mir-based-borrow-check-nll-status-update/ #Rust #language
PSA: #StackOverflow is an unpleasant place. It's better to ask #Rustlang questions on https://users.rust-lang.org where you will get a good answer, even if you ask a "duplicate" question about lifetimes, like every Rust user does.
The convenient way to use C libraries in #Rustlang is via "sys" crates.
Here's a comprehensive guide to making sys crates: http://kornel.ski/rust-sys-crate
I think I'll try to collect any blog posts I find with insight and clues to good #Rust programming with the hashtag #RustWisdom
This is the first such collected blog post: https://jwilm.io/blog/from-str-to-cow/
Methods taking `&mut self` can't take anything from self as arguments: http://smallcultfollowing.com/babysteps/blog/2018/04/16/rust-pattern-rooting-an-rc-handle/
If you need to find'n'replace expressions in #Rust code, use https://github.com/google/rerast
For example, you can replace all uses of the old `try!()` macro with the `?` operator that replaced it:
https://users.rust-lang.org/t/automatically-replace-all-try-with/16873
Cargo build scripts (build.rs) need special care to support cross-compilation correctly.
Don't use `#[cfg(target…)]`/`cfg!(target=…)`, because all macros and constants in the source code are for the machine that does the compilation, which may be different from the architecture the code is cross-compiled for (e.g. macOS can build libraries for Android).
Instead, check values of `std::env::var("TARGET")`, `CARGO_CFG_TARGET_ARCH`, etc.
https://kazlauskas.me/entries/writing-proper-buildrs-scripts.html
Open documentation for your project and its dependencies:
cargo doc --open
Or for a specific dependency only:
cargo doc -p crate_name --open
And for #Rustlang itself:
rustup docs
It all works offline.
Get automated improvement suggestions for your code from Clippy:
cargo +nightly install --force clippy
cargo clippy # run in your project directory
If some suggestions are too nitpicky for you, you can hide them by adding `allow(<clippy warning name>)` to your code:
#![cfg_attr(feature = "cargo-clippy", allow(too_many_arguments))]
Clippy depends on Rust compiler version, so you'll need to install it again after every #Rust update.
for_each is a thing now! https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.for_each
#Rustlang iterators are evaluated lazily, so they don't do anything until they're used to produce a value (e.g. `next()`, `collect()`, `count()` or `for i in iter {}`)
There's no "for_each()" method to just run an iterator without getting values out of it. Use `for _ in iter {}` instead.
When implementing a custom iterator you may be tempted to reuse the same buffer for each element for efficiency. Unfortunately, that won't compile, because the `Iterator` trait allows such usage:
let one = iter.next();
let two = iter.next();
If you could return iterator's internal buffer, then `one`'s content would be overwritten when `two` is created.
Use `StreamingIterator` instead: https://github.com/sfackler/streaming-iterator
#Rustlang won't let you cut the branch you're sitting on.
Sometimes you need to change a complex struct or enum based on its contents. However, you can't do this inside a `match` that takes references, because the references inside the `match` keep a "lock" on the whole object and prevent it from being replaced.
The solution is to use `match` only to check the condition, and perform replacement in a separate step after the `match`.
It's better explained with code:
https://play.rust-lang.org/?gist=f7616168b8aba14a6c387a8f5df3eec7
Citrus: C to Rust transpiler:
https://users.rust-lang.org/t/citrus-c-to-rust-converter/12441
Cannot move a value? Swap it instead.
#Rustlang debug print format `{:?}` prints the whole expression in one line.
There's a pretty-print `{:#?}` which prints structs and vectors in a nice multi-line indented format.
println!("{:#?}", complex_value);
If you're implementing Debug trait for your types manually, check out Formatter methods to support pretty-printing:
In functions returning `Result` you can avoid repeating `Ok()` all the time by moving it to the outermost scope.
Instead of:
match foo {
bar => Ok(1)
baz => Ok(2)
quz => Ok(3)
_ => Err("etc"),
}
use:
Ok(match foo {
bar => 1,
baz => 2,
quz => 3,
_ => Err("etc")?,
})
#Rustlang uses types to automatically manage memory.
The owned `String` type tells the compiler to free it.
The borrowed `&str` tells the compiler NOT to free it.
But you can't mix them, because the compiler won't know whether to free the variable or not:
let label = if x != 0 {x.to_string()} else {"zero"};
The tip:
let tmp;
let label = if x != 0 {tmp = x.to_string(); &tmp} else {"zero"};
Now the compiler knows to free the `tmp`, but not the `label`.
Cow: https://is.gd/vi8eMF
If you have an iterator of `Result`s, you can collect and unwrap all values into a `Vec` on success or return the first `Err` found:
let files_contents = file_names.iter().map(read_file).collect::<Result<Vec<_>, _>>()?;
If you did `.collect::<Vec<_>>()` instead, you'd have an array of mixed `Ok`/`Err` values.
See in #Rust playground: https://is.gd/4GZ45I