1. 20
  1.  

  2. 17

    I have written nothing but Rust code for my day job for the past three weeks and nothing but Rust, C, and various little scripts for the last year and a half. I love Rust more than any other language. I feel like I need to start with that before I say:

    I think the author probably made the right choice.

    Where I work our codebase is a very large C application where we’re slowly introducing more and more Rust as we introduce new features. But almost all of it all of the new Rust code we’re introducing is for features that are mostly isolated from the rest of the codebase. Because you know what is a real pain? FFI

    The fact that the author has a code base that’s mostly C++ with just module that is Rust probably makes this even more painful since they two layers of impedance mismatch. One that is Rust to C and one that is C to C++. The fact that their goal is to have a working program means that all the type wrangling they have to do where neither the C++ type system nor the Rust type system can help is just wasted mental effort.

    The problem isn’t Rust and the problem isn’t C++. The problem is that it takes much more work to use them together and in this case there just wasn’t a payoff coming from that effort. I think that’s totally reasonable.

    1. 10

      The comment section on the linked post is is full of people getting upset at the very idea of someone not liking Rust. Never seen that before…

      1. 10

        Never seen that before…

        It seems common enough to me. At least I have seen it in action plenty of times, especially over on HackerNews. There is even a joke/moniker for it: “Rust Evangelism Strike Force”. People tend to get very worked up and defensive about things they like I suppose.

        Do note that it definitely seems, based on what I have read, that such behavior is generally frowned on by the Rust team itself. It also /maybe/ doesn’t seem quite as prevalent as it used to? Not sure.

        1. 4

          Yes, there is an ongoing significant effort by many of the people in the Rust community to actively work against aggression. There are a lot of messages happening behind the scenes on the platforms that support it where people will be asked to use language that will be more welcoming.

          1. 5

            Yeah I was being sarcastic :)

            Do note that it definitely seems, based on what I have read, that such behavior is generally frowned on by the Rust team itself.

            Given that people like Steve Klabnik do it on reddit all the time, I doubt that’s the case

            1. 10

              Steve can often be seen disagreeing with things he views as mischaracterizations, usually in a pretty respectful way. I can’t think of an example of him being upset that someone didn’t like rust though.

              I think people sometimes get the impression that he is on the RESF because he can be seen engaging everywhere, but he’s really advocated strongly for NOT doing what you describe. If you’re everywhere, you tend to get associated with the people who might seem to be “on your side” even if they are going about that in a way that you really disagree with. I don’t think Steve would consider people on the RESF to be on his side at all, though.

              1. 2

                Well, also cuz it was his job to be everywhere promoting it. All the community team members have publicly denounced the kind of behavior in that comment thread, though. They know it’s not good for their goals. Certainly not coming from them. Just Internet as usual.

          2. 6

            I’ve seen it often enough that I don’t bother talking about Rust any more.

            I’m a C++ developer, but I keep an eye on Rust and Go just to stay up on what’s going on in “systems languages”. I’ve mentioned several times that I don’t see a big advantage to using Rust, since I already know C++ well enough to avoid most of the errors Rust solves. Valgrind, Coverity, and newer C++ features like shared_ptr can eliminate a lot of the errors that Rust tries to solve.

            But according to some Rust zealots, there’s no way that’s true, and the mere fact that I’ve suggested it means I’m ignorant to the problem and I’m causing buffer overflows left and right.

            EDIT: Too early, took me a minute to notice it’s sarcasm

            1. 3

              newer C++ features like shared_ptr can eliminate a lot of the errors that Rust tries to solve.

              unique_ptr is slightly harder to misuse, IMO. shared_ptr preserves the ownership quandary that Rust helps mitigate.

              Undefined behavior is everyone’s nemesis, IMO. UBSan helps but

              I already know C++ well enough to avoid most of the errors Rust solves

              And so you probably know it well enough to recognize the bugs you’ve introduced when you’ve spent some time debugging an issue.

              Valgrind, Coverity, and …

              IMO if you value static checkers like Coverity’s, then it stands to reason that you might like a Sufficiently Smart Static Checker. But if C/C++ had to be constrained to a subset of the current language in order to give that Sufficiently Smart Static Checker the additional context it needed to find bugs, would you still find it interesting? If the answer’s “yes”, then it seems to me like Rust isn’t far from what you’d get from a constrained C++. If the answer’s “no” then maybe C++ is ideal for your use.

              cargo and the crates infrastructure is Rust’s big win, in my opinion. Safety features are just the entrance criteria for a new language.

              1. 1

                I’m not a Rust zealot, but I settled on the default approach of “if you are using C or C++ for new things in 2019, there is something going horribly wrong; but I’m open to hear the reasoning to convince me otherwise”.

                Nothing is worse than C/C++ developers thinking they understand their language, despite a million man-decades of evidence pointing to the exact opposite.

                1. 6

                  There is a difference between knowing it well enough to write a compiler compliance suite, and knowing it well enough to quickly deliver business value.

                  Please do not keep parroting the same “C/C++ is evil” meme, and certainly don’t lump them together.

                  1. 3

                    The only difference is whether the result of not knowing it well enough will kill people or just slightly reduce some business value (isn’t it crazy how C and C++ have trained the general populace to not even expect programs to be reliable?).

                    Please do not keep parroting the same “C/C++ is evil” meme, and certainly don’t lump them together.

                    It took people a few decades to figure out that smoking kills, so regardless of whether you consider it “evil”, I hope that in the future C++ compilers ship with mandatory shock pictures that show the consequences of using C++.

                    1. 3

                      isn’t it crazy how C and C++ have trained the general populace to not even expect programs to be reliable?

                      Please provide evidence for such big claims. As a personal anecdote, I have to deal with much more unreliability caused by Java software than by C/C++.

                  2. 1

                    FWIW, this is exactly the type of response I was talking about. You’re right, obviously I have no idea what I’m doing.

                    I’m not interested in this tedious argument, so I won’t be replying again.

                2. 2

                  Yeah, there were some assholes in there. They should knock it off given it’s certainly not doing any favors for Rust adoption or even making new friends who work on cool projects like Dust3D.

                3. 1

                  TLDR: he went back to C++ because he was adding too many “unsafe” Rust blocks - that is, he didn’t grasp Rust core principles yet.

                  1. 10

                    Do you realize that your comment is very similar to some C and C++ experts saying that people have security vulnerabilities because they’re not experienced enough?

                    1. 10

                      No, it’s actually just hard to learn Rust due to how the borrow-checker forces you to change your design and coding habits. It’s a wall all the newcomers hit. In the article, the author even mentions this:

                      “ I know the friction is greater because I am still a Rust learner, not a veteran”

                      Author then says they’re trying to write the kinds of data structures that Rust team says are the hardest to borrow check. That’s a huge jump. The Rust team usually tells people to avoid stuff like that in favor of easier examples. People can gradually pick it up. There’s also resources out there like the linked lists article to help speed the process up. One other thing I hear developers mention is using a data-driven design rather than control-flow-oriented design helps, too. I’m still unclear on fully what that means but quite a few say it. Gotta be an article somewhere…

                      Long story short, he’s an amateur at Rust applying it to the hardest problems. He should probably stick to C, C++, or unsafe Rust for the hardest stuff. He can rewrite those components later in safer Rust if he figures out how. I tend to just Google stuff like this in case others ran into same problems. Found one BST article. Anyone that can read Rust tell me if that one borrow checks?

                      1. 4

                        When they say “data-driven” design, they’re pointing you towards a more ECS-like design. You can see an example of how this plays out on the GUI side in this talk: Data Oriented GUI in Rust by Raph Levien - Bay Area Rust Meetup

                        In short, rather than a tree of widgets, where each widget ends up with a reference to its children and its parent, you end up with an array of widgets, each of which is identified by its index in that array. Now when you want to refer to a widget you’re just indexing into an array rather than dereferencing a pointer. This plays well with the borrow checker.

                        1. 1

                          I’m wondering in which way this index-based approach is superior to unsafe code? I don’t really know Rust but to me it seems like sidestepping the problem since you can easily end up with indices that point to freed or invalid array elements.

                          In other words, many compile time guarantees are lost.

                          1. 3

                            I believe it’s a kind of a compromise. In that you still may get logic errors, but at least consequences won’t be so dire and will be easier to track. With unsafe blocks, you’re getting back to Undefined Behavior-like territory, basically risking memory corruption and sabotaging of any typesystem guarantees.

                            1. 1

                              Fair enough. Having hunted my share of nasty buffer overflow bugs, I can definitely see the benefit here even though logic errors are not caught at compile time.

                            2. 3

                              I’ve seen some approaches that use “generational indices”, which is basically where you store a tuple of (generation, item) as elements in the array, and your “reference” to that item is (generation, index). If you update the item, you bump its generation. Then when you go to access the item you compare the generations. If they don’t match, that means your “reference” is stale, and you can handle that however you want.

                              1. 3

                                this is what jonathan blow pointed out, there was a ton of discussion around it:

                                https://www.youtube.com/watch?v=4t1K66dMhWk (the jblow rant)

                                https://www.reddit.com/r/rust/comments/9fqget/jonathan_blow_entity_systems_and_the_rust_borrow/

                                I feel like it was discussed a lot on HN and maybe here too but I can’t find it.

                              2. 1

                                Thanks! I’ll check it out.

                              3. 2

                                No, it’s actually just hard to learn Rust due to how the borrow-checker forces you to change your design and coding habits. It’s a wall all the newcomers hit.

                                Yes and it’s actually hard to learn safe C/C++. As @azdle pointed out below, my issue with the comment was the generic dismissal of real problems that people face with Rust, which robs us of an objective opinion of what to expect from migrating to it.

                                Long story short, he’s an amateur at Rust applying it to the hardest problems. He should probably stick to C, C++, or unsafe Rust for the hardest stuff. He can rewrite those components later in safer Rust if he figures out how. I tend to just Google stuff like this in case others ran into same problems. Found one BST article. Anyone that can read Rust tell me if that one borrow checks?

                                The point is, that those are hard problems in Rust, and not in other languages, and the author doesn’t wanna waste time doing it in Rust, when they can do it much faster in C++. What I understood was that the author just wants to work on Dust3D, and not on programming languages.

                                1. 1

                                  my issue with the comment was the generic dismissal of real problems that people face with Rust

                                  I certainly wouldn’t want that. Another person was griping about the FFI. I expect most new languages to have a hard time integrating with C++ code. I expect indirections which might hurt performance too much. So. there’s another objection that was valid on top of learning borrow checker.

                                  “that those are hard problems in Rust, and not in other languages,”

                                  They are hard problems in other non-GC languages if your goal is temporal safety and race freedom. Even OpenBSD with its great coders kept having temporal errors. The races are often heisenbugs difficult to track down. Having the compiler guarantee these properties are preserved on all inputs is something C and C++ don’t have that I’m aware of.

                                  Now, let’s say you don’t need them. You might not need Rust given that’s one of main selling points. Let’s say you don’t always need them which is consistent with OP. As in, a few data structures were too hard to do. I’ll point out something folks rarely bring up in these discussions: Rust can do both unsafe and reference-counted pointers. As in, you can drop down to C or C++ style on any module it can’t handle wrapped in a type-safe interface optionally with input validation. Then go right back to safe-by-default code for majority of the app with lower defects and panics instead of code injections. That’s still better defect vs effort ratio than C or C++.

                                  At that point, the borrow checker is no longer a negative. The FFI situation could still mess the author up, though. Also, two languages with lots of typing that might not mix well. Might be too much pain to justify except for critical applications.

                              4. 2

                                You’re just asking for a “Do you realize that your comment is very similar to those people saying that if a programming language is difficult then it is not worth adopting?” reply.

                                Rust was literally born as a reply to those experts you just named. And if a programming language doesn’t change the way you think, then it’s not worth wasting time on it.

                                I wouldn’t have posted that comment if the author said “I’m not yet comfortable with officially releasing Rust code while I’m still learning”, or something like “I had to switch back because currently I find it easier to maintain C++ code”.

                                No. His point was all about tricking the Rust compiler to get problems solved. Add an unsafe and the borrow checker stops complaining. Oh boy.

                                1. 1

                                  Rust was literally born as a reply to those experts you just named.

                                  Which is why I find your comment ironic. It’s a bit hypocritical in my opinion when someone starts using the same methods they argue against.

                                  I wouldn’t have posted that comment if the author said “I’m not yet comfortable with officially releasing Rust code while I’m still learning”, or something like “I had to switch back because currently I find it easier to maintain C++ code”.

                                  No. His point was all about tricking the Rust compiler to get problems solved. Add an unsafe and the borrow checker stops complaining. Oh boy.

                                  I don’t think this is a fair understanding of the author’s intent. Let me quote them:

                                  Given so many advantages, why I am switching back to C++? The most beautiful thing about Rust is also a disadvantage. When you implement an algorithm using C++, you can write it down without one second of pause, but you can’t do that in Rust. As the compiler will stop you from borrow checking or something unsafe again and again, you are being distracted constantly by focusing on the language itself instead of the problem you are solving. I know the friction is greater because I am still a Rust learner, not a veteran, but I think this experience stops a lot of new comers, speaking as someone who already conquered the uncomfortable syntax of Rust, coming from a C/C++ background.

                                  I think this is a fair criticism. You and others are saying the author has to change the way they think and approach problems differently, mainly from rust’s point of view, the author on the other hand just wants to use an already existing algorithm verbatim, and doesn’t wanna look for different algorithms that would fit the rust model more. How is this about tricking the borrow checker?

                                  Also the author further goes on to say:

                                  Another reason is the Rust ecosystem is still immature. As an indie game developer I can see the situation is changing, there is a website Are we game yet? that lists many neat things in the Rust world, there is a data driven game engine written in Rust called Amethyst, all these things look really promising. But, there is no Qt, no CGAL etc, all these frameworks and libraries have been developed for so many years and maintained very high level of quality. I know there are some bindings, but it’s not mature and not enough.

                                  which to me is completely different to the TLDR you provided.

                                  1. 1

                                    When you implement an algorithm using C++, you can write it down without one second of pause, but you can’t do that in Rust.

                                    You can’t if you want it statically guaranteed to be safe. You can using other mechanisms if you don’t care about that. So, author is incorrect.

                                    Now, I can’t tell you if doing it another way will cause any conflicts when integrating into existing ecosystem of Rust crates. I don’t know if they expect code calling their functions to borrow check in a way that will cause a different, compiler warning. Worth some experiments. If not, then the primary gripe about Rust goes away whenever you want it to.

                                    “But, there is no Qt, no CGAL etc, all these frameworks and libraries have been developed for so many years and maintained very high level of quality.”

                                    One of the best reasons not to use Rust in that niche. Hard to say how difficult it would be to wrap or port any of that.

                                2. 0

                                  no, no its not.

                                  in fact its the exact opposite of that - “unsafe” is not the default in Rust - OP would have to explicitly add the “unsafe” keyword to enable this behavior

                                  if he chooses to do that then the consequences are his fault - unlike in C++ when “unsafe” is essentially the default

                                  stop posting misinformation.

                                  1. 4

                                    I don’t know that you meant it this way, but your comment comes off as a rather rude out-or-hand dismissal, which is especially unfortunate because I think you misunderstood what nullp0tr meant.

                                    You’re correct about your description of how unsafe works, but the way I understood what they mean was more about generic shallow dismissals of problems that people new to the language (or just people from the fact of being human) have with a language.

                                    The “solution” to both problems here is “be more experienced” and “don’t do it wrong”, which really aren’t helpful.

                                    1. 2

                                      Exactly what I meant! thanks for being understanding:)

                                3. 9

                                  he didn’t grasp Rust core principles yet

                                  Or, unsafe is still needed quite often when doing low level/performance sensitive work.

                                  1. 3

                                    “Quite often” is debatable. If you need many unsafe‘s then either you’re cutting too many corners or you’re not using appropriate type definitions. Or you think you can outsmart the LLVM optimizer every time you fancy to.

                                  2. 5

                                    It honestly took me about 2 years of bursty usage before I started feeling like I could really fly. Things are in a far, far, far better place now for newcomers, but that feeling of being unable to express yourself is going to exist until you have the time and resources to really understand borrowing.

                                    I really like this post that drills into it: Rust: A unique perspective. For me, it really started making sense when I started thinking of immutable references as being similar to a reader lock, and a mutable reference as being similar to a writer lock, since I had done a bit of concurrent programming before coming to Rust. But everyone has different metaphors that they will need to find. People come to Rust from a ton of different places, it’s not just another exodus-from-X but it pulls people in from front-end, back-end, embedded, databases, distributed systems, etc… But resources targeted at people with different backgrounds are starting to pop up more and more to make the process faster for them.