HNHacker News
TopNewBestAskShowJobs

shepmaster

1,167 karma · joined February 6, 2011

Cofounder of the world's first Rust consultancy[1] — we are available to help you and your company with any and everything related to Rust! We also produce the Rust in Motion video series[2] for Manning.

[1]: http://integer32.com/ [2]: https://www.manning.com/livevideo/rust-in-motion?a_aid=jgoulding&a_bid=6a993c2e

submissionscomments
shepmaster··on Correct Git commits with git-autofixup
You could throw it in a gist to start with.
shepmaster··on Correct Git commits with git-autofixup
> using --fixup

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.

shepmaster··on Correct Git commits with git-autofixup
Right, that process is what I do now, outside of Magit. The point of this article is a tool that (attempts to) automatically find the correct commit to combine with. Conceptually it removes the effort taken to move the fixup commit to the right spot; both keystroke-wise and mental effort wise.

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.

shepmaster··on Correct Git commits with git-autofixup
Could you share what your workflow would be? I’m assuming you put the point on the line you want to fix, then use Magit to start a rebase at the last commit that changed that line, then apply your changes, then continue?

I’m a casual Magit user, so learning from other users would be very beneficial.

shepmaster··on Correct Git commits with git-autofixup
Does Magit have a similar feature to what is discussed in this article? Specifically “magically figure out which previous commit these changes should be combined with”?
shepmaster··on Rust Foundation: Hello, World
Can you share a bit about how you’ve integrated Hotwire with Rust? I recently wondered how well they’d pair.
shepmaster··on Show HN: Rust-starter, a boilerplate to build Rust CLI applications
Yep! Really, most of the error handling libraries just reduce the boilerplate associated with creating your own error types. SNAFU also adds some opinions to the mix.

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!

shepmaster··on Show HN: Rust-starter, a boilerplate to build Rust CLI applications
I (the author of SNAFU) absolutely recommend it!

It works well for libraries and applications and has bells and whistles you might want, such as backtrace captures on stable Rust.

shepmaster··on Rust is now overall faster than C in benchmarks
Why does the Rust compiler not optimize code assuming that two mutable references cannot alias? —https://stackoverflow.com/q/57259126/155423
shepmaster··on Rust 1.49.0
> If you didn't want to interpolate the value of e

For those reading along (not Steve) expect does do that, but using the Debug formatter instead of Display, as the grandparent used.

shepmaster··on Rust 1.49.0
https://stackoverflow.com/q/27791532/155423
shepmaster··on Tokio 1.0 – async runtime for Rust
... for not-so-fun parties. ;-)
shepmaster··on Tokio 1.0 – async runtime for Rust
> rustafarian

The community prefers the term "rustacean" to be as inclusive as possible. Please keep that in mind in the future.

shepmaster··on ARM MacBook vs. Intel MacBook: A SIMD Benchmark
Related:

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...

shepmaster··on Error Handling Is Hard
I'm not 100% sure what you mean, so I'll try to cover it broadly.

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

shepmaster··on Error Handling Is Hard
As the author of [SNAFU], another error handling library, this is how I'd encourage it:

    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
shepmaster··on CrateDB: Purpose-built to scale modern applications in a machine data world
A good, multifaceted joke; kudos.

(For those not getting it, Rust’s primary library distribution website is crates.io, one letter different)

shepmaster··on Run Homebrew Natively on Apple Silicon Arm M1
> I'm a bit against using cargo

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.

shepmaster··on Run Homebrew Natively on Apple Silicon Arm M1
> Installs of rust itself aren't succeeding yet for me via Homebrew

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 ;-)

[pr]: https://github.com/rust-lang/rust/pull/79219

shepmaster··on Run Homebrew Natively on Apple Silicon Arm M1
> Rust is really the main thing in my end-user stack I'm waiting on since fzy, bat, exa,

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...

shepmaster··on Apple Silicon M1 chip in MacBook Air outperforms high-end 16-inch MacBook Pro
And I’ve been getting Rust to work on Apple Silicon. It’s only tier 2 for now, but that’s mostly because there are no CI providers so we can’t automatically run tests for it. I’ve been running them by hand.

https://github.com/rust-lang/rust/issues/73908

shepmaster··on Rust After the Honeymoon
> Yeah, but no PDB

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.
shepmaster··on Rust Starter Kit 2020
The post you are replying to says "efficiently implemented with unsafe". For a linked list, you generally get (has unsafe code + efficient) or (no unsafe code + not as efficient).
shepmaster··on Rust Starter Kit 2020
> Long story short, yeah, there's a lot of crates.

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

shepmaster··on My Adventures in MMIO Abstraction
If this kind of thing interests you, make sure to check out the AVR Rust book [1] and the Rust embedded guide [2].

[1]: https://book.avr-rust.com/

[2]: https://rust-embedded.github.io/book/

shepmaster··on Rust testing or verifying: Why not both?
As a previous user of quickcheck and now user of proptest, I can say that proptest feels much better to use because it doesn't tie quite as directly to a single type (as a sibling comment mentions).

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...

shepmaster··on Tower Defense with a twist: all towers must be positioned with CSS Flexbox
> Some layouts are impossible

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.

shepmaster··on Rust 1.46
I literally spend tens of hours a week on Stack Overflow ensuring this isn’t the case, or if it is that it’s clearly notated.

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.

1: https://chat.stackoverflow.com/rooms/62927/rust

shepmaster··on A tale of webpage speed, or throwing away React
> gatsby-plugin-no-javascript

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.

shepmaster··on AVR support merged into Rust nightly
Note that there is still plenty of work to be done in LLVM, Rust, and the ecosystem.

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.

← PreviousPage 5 of 9Next →