exDM69 3 hours ago

Why does adding `backtrace` to thiserror/anyhow require adding debug symbols?

You'll certainly need it if you want to have human readable source code locations, but doesn't it work with addresses only? Can't you split off the debug symbols and then use `addr2line` to resolve source code locations when you get error messages from end users running release builds?

namjh 8 hours ago

> Consequently, this also means you cannot define two error variants from the same source type. Considering you are performing some I/O operations, you won't know whether an error is generated in the write path or the read path. This is also an important reason we don't use thiserror: the context is blurred in type.

This is true only if you add #[from] attribute to a variant. Implementing std::convert::From is completely optional. Personally I don't prefer it too as it ambiguates the context. I only use it for "trivially" wrapped errors like eyre::Report.

  • skavi 4 hours ago

    Yup. I absolutely would throw `#[from]` on everything when I started using thiserror, but now only do so in incredibly obvious cases like

      enum CarWontMove {
          EngineTroubles(EngineTroubles),
          WheelsFellOff(WheelsFellOff),
      }
    
    Even then, there’s often some additional context you can affix at that higher level.
lilyball 3 hours ago

> Then, to be able to translate the stack pointer we will need to include a large debuginfo in our binary. In GreptimeDB, this means increasing the binary size by >700MB (4x compared to 170MB without debuginfo).

Surely that's comparing full debuginfo, right? Backtraces just need symbols, not full debuginfo, and there's no way the symbols are 4x the size of the binary.

  • dwattttt 3 hours ago

    There's also split-debuginfo, which allows emission of debug info into a separate file, rather than needing to distribute it in the binary. Then they could capture stack traces, and resolve the symbols later if necessary. That would also address their concern about how long it takes to capture a stack trace, because just gathering the addresses themselves is quick.

shepmaster 8 hours ago

Hey all, I’m the author of SNAFU (mentioned in the article). I’m off to bed now, but I’d be happy to try and answer any questions people might have sometime tomorrow.

I’m glad to see SNAFU was useful to others!

  • zamalek 2 hours ago

    Its looks really neat! Two questions:

    * can it be used as a build dependency (i.e symbols from the snafu crate don't appear in the generated code).

    * I assume you have to use one of the macros (ensure! or location!) when constructing an error that contains a location?

Sytten 7 hours ago

What is really annoying with thiserror is the wizard refusal to give us an easy way to print the error chain. No I dont want to convert it to anyhow just to print the error...

  • lumost 7 hours ago

    Rust is full of these, I’ve found the community simply falls back on user error to understand rust when vexed by in my opinion basic software operations.

    As someone who works extensively in cpp/java/python. I want so much to love rust, but unfortunately I haven’t found it to be productive after 6+ side projects.

    • nixpulvis 7 hours ago

      Rust's community is slightly more fragmented than it should be. The community being built while the language was changing so dramatically (e.g. async) didn't help, but it also is part of what lead to Rust in the first place.

      But it's still somewhat young, lots of stuff is being built. So some of the lack of productivity probably just comes from not knowing the right stacks yet.

gfreezy 8 hours ago

    async fn handle_request(req: Request) -> Result<Output> {
        let msg = decode_msg(&req.msg).context(DecodeMessage)?; // propagate error with new stack and context
        verify_msg(&msg)?; // pass error to the caller directly
        process_msg(msg).await? // pass error to the caller directly
    }

    async fn decode_msg(msg: &RawMessage) -> Result<Message> {
        serde_json::from_slice(&msg).context(SerdeJson) // propagate error with new stack and context
    }

how to capture the virtual stack when `verify_msg` returns an error? Do you have some lint to make sure every error is attached with a context?
samanthasu 10 hours ago

A good error report is not only about how it gets constructed, but what is more important, to tell what human can understand from its cause and trace. In this example, we analyzed and showed how to design stacked errors and what should be considered in this process.

dgfitz 8 hours ago

Rust is such a powerful yet completely disgusting language. I’m teaching myself rust out of spite at this point.

Everything about the syntax of the language is awful.

  • GrantMoyer 7 hours ago

    This seems to be a fairly common sentiment. I consider Rust's syntax fairly consistent and elegant for a curly brace language, but evidently I have some blind spots. What quibbles do you have with Rust's syntax?

    • akira2501 7 hours ago

      The explosion of single character sigils and the taint of C++'s template syntax.

      • maxk42 5 hours ago

        The only single-character sigils I can think of are '&', '*', '\'', and maybe '?'. Am I missing any?

        • akira2501 3 hours ago

          I kinda feel like macros!() should count.

        • troupo 4 hours ago

          It's probably the explosion of those characters and punctuation characters like in this example: https://x.com/AndersonAndrue/status/1864457598629540348

          To quote Tsoding, https://x.com/tsoding/status/1832631084888080750: "Rust is a very safe, unergonomic language with annoying community and atrocious syntax. Which is somehow surprisingly miles better than modern C++."

          • saghm an hour ago

            > It's probably the explosion of those characters and punctuation characters like in this example: https://x.com/AndersonAndrue/status/1864457598629540348

            I feel like there's plenty of places to make criticisms of Rust's syntax, but the example they picked has like half a dozen places where the full path to reference an item is used instead of importing it. Sure, there are languages where you're required to import things rather than referencing them in the full path, but there are also languages where you don't have any flexibility in the paths to use something (e.g. Go and Java) or where they dump literally everything into a single namespace with no context (e.g. C and C++). Using the entire path to something instead of importing it is absurdly less common by at least an order of magnitude over importing things directly, so it's not like people are abusing it all over the place (if anything, people probably import things _more_ than they need to, like with top-level functions that might otherwise make their provenance obvious). Having an option to do things verbosely that most people don't actually do is "unergonomic"? It's like saying the problem with Unix file paths is that using absolute paths for literally everything is ugly; sure, it can be, but that's also just not how 99% of people use them.

          • swiftcoder 2 hours ago

            Anderson's example has literally one more sigil than the equivalent C++

      • littlestymaar 3 hours ago

        > and the taint of C++'s template syntax.

        Interestingly enough, nobody says that when talking about TypeScript…

      • Vecr 7 hours ago

        What's mandated to be a single character? I'm not sure what the popular style is today.

  • jtrueb 8 hours ago

    Which statically typed language do you find most agreeable?

    Same question for any language.

  • speed_spread 8 hours ago

    Rust's syntax is largely irrelevant to its purpose. If you don't see the need for it, might as well learn something else.

    • more-nitor 7 hours ago

      idk if its about a few syntax, then it's possible to make a temp proc-macro for those