1,167 karma · joined February 6, 2011
[1]: http://integer32.com/ [2]: https://www.manning.com/livevideo/rust-in-motion?a_aid=jgoulding&a_bid=6a993c2e
If I understand you correctly, this requires that I think about which commit I want to fixup. Once identified, I can mark my fixup with what commit it should be combined with automatically.
My understanding of the article is that it attempts to automatically figure out which commit to combine with. That’s the feature that I’m interested in.
That’s what I’m looking for: a Magit-native way to make my little fixups without having to manually track which fixup should be applied where in history.
I’m a casual Magit user, so learning from other users would be very beneficial.
You can see what the libraries do by expanding the procedural macros they use. When you look at the output, it's nothing special that you couldn't have done yourself!
It works well for libraries and applications and has bells and whistles you might want, such as backtrace captures on stable Rust.
For those reading along (not Steve) expect does do that, but using the Debug formatter instead of Display, as the grandparent used.
The community prefers the term "rustacean" to be as inclusive as possible. Please keep that in mind in the future.
Why does my native application compiled on Apple Silicon sometimes build as arm64 and sometimes build as x86_64?
Why does my native arm64 application built using an x86_64 build system fail to be code signed unless I remove the previous executable?
[1] https://stackoverflow.com/questions/64830635/why-does-my-nat...
[2] https://stackoverflow.com/questions/64830671/why-does-my-nat...
Ideally the fact that you use SNAFU should not escape from your library; I encourage creating an [opaque] error in most cases.
The current deliberate "leak" is that we implement a [trait] that exposes the ability to get a backtrace from a SNAFU error because the standard library has not yet stabilized backtraces. Once those are stabilized, we should be able to completely isolate and only operate through the `std::error::Error` trait.
[opaque]: https://docs.rs/snafu/0.6.9/snafu/guide/opaque/index.html
[trait]: https://docs.rs/snafu/0.6.9/snafu/trait.ErrorCompat.html
use snafu::{Snafu, ResultExt};
#[derive(Debug, Snafu)]
enum Error {
#[snafu(display("Failed to read {}", filename))]
ReadInput { filename: String, source: std::io::Error },
}
type Result<T, E = Error> = std::result::Result<T, E>;
fn main() -> Result<()> {
let filename = "input.txt";
let s = std::fs::read_to_string(filename).context(ReadInput { filename })?;
println!("{}", s);
Ok(())
}
Unfortunately, this uses the default `Debug` formatting, so what is printed to the user in this `main` example is still less-than-ideal: Error: ReadInput { filename: "input.txt", source: Os { code: 2, kind: NotFound, message: "No such file or directory" } }
I encourage using the `Display` formatter or something more complete.I find that doing this rigorously creates what I call a "semantic backtrace", where the linked list of (error, context, underlying cause) provides a great deal of insight into the problem.
The next release of SNAFU will incorporate something that allows for stringly-typed errors:
use snafu::{ResultExt, Whatever};
type Result<T, E = Whatever> = std::result::Result<T, E>;
fn main() -> Result<()> {
let filename = "input.txt";
let s = std::fs::read_to_string(filename)
.with_whatever_context(|_| format!("couldn't read {}", filename))?;
println!("{}", s);
Ok(())
}
You will also be able to combine stringly-typed errors with the structured errors.Other features of the currently-released SNAFU:
- Custom error types
- Backtraces
- Extension traits for Results / Options / Futures / Streams
- Suitable for libraries and applications
- no-std compatibility
- Generic types and lifetimes
[SNAFU]: https://crates.io/crates/snafu(For those not getting it, Rust’s primary library distribution website is crates.io, one letter different)
Sure and that's fine, but the original comment wasn't clear that they were waiting for homebrew to ship an arm64 version of Rust. The phrasing made it sound like Rust itself was the aspect blocking those tools from working. That's the point I was addressing.
> not system-wide installs
rustup installs Rust into your home directory by default, and then `cargo install` follows suit, so it's not system-wide.
Ah, yes. Homebrew builds Rust itself and building Rust uses a previous beta release to build the current development code.
Until my recent [pr] bumping the beta bootstrap version, building Rust on aarch64-apple-darwin required specifying a nightly version of Rust because we only had nightly artifacts. I've mentioned that to a homebrew developer, so it should flow through soon. I'd expect that you'd only be able to install the nightly release at first.
> if you have recommendations
I'm a Rust fanboy, so I'd recommend installing Rust via rustup ;-)
Can you expand further?
% cargo install bat
Finished release [optimized] target(s) in 2m 21s
Installing ~/.cargo/bin/bat
Installed package `bat v0.16.0` (executable `bat`)
% file $(which bat)
~/.cargo/bin/bat: Mach-O 64-bit executable arm64
% cargo install exa
Finished release [optimized] target(s) in 1m 21s
Installing ~/.cargo/bin/exa
Installed package `exa v0.9.0` (executable `exa`)
% file $(which exa)
~/.cargo/bin/exa: Mach-O 64-bit executable arm64
I don't know what you mean by [fzy], as it appears to be a C program, not Rust.See also:
• The tracking issue for tier 1 support [tracking]
• My intermediate README with instructions [readme]
[fzy]: https://github.com/jhawthorn/fzy
[tracking]: https://github.com/rust-lang/rust/issues/73908
[readme]: https://github.com/shepmaster/rust/blob/silicon/silicon/READ...
Can you expand on this?
C:\rust>cargo new demo
Created binary (application) `demo` package
C:\rust>cd demo
C:\rust\demo>cargo build
Compiling demo v0.1.0 (C:\rust\demo)
Finished dev [unoptimized + debuginfo] target(s) in 2.28s
C:\rust\demo>dir target\debug
Volume in drive C is Windows 10
Volume Serial Number is B4A6-FEC6
Directory of C:\rust\demo\target\debug
10/11/2020 02:03 PM <DIR> .
10/11/2020 02:03 PM <DIR> ..
10/11/2020 02:03 PM 0 .cargo-lock
10/11/2020 02:03 PM <DIR> .fingerprint
10/11/2020 02:03 PM <DIR> build
10/11/2020 02:03 PM 61 demo.d
10/11/2020 02:03 PM 152,064 demo.exe
10/11/2020 02:03 PM 1,101,824 demo.pdb
10/11/2020 02:03 PM <DIR> deps
10/11/2020 02:03 PM <DIR> examples
10/11/2020 02:03 PM <DIR> incremental
4 File(s) 1,253,949 bytes
7 Dir(s) 15,995,387,904 bytes free
`demo.pdb` is readily available.And I'd add one more to the pile: my [SNAFU] crate. It actually does what the author says they do by hand:
> So, I just write the boilerplate and make my errors descriptive enough I don’t need a backtrace. When I want to get fancy I implement the built-in `Error` trait, which used to be kinda useless but is now more helpful. And in another five years it’ll still work just fine.
SNAFU is all about creating enums for each error case so that the hierarchy of types tells you exactly what and where the error came from. In my ideal usage, you don't need a stacktrace or even origin line number / file name because each specific combination of error is used only once.
The nesting of types within specific contexts gives what I like to call a "semantic backtrace"
Example usage:
#[derive(Debug, Snafu)]
enum Error {
#[snafu(display("Unable to read configuration from {}: {}", path.display(), source))]
ReadConfiguration { source: io::Error, path: PathBuf },
#[snafu(display("Unable to write configuration to {}: {}", path.display(), source))]
WriteConfiguration { source: io::Error, path: PathBuf },
}
type Result<T, E = Error> = std::result::Result<T, E>;
fn example(path: &Path) -> Result<()> {
let data = fs::read_to_string(path).context(ReadConfiguration { path })?;
fs::write(data, path).context(WriteConfiguration { path })?;
Ok(())
}
This creates the `Error` enum and implements `std::error::Error` for it, plus what I call context selectors to easily add on to fallible calls to help group them. Note that both SNAFU errors are caused by an `io::Error`, but the context in which the `io::Error` is created is vastly different.> for applications and libraries, respectively
I've yet to understand why people want to draw a line between these two cases. For me, the only difference is that the error type in a library needs to be conscious that it's part of the public API. That's why SNAFU can generate [opaque] error types
---
Other bonuses:
- Doesn't require heap allocation (but can make of use it)
- Works in no-std environments
- Comes with extension traits for `Result` and `Option`, and feature flagged ones for `Future` and `Stream`
- Supports generic errors (types and lifetimes)
- Can create backtraces (either from the backtrace crate or the unstable `Backtrace` type in the standard library)
[SNAFU]: https://crates.io/crates/snafu
[opaque]: https://docs.rs/snafu/0.6.9/snafu/guide/opaque/index.html
With quickcheck, I had to define `MyTypeWithAnOddOffset` and `MyTypeWithAnEvenOffset` (or equivalent formulation) and composing things was tedious or hard.
With proptest [1], things flow much nicer.
[1]: https://github.com/shepmaster/jetscii/blob/2b1039a9fb8d8ad9c...
Do you have any links to demonstrate this? I’m starting to use grid more and more, so I’d like to have a little advance knowledge of when I shouldn’t apply it.
As always, feel free to drop into the Rust Stack Overflow chat room[1], or any of the official Rust discussion channels, and ping me or other Stack Overflow contributors to review and update answers.
Thank you for mentioning this! I’ve been on a passive search for exactly this: the ability to use React and generate a completely static site without even the possibility of JS at runtime.
For example, function pointers accessed in global variables have the incorrect relocation applied. This notably affects the ability to use futures executors.
However, a lot of things do work, and we are always looking for more people to contribute!
Check out https://book.avr-rust.com/ for more.