1. 15
  1.  

  2. 26

    I didn’t find too much to take away from this. No comparison with C (not that it hasn’t been done a million times already). It’s just a feature list and potential applications for Rust.

    1. 7

      I assume one of the reasons is that we’re not the target audience. I read the blog post as more geared towards technical high/C-Level management.

    2. 18

      I certainly would like rust to become even more successful. But I feel like zig is going to take the lead in replacing C eventually, based on my limited knowledge. It’s far easier to integrate with existing C than rust is already. It has even easier ways of having multiple allocators (stack,pool etc) and allows for seamless async-await as far as I know. This makes it even better for usage in embedded environments and the harsh c world of Drivers, Kernels and so on.

      Rust is a little bit too heavy or constraining it seems for those bare metal workloads and zig can just place itself as drop in replacement. Sure rust gives you even more guarantees, while zig feels like a tidy C in that aspect. But this may be more desirable than to fit your stuff into rusts totally different world. Or writing loads of unsafe code, while 99% of your Linux Kernel may already be a bunch of unsafe hacks to allow the speed and integration it has.

      On the other side are the people that enjoy strong typing but don’t want to interact with the borrow checker, here Nim may be more of an option. Meanwhile Deno/Typescript, Ruby and Python are still staying strong in that field.

      And replacing numpy with a rust-ish library sounds nice. But we shouldn’t forget that there are still loads of Fortran libs underneath those heavily utilized python libs.

      This may sound pessimistic so I’d really like to get some different opinions on my thoughts.

      1. 5

        This may sound pessimistic so I’d really like to get some different opinions on my thoughts.

        Sure.

        Rust is a little bit too heavy or constraining it seems for those bare metal workloads…

        There are a few examples of Rust being used in “bare metal” environments. I wouldn’t say it’s constraining to the point that “bare metal” software can’t be written in it. Rust is billed as a “systems programming language”, after all.

        Sure rust gives you even more guarantees, while zig feels like a tidy C in that aspect. But this may be more desirable than to fit your stuff into rusts totally different world. Or writing loads of unsafe code, while 99% of your Linux Kernel may already be a bunch of unsafe hacks to allow the speed and integration it has.

        I didn’t fully understand this point. That valuing performance over safety guarantees is a trade-off worth making?

        On the other side are the people that enjoy strong typing but don’t want to interact with the borrow checker, here Nim may be more of an option. Meanwhile Deno/Typescript, Ruby and Python are still staying strong in that field.

        Garbage collection is certainly another viable approach to the problem of memory safety. Though, some may argue that GC pauses are inappropriate for an embedded system running some sort of real-time application.

        And replacing numpy with a rust-ish library sounds nice. But we shouldn’t forget that there are still loads of Fortran libs underneath those heavily utilized python libs.

        I believe Fortran is relatively safe. IIRC the speed of Fortran arises from aliasing not being allowed in the language.

        Zig is cool, but the size of its user base is much smaller than Rust’s, ergo I expect more effort to be poured into the Rust language.

        1. 2

          That valuing performance over safety guarantees is a trade-off worth making?

          Sometimes it is. Sometimes, if you don’t prioritize performance, the code is incorrect, and the fact the code is safer doesn’t make it correct. Just buying a faster processor isn’t always a solution, either.

        2. 7

          Yeah, Rust is more of the C++ replacement than C.

          1. 14

            Rust has attracted a lot of people (including me) who wanted a better C, and don’t think that C++ is a better C.

            I agree that zig is closer to being a direct C replacement. However, after using Rust I also got used to quality-of-life improvements it brings, so there’s no going back for me :)

            1. 4

              But D though… >_<

            2. 2

              I am unsure if Zig can take the lead in replacing Rust. Successfully replacing a language such as C, in my opinion, can only be a combination of (1) a strong value proposition, (2) ability to gain traction within a developer community, (3) gain traction in larger organisations. I believe the first aspect, both Rust and Zig has. What I believe Rust has, that makes it a prime candidate for replacing C in some ares, is that it has a very strong developer community that is develops integrations into wide variety of developer tools (e.g. IntelliJ Rust support), a strong ecosystem (crates.io, cargo) and advocates highly for it. In addition, it gains tractions within larger organisations and allows people to work paid on the Rust ecosystem. While Zig might be better suited, in my opinion, other factors play a significant role where Rust is really strong atm, in addition to have a strong value proposition.

            3. 15

              I doubt many people who still favor C will like Rust, much less switch to it (voluntarily.) C is barely-structured, with a minimum of typing or type-safety. You get struct, enum, pointers and arrays. It’s “structured assembly”, as they say. Anyone who prefers C today likes it that way.

              Going from that to Rust’s complex type system must be like trying to learn a distant foreign language like (to me) Russian or Chinese. (Actually I hear Georgian has the most WTF grammar of all, to an English speaker.)

              And after the feel-good C parser (“Hey dude, I’m not sure that void* really points to a Foo, but I’m not going to harsh your mellow, go for it”), the borrow checker would feel like some sadistic English headmaster. “Class! Tompkins, that blithering moron in your midst, has yet again attempted to reuse an already-moved value. Fetch my cricket bat and lower your trousers, boy.”

              1. 3

                Okay that had me laughing.

              2. 7

                Cons

                Lack of classes and succession, which makes writing object-oriented code harder

                This shouldn’t be in the “Cons” list. Not having inheritance is a blessing because it doesn’t let people indoctrinated into OOP introduce complexity at every step.

                1. 3

                  It’s a con for the already indoctrinated, though…

                2. 14

                  Rust seems like a cult at this point. It seems that in every post there is always someone commenting “you know, in Rust we do it like this”, or “how funny, this remind me that one time, at Rust camp, when…”

                  I’m glad some many people have found their passion, but it is funny nonetheless to see how “intense” Rust fans can be.

                  1. 11

                    Rust does an excellent job alienating a decent number of C++ programmers by constantly hijacking their posts.

                    I wish people would also stop wrapping C++ up in discussions about C. They’re not the same language and each have their own good and bad points. That table’s wrong: C++ is type safe, has C++ has implicit typing with auto and you can do “dynamic” type checking (either with templates or std::any).

                    1. 7

                      C++ is type safe

                      What meaning of “type safe” do you have in mind here? In C++ the type system is more of a suggestion than a strict enforcer. Let’s see what Wikipedia has to say about it:

                      First definition:

                      In computer science, type safety is the extent to which a programming language discourages or prevents type errors. A type error is erroneous or undesirable program behaviour caused by a discrepancy between differing data types for the program’s constants, variables, and methods (functions), e.g., treating an integer (int) as a floating-point number (float).

                      Second definition:

                      Vijay Saraswat provides the following definition: “A language is type-safe if the only operations that can be performed on data in the language are those sanctioned by the type of the data.”

                      Both are demonstrably not true for C++ with its const_cast, reinterpret_cast, normal casts between different pointer types, no array bounds checking and lack of memory safety which results in values being overwritten by other data and basically any violation of type system you can think of.

                      Now, Rust also isn’t type-safe. Safe Rust is type-safe. Unsafe Rust isn’t, but even unsafe Rust is more type-safe than C++.

                      1. 4

                        In C++ the type system is more of a suggestion than a strict enforcer

                        I can’t comprehend how that could be true, other than that it allows explicit casting, which many languages (that are generally considered type-safe) do. One typical difference is that C++ is not memory safe, and such a cast may have or result in undefined behaviour rather than a run-time error as a result. But memory safe and type safe are not the same thing.

                        Let’s see what Wikipedia has to say about it:

                        The first definition is bogus, and the second is met by C++, excluding casts; it won’t let you call a member function that doesn’t exist, it won’t let you add two things that have no suitable operator overload defined, etc. That’s what’s usually meant by type-safety: if the code compiles and contains no type casts, you can’t get a runtime type error. Casts do break this, of course, but if you use a cast you’re explicitly overriding the type system.

                        It may do a few implicit conversions if necessary, which is an example of weak typing, but not of lack of type safety.

                        (One problem, admittedly, is that there is no very good agreement on what “type safety” really means, as can be seen in the wikipedia article you refer to. But it irks me that people point at C++ and say it lacks type safety because of XYZ, and they are really talking about memory safety or implicit conversion).

                        no array bounds checking and lack of memory safety

                        That’s nothing to do with type safety.

                        1. 4

                          Without memory-safety there is no type-safety, as you can modify any object representation to anything you want. You don’t need casts in C++ to violate type-safety in this way, just use-after free, out-of-bounds array access, use-after-referenced-object-wend-out-of-scope.

                          I can’t comprehend how that could be true, other than that it allows explicit casting, which many languages (that are generally considered type-safe) do.

                          Which languages are you talking about and in what way does casting in them violate type-safety? Note that type-casting alone isn’t a problem in C++, only casting of pointers.

                          1. 2

                            in what way does casting in them violate type-safety

                            It doesn’t, that was the point I was making.

                            You have certain types of cast available in C++ for which using them breaks universal type safety (as you define it at least). But, they’re clear markers in the code, and they indicate a choice of the programmer to override the type system. Saying “the type system is more of a suggestion than a strict enforcer” is true for C++ only in the same way as it is for Rust, which has an “unsafe” keyword and allows casts; that is, it’s not really true at all. Type-checking in C++ is generally quite stringent.

                            even unsafe Rust is more type-safe than C++

                            How would you even measure it? If “without memory-safety there is no type-safety” – your own words – then both unsafe Rust and C++ have no type-safety, and unsafe Rust can’t be “more” type-safe than C++.

                            I think Rust is pushing language development in a good direction, but this kind of “Rust good, C++ bad!” clamour is not constructive.

                            1. 2

                              You have certain types of cast available in C++ for which using them breaks universal type safety (as you define it at least). But, they’re clear markers in the code, and they indicate a choice of the programmer to override the type system.

                              That’s only true for casts though. I’ve already pointed out many other aspects of the language which don’t require any casts, and yet violate type-safety. You can’t grep for out-of-bounds array access, use-after-free,use-after-referenced-variable-went-out-of-scope the way you can for unsafe.

                              How would you even measure it? If “without memory-safety there is no type-safety” – your own words – then both unsafe Rust and C++ have no type-safety, and unsafe Rust can’t be “more” type-safe than C++.

                              I need to do more in unsafe Rust to e.g. go against the borrow-checker. It’s not enough to just write unsafe, I also need to convert some references into pointers. In C++ there is no equivalent thing that would stop me from violating the ownership model.

                              I think Rust is pushing language development in a good direction, but this kind of “Rust good, C++ bad!” clamour is not constructive.

                              There are good and bad language design decisions. C++ had plenty of the latter. Is pointing out the bad decisions inconstructive? Maybe in the sense that it doesn’t advance the state of C++. But I think it’s constructive in the sense that people should be aware that it’s not the only way in the niche that C++ fills and there are options you can switch to. C++ continually disappoints me both in ergonomics and safety, and its committee never disappoints on the front of making it even worse that it already is. So yes, it’s not constructive for C++. I don’t have a problem with that. Pointing out those flaws also serves another constructive purpose: a warning not to repeat C++‘s faults in other languages. Let’s learn from the past.

                              1. 1

                                C++ had plenty of the latter. Is pointing out the bad decisions inconstructive?

                                No. But bold assertions like “In C++ the type system is more of a suggestion than a strict enforcer” are unconstructive. Assertions like “unsafe Rust is more type-safe than C++” are unconstructive if you don’t clarify what you mean by “more type-safe”.

                                How would you even measure it?

                                I need to do more in unsafe Rust to e.g. go against the borrow-checker

                                You’re missing my point. You vacillate between treating type-safety as a binary quantity (“C++ is not type-safe”) and as a spectrum (“unsafe Rust is more type-safe than C++”). Pick one!

                                1. 1

                                  Agreed. I was being ridiculous. Too much time spent on the internet.

                          2. 1

                            it allows explicit casting, which many languages (that are generally considered type-safe) do.

                            Please name one language that allows unsafe typecasts but is considered type-safe.

                            That’s what’s usually meant by type-safety: if the code compiles and contains no type casts, you can’t get a runtime type error.

                            Most people’s definition of type safety is not the same as yours; runtime type errors are an example of type safety as the language doesn’t allow values of a type to be used incorrectly. Compile-time vs runtime type-checking has nothing to do with type safety. You seem to be confusing static typing with type safety.

                            1. 1

                              Please name one language that allows unsafe typecasts but is considered type-safe.

                              I didn’t say “unsafe typecasts”.

                              If you want to make the argument that it’s the unsafe casts that make C++ not typesafe, I’m somewhat ok with that. But do casts in general make it not typesafe? No. Implicit conversions? No.

                              Most people’s definition of type safety is not the same as yours; runtime type errors are an example of type safety as the language doesn’t allow values of a type to be used incorrectly

                              Definitions are problematic here, as I already noted. By your definition, I don’t think you can have a memory-unsafe language which is type-safe at all (depending on what exactly you mean by “used incorrectly”, I suppose). The wikipedia article also essentially defines “type safe” and “memory safe” in a way that you can’t have one without also having the other. That seems pointless to me, but ok, maybe it’s the more accepted usage.

                          3. 1

                            C++ does implicit conversions of primitives, that doesn’t mean that it’s not type safe. You can see this with restrictions on narrowing casts on things like std::vector<int> v = {{ 1, 2, 3.0 }}; giving an error, and also with how function overrides with various primitives work. This is also visible at the function level because C doesn’t allow function overloading, whereas C++ does, because the types (integer, float, etc.) are part of the symbol put in the binary.

                            Rust even allows normal casts between pointer types using as. This is actually a difference between C and C++ in that C++ requires the cast.

                            reinterpret_cast in C++ is used for the same purposes as std::mem::transmute in Rust, for most of the same reasons, like reinterpreting binary data from a file or network as a struct.

                            I think I’ve only ever seen one actual use of const_cast in 5 years and about 20 million lines of code.

                            1. 4

                              C++ does implicit conversions of primitives, that doesn’t mean that it’s not type safe.

                              It doesn’t matter whether they are implicit.

                              Here is a perfectly valid C++14 program demonstrating problems with casts:

                              #include <iostream>
                              #include <string>
                              
                              int main() {
                                  const std::string hello = "hello";
                              
                                  float* fello = (float*)(void*)const_cast<std::string*>(&hello);
                              
                                  *fello /= 0.0;
                              
                                  std::cout << hello;
                              
                                  int x = 5;
                              
                                  double* y = (double*)&x;
                              
                                  std::cout << *y;
                              }
                              

                              Another one, no casts, no bounds-checking:

                              #include <iostream>
                              #include <string>
                              
                              int main() {
                                  const std::string hello = "hello";
                                  volatile int a[] = {1, 2, 3};
                              
                                  for (int i = 0; i <= 3; i++) {
                                      a[i] = 0xff;
                                  }
                              
                                  std::cout << hello;
                              }
                              

                              What do they have in common? They demonstrate that the language is not type-safe (they violate the semantics of the std::string type). Similar effects can be achieved with use-after-free, referring to variables whose references were captured in e.g. a lambda, but whose scope already ended.

                              Rust even allows normal casts between pointer types using as.

                              reinterpret_cast in C++ is used for the same purposes as std::mem::transmute in Rust, for most of the same reasons, like reinterpreting binary data from a file or network as a struct.

                              You can do neither in safe Rust. All C++‘s footguns on the other hand are at your disposal at all times. And you can’t just grep for them in an inherited codebase.

                              Wikipedia page provides a clear objective definition of a type-safe language. It isn’t a language that merely allows you to write programs that don’t violate type safety. It’s a language that prevents you and your collaborators from violating type safety, so you may sleep well, without the paranoia that maybe a string is not a string.

                              1. 2

                                Type-casts are explicitly there to subvert type-safety. Rust has equivalent constructs, and I can write equivalent programs in Rust, if you allow me the “unsafe” keyword.

                                Native arrays in C++ are of course flagrantly unsafe. So is pointer arithmetic. Both are heavily discouraged in modern C++

                                So I will disagree with you that Rust is type-safe; only the subset without “unsafe” is. I agree C++ is unsafe, but the unsafety can be avoided by avoiding certain language features, which can be enforced as part of a style guide. (Unlike C, where no style guide can save you.)

                                (I do think “unsafe” is a brilliant feature, and I wish other languages had it; I’m looking at you, Nim.)

                                1. 2

                                  Native arrays in C++ are of course flagrantly unsafe. So is pointer arithmetic. Both are heavily discouraged in modern C++

                                  They are discouraged in favour of std::vector with operator[] which has the same problem.

                                  So I will disagree with you that Rust is type-safe; only the subset without “unsafe” is.

                                  If you check my comment again, you will see that I explicitly said that Rust isn’t type-safe, only safe Rust (as in without unsafe code) is.

                                  1. 1

                                    Hm, I’d forgotten that vector isn’t range-checked by default. I use the libc++ feature that turns on range checking, plus the Clang address and UB sanitizers in test builds.

                                    1. 1

                                      At that point you can opt into bounds-checking in the compiler and then classic arrays are just fine. You’ll gain lighter syntax and faster compilation as well. Unless you want growable arrays, but that’s a different scenario.

                                      1. 1

                                        I’m not aware of a compiler flag for bounds-checking C arrays … ? It seems of limited use because, if you pass an array as a function parameter, it decays into a pointer with no length information.

                                        1. 2

                                          g++ -fcheck-pointer-bounds -mmpx

                                          Appears to work with arrays converted to pointers as well. But maybe there is a case where it will not work. I would have to check more details.

                                          UPDATE: Above works only on x86 linux though. But after a bit of searching I found this piece on Wikipedia, which says that you can enable bounds-checking in STL with _GLIBCXX_DEBUG=1 or _LIBCPP_DEBUG=1 preprocessor constants. That will be more portable. I’m glad I found out about it. Less stress in the future debugging C++ memory issues.

                              2. 1

                                Implicit conversions have nothing to do with type safety. JavaScript will implicitly convert a float to a string but is a type-safe language. You can work around C++‘s type system which means it isn’t type-safe. Rust’s std::mem::transmute is also not type-safe and can’t be used in safe Rust code.

                          4. 2

                            Maybe explore why this is the case?

                            1. 6

                              If I had to guess, it’s desperation to validate the time they’ve spent climbing the absurd learning curve. I see so many Rust programmers who only have personal projects to show, and bash away with Python/Go/Whatever at their jobs.

                              I’d never even consider Rust for anything serious. It’s way too difficult to learn, and there’s way too many low-quality user conversations that I’ve read. It’s hard to take it seriously.

                              I think Zig will eventually find a place in low-level systems programming, and thank God for that. It’s by no means perfect, imo, but it’s way easier to learn than Rust.

                              1. 12

                                Your comment reads like your issues with Rust are that (i) it’s not mainstream, and (ii) you’re not familiar with it.

                                I’ll just note that C++ is probably even harder to learn than Rust. Except most don’t even realise it, because on average, they’re much more familiar with C++ already.

                                1. 5

                                  I’ll just note that C++ is probably even harder to learn than Rust.

                                  I agree. I think there’s a misconception that Rust is harder to learn than it is, and that comes from the strong shift it forces you to make in your mental model when you’re at the early-intermediate stage of your learning. It’s an uncomfortable thing to have to do, because it makes you feel like a beginner for a bit, but ultimately I don’t think it makes Rust that much harder to learn. I think if you were learning Rust and you actually were a beginner to programming, that barrier wouldn’t really exist.

                                  C++ teaches you the same lessons that Rust’s borrow checker does, but it teaches you those things over the span of 40 years through hard-won experience. Rust compresses that into a few months.

                                  1. 5

                                    I’ve always been curious about this. Having written C++ and C in the past (though not a lot), I found Rust’s borrow checker to be, in most cases, fairly easy to learn. I understand the pain if you’re coming from a managed memory language, but if you’re already used to manual memory management, the borrow checker often just enforces best practices. Don’t return dangling pointers unless they have an explicitly tracked lifetime, make sure that any function consuming a struct uses a read-only pointer to the struct, etc, etc. The borrow checker certainly makes some things that a programmer knows is safe much harder to express, but that sounds more like a sharp edge than a learning curve. And if you’re coming from a managed language, manual memory management will always be a learning curve.

                                    1. 2

                                      Rust compresses that into a few months.

                                      That’s exactly what I mean by “hard to learn”; the learning is front-loaded. The payoff is great but the cost is very real.

                                    2. 1

                                      The low-quality internet chatter certainly doesn’t help, case in point TFA. Most of it just reads like marketing blog posts and exhortations on the glory of the fearless borrow checker.

                                    3. 6

                                      If I had to guess, it’s desperation to validate the time they’ve spent climbing the absurd learning curve.

                                      I can only speak from my own experience, but for me this is the other way around. My outward expression of enthusiasm is a result of already feeling the time I spent learning Rust has been validated by how much I enjoy working with the language.

                                      I see so many Rust programmers who only have personal projects to show, and bash away with Python/Go/Whatever at their jobs.

                                      I’m not sure if you intended it as such, but I don’t think this really works as a supporting argument that it’s too difficult to learn. Rust jobs are still really scarce, for a variety of debatable reasons - foremost among them, imo, that it’s trying to displace some very well-established/entrenched languages (C and C++). That and the fact that it’s still quite a young language in the grand scheme of things. I think that scarcity is probably the main reason you see this happening.

                                      I’d never even consider Rust for anything serious. It’s way too difficult to learn

                                      Again, I can only speak anecdotally, but I work full-time in Rust, and it’s in a very serious use-case. And I work with people who didn’t know Rust before they worked here, and they’re getting by more than fine.

                                      And yes, I realise the more I type the more I validate this:

                                      to see how “intense” Rust fans can be

                                2. 2

                                  Being the most popular language on Stack Overflow probably means a mix of being a language people want to learn and being a language that makes people wonder what on earth is going on.

                                  1. 2

                                    The list of “cons” doesn’t include some pretty important stuff like slow compile times, poor error handling (anything less powerful than a condition system is “poor”), and missing REPL and hotpatching - conversely, I don’t like “lack of classes and succession” and “compiler polices memory addresses too much” (what does this even mean?) in that list.

                                    Moreover, sections like “Blockchain in Rust” and the “Rust development timeline” that is made to look like a graph (but isn’t) make me feel like the article is overall a content-light fluff piece.

                                    1. 1

                                      What are the main advantages of a condition system? I looked the term up and wasn’t impressed, quite possibly because I didn’t find any use-cases where the idea truly excelled.

                                      1. 2

                                        The main benefit is being able to handle errors from a function lower in the stack without unwinding the stack, and then continue execution from where the error occurred. As a big fan of Common Lisp I do like the condition system but I’d still take a sum type error system like Rust or Haskell over it any day, because despite my best intentions I do forget to handle errors I should be handling without it.

                                        1. 1

                                          In addition to travv0’s point - one of the advantages is the ability to separate the decision of which error-recovery strategy to choose from what that strategy is. Exception systems force you to either handle the error at a high level, which results in duplicating the lower-level code all the way down the callstack to where the error occurred (because that’s the only code that had access to the details of the error), or at a low level, and hard-coding a recovery strategy that is completely blind to the high-level context of why the erroring operation was initiated in the first place. In other words, it separates policy from mechanism.

                                          1. 2

                                            Of course, I knew there was another key piece I was missing. Thanks for expanding on my answer. For those that want more info, Peter Seibel’s excellent book Practical Common Lisp has a chapter on them and has a pretty high-level explanation even if you’re not familiar with Common Lisp: http://www.gigamonkeys.com/book/beyond-exception-handling-conditions-and-restarts.html

                                      2. 1

                                        Is this the technical content that I hard lobste.rs likes to pride itself upon?

                                        1. 1

                                          No. (I consider it a weak submission but not something to be flagged.)