Rust promotes itself on the compiler having extensive static analysis and error reporting. What they don't tell you is that most of the time these errors will either make no sense or just straight up be wrong.

@animeirl i keep running into issues like it infers something and that leads to an error somewhere else. you have no way of fixing the error because it's caused by an inferred lifetime in a different place...

@valerauko I spent the past few hours trying to figure out why the compiler was telling me the types in a Result didn't implement a trait, even though they did. It turned out the actual problem was that one of the wrapped Errors didn't implement a completely different, unrelated trait.

@animeirl ah yes the "this returns this library's error class so you can't just ?. because 🤷 "

@valerauko I mean the common cause of that is the error you're converting to not implementing From<OtherError>, but this is weird shit like the framework I'm using requiring any error type that can be sent to the user to implement Debug, but the compiler check for that happening in some weird place rather than where you implement the trait that actually sends the data to the user.

@valerauko Once I solved that error, it started giving me a new one in the same place complaining about returning a borrowed value that I can only assume must be deeply nested in an external library macro because I've never heard of it and it's called "__transform.0.0" and of course the rust compiler doesn't tell me where the fuck this actually is

@valerauko I need to take a break but I'll paste some fragments somewhere after dinner

@animeirl They're usually not wrong. If the error is *wrong*, that's a compiler bug. More likely is that the error was correct and the result of a deeper cause, likely mentioned in the notes.

It's part of learning the language that you struggle with the compiler until you better understand it.

@ascclemens Probably. Do you have any recommendations for reading that would help me understand lifetimes? I could just be a moron but I found the rust book's documentation on the subject unhelpful.

@animeirl Besides the Rust book and Learn Rust by Example, I remember searching frustratedly and finding a few blog posts explaining them, but I can't seem to find them anymore. :c

For most people, it's an entirely new way of conceptualising memory management, and it took me a month or two of banging my head against the compiler before I started to grasp it and start making greater strides.

In case you've been looking at an old version:

@ascclemens Yeah i've read it, but I still do not understand it, especially when it comes to stuff where you're dealing with multiple lifetimes. Currently I have more luck just brute forcing every possibility until it compiles since so far my attempts at understanding what's going on have just resulted in me being completely wrong for reasons I still don't understand and spending hours neither accomplishing or learning anything

@animeirl It can get tricky working with multiple different lifetimes when you still don't fully grasp having one lifetime.

It helps to reason about where in the code the memory is allocated, then where it's being borrowed. If it's possible the memory can be freed while you still have a reference to it, that's not allowed.

@ascclemens Yeah I'm mainly running into it with third party libraries where it's unclear where that's happening and the compiler doesn't give you any errors until you try to use your implementation of a trait a specific way and it blows up. That's probably the library/documentation's fault as much as the language though. My other main gripe with rust so far is that, and maybe I'm missing something, but the whole builder pattern thing seems incredibly cumbersome and shitty and I'm constantly scratching my head at how this is the pattern they came up with.

@animeirl In my experience, that means the implementation is doing something wrong or the trait isn't flexible enough for what you want.

There's &mut self builders and self builders, though I see no issues with them. They're tedious to write but fine to use. I'm sure there's a crate that uses a proc macro to make a builder for a given struct. Maybe

@ascclemens The issue is you can create a broken implementation (at least w/r/t lifetimes) and have no idea until later since the compiler sees nothing wrong with the implementation itsself. Kinda hard to articulate since I still don't know why it caused an error.

As for builders: Tedious to write (and also to read, let's not forget main projects have multiple developers) is the main issue. I looked at derive_builder but it breaks autocomplete (at least with rls) which is kind of a nonstarter for something that exists entirely to generate public facing apis.

@animeirl I'm not sure I agree. Your trait may be too restrictive to allow what you want, but that isn't a fault of the language. The compiler catches it when you try to use it in a way that it can't be used, which is a good thing. That's assuming it actually is the trait that's the problem.

I've never seen a builder pattern that isn't tedious. Macro expansion is getting better; eventually there will be good autocomplete. ;-;

@ascclemens The problem is the trait Im implementing only has one use case

@ascclemens and yeah, the builder pattern is inherently tedious. My complaint isn't that rust uses a particularly bad implementation of the builder pattern, my complaint is that it uses the builder pattern at all

Sign in to participate in the conversation

We love to post!