1. 67
  1.  

  2. 20

    Linus Torvalds is convinced Rust will take over the Linux Kernel.

    Not exactly. From the source article:

    However, he said that for things “not very central to the kernel itself”, like drivers, the kernel team is looking at “having interfaces to do those, for example, in Rust… I’m convinced it’s going to happen. It might not be Rust. But it is going to happen that we will have different models for writing these kinds of things, and C won’t be the only one.”

    1. 3

      Yeah, that’s weird. Was the whole article a big joke?

      1. 1

        I thought there were a few strange claims and editorial choices in it, but overall it seems like a good summary.

    2. 19

      Great article! Just want to call out one thing. Rewrite decisions are mostly social not technical. It is a great exercise to pass down business logic knowledge from one developer to another, and keep the new developers engaged in bug-fixes and active ownership in general.

      1. 6

        …and the reason why thay fail so often is that the new developers fail to follow the business logic through the implementation details of the old system, or fail to understand the reasons behind it, and the authors of the original system often aren’t around to answer their questions.

        1. 3

          I wonder what people mean by failure in this context. Is it that the new implementation isn’t immediately exactly like the old one or that in the end the new implementation gets canned and all the work that went to it with it?

          I’ve been a part of a few rewrite gigs and they all sucked at MVP stage compared to the old one, and most of them were better eventually than the old one, some even massively better.

          1. 3

            in the end the new implementation gets canned and all the work that went to it with it

            I meant these, usually in a context when the thing to be rewritten is old and big.

      2. 8

        It has macros, an intelligent evolution of C macros mixed with C++ template metaprogramming.

        As a lisp enthusiast this pains me. C-style macros/C++ metaprogamming is a devolution of Lisp-style macros, and framing Rust as evolving this instead of ignoring them altogether them in favour of Lisp-style macros is just weird to me.

        1. 2

          I feel this is true for a lot of things. In a sense, modern production languages have just been reimplementing stuff from Lisp for decades now and calling it evolution. Especially the production languages I mention (stuff like Go, Python, C++, Rust, etc.) aren’t really innovating anymore, just taking stuff from functional languages like Haskell, Ocaml and Lisp and making it work with their imperative style.

          1. 8

            It’s true that Rust “just took stuff” from other languages. That was one of the primary principles of the project: nothing new, only proven ideas.

            Rust macros were designed by Dave Herman, who had experience from Racket, Scheme, Moz Research project for macros in JS, and wrote a dissertation on hygienic macros. The design certainly doesn’t come from ignorance about Lisp or macros.

            Rust has deliberately chosen to have a syntax richer than s-expressions. With this requirement, Lisp macros are not directly applicable any more. FWIW Rust also has procedural macros, which are written in Rust and manipulate Rust’s own AST.

            1. 6

              Also, programming languages are often interesting in the intersection of their individual choices. Yes, language A may pull feature X from language B, and feature Y from language C, but does any other language have X and Y together? Also, when you zoom in, how similar are X in A and X in B? Often, the specifics of their differences, needing to coexist and intermingle with other language features, means that even when one language takes from another, there’s a transformation at the same time.

              So saying something like “Rust macros are just copying Lisp” is maybe correct at a high vantage point, but languages are holistic objects, and the specifics of what a language permits and how a language feels are important. Any cross-language comparison is more “seems like” than “is.”

              1. 1

                The design certainly doesn’t come from ignorance about Lisp or macros.

                I believe it’s ignorance on the blog post authors end frankly. I did read the Dave Herman post, but I had this impression of Rust macros before that as well.

                1. 1

                  It’s true that Rust “just took stuff” from other languages. That was one of the primary principles of the project: nothing new, only proven ideas.

                  Yes, this is why I disagree with the people who claim Rust is innovative.

                  The design certainly doesn’t come from ignorance about Lisp or macros.

                  I didn’t disagree with this. I’m saying that it’s already been in Lisp for years and production languages are finally catching up in some regards.

                  Of course, because of the syntax of Rust and the lack of s-expressions in the language, they will never be as powerful as proper Lisp macros. However, since it’s a production language I don’t think this is the goal either. It’s much more important for languages such as these that the production of one developer will be very similar to the production of another one, so that businesses will have an easier time managing their workforce.

            2. 8

              The whole “modern languages” section is a serious oversimplification. History is a cumulative process. Rust is a neat language and will displace C, C++, ObjC, Go, Swift, and even Python etc. to an extent.

              Rewrites may succeed with small stuff like coreutils and ls, and likely will succeed in corporate settings because wages are great at getting people to do chores, but other, bigger, more established projects will unlikely fail. E.g. Remacs, seems to have stalled.

              Fortran is alive and kicking. So is Pascal, C, C++, Java, PHP. It has nothing to do with decades, good tools find their niche and settle there. Same will happen with Rust. Sometimes some stuff fade out. C won’t. C++ won’t. There’s just too much of these in too many boring places, and none of the modern languages present a full replacement. Nothing bad about that.

              P.S.: it might be my astigmatic eyes but type with big stroke thickness contrasts doesn’t really work on a (back)lit screen IMHO.

              1. 3

                The whole “modern languages” section is a serious oversimplification.

                Looking at your username, I’m willing to bet up to two pints of beer that I know why you hold that opinion.

                (And FWIW I agree with you).

              2. 13

                I am going through and rewriting go programs in rust as they have a much more expressive type system along with scheme style macros…

                edit: EVERYTHING AFTER THIS IS OFFTOPIC: but whooo boy am I considering just going back to C++. The compile times are astronomical, which make me not want to compile or run my test programs.

                Also, I haven’t figured out why I struggle with the sheer volume of vanity types (aka type Bar = GenericArray). My current struggle is with the AES crypto libraries using GenericArray with a Nonce type, but somehow I can’t figure out how to write a function that returns a correctly typed Nonce! And the compiler keeps suggesting types that are longer than 200 chars at this point. I just figured out strings, and now arrays, vectors, and slices of things are some new confusion.

                Finally, rust documentation organization is completely baffling for me to navigate right now. It’s very hard to figure out “given type A, what are all the methods it has?”

                Note: I complain because I’m excited and want to use rust, and the few programs I have written to parse my org files have ended up with easy to reason code and only slightly slower than my old C code, and 3x faster than my Go code.

                1. 11

                  You should look at Zig. It’s beautiful, though not yet ready for prime time.

                  1. 10

                    Finally, rust documentation organization is completely baffling for me to navigate right now. It’s very hard to figure out “given type A, what are all the methods it has?”

                    I find the official book equally annoying. I think it’s been revised but back when I started learning Rust a few years ago it was incredibly frustrating.

                    Virtually every section consists of 1-5 “we could do it like this, but this thankfully won’t compile because it might have this bug” examples, followed by the correct program listing. Just tell me how to do it already. Every compiler rejects an infinite amount of programs (okay, maybe except for Perl), I don’t need to look at every one of them.

                    If you want to illustrate how the compiler usefully rejects potentially buggy programs – a great idea! – list the rules and explain them after you’ve explained the correct approach, so that at least I have a working reference to compare the rules to. And then by all means list a bunch of examples, after you’ve explained the logic that the runtime or the compiler employs. Don’t make me try to figure out what’s wrong with a program written in a language that I don’t know yet, and don’t bury the useful, two-sentence description of the compiler’s logic in three pages of broken sample code and snark about C++.

                    1. 6

                      Try Ada 2012. It compiles to native binaries quickly and feels like a Pascal version of a safer and simpler C++, there’s a lot of underlying conceptual familiarity so you’ll feel at home. The type system is also ludicrously powerful. I’m rewriting some tooling in it and it’s pretty easy since there’s a lot of functionality between the standard library and GNATcoll.

                      1. 4

                        I’ve been thinking a bit about trying to make a language that takes the best bits of Ada SPARK (nice integration with Why3 for great SMT reasoning, ability to “turn-off” language features, nice bare-metal ergonomics etc…), building off of the work around stacked borrows applied to Rust, and generally trying to lean more into linear + temporal + separation logic. Ada and Rust have shown that some amazing things are possible. This effort might “collapse” into tooling around Rust that tries to prove contracts specified in comments + additional clippy lints that disable more features as well as those in dependencies.

                        1. 2

                          linear + temporal + separation logic

                          I’ve dived heavily into the Ada 2012 side, but not too much into SPARK, and there’s a lot of things people aren’t familiar with in regular Ada. You can force stateless behavior of a package using with Pure to be able to safely write your code with a compiler-enforce “functional core, imperative shell”, and mutable behavior is contained by parameters being readonly unless marked as out. On the temporal side, tasks contain active concurrent behavior and coordinating behavior and use protected types for passive concurrent behavior (mutual exclusion). For separation, Ada uses storage pools tied to individual access types and you can create multiple access types for the same type with each having its own pool. I haven’t played much with this yet, but access types are typed and you can’t cross access types from different pools, so I’m curious how far people could push this.

                          1. 2

                            You might like to take a look at F*. It looks quite like F# (i.e. ML), but integrates with Z3 and allows you to express programs and proofs in the same language. The output is C code and so it can be deployed on any system with a C compiler.

                          2. 2

                            Someone mentioned Ada 2012 here the other day and on their recommendation I bought the Ada 2012 book and started playing around with it.

                            I like what I’ve seen of the language (I remember working with Ada 83 in college for some reason, a PLT class or something, but I didn’t see enough of it to say I “know” it or anything).

                            The problem, of course, is the rather slim ecosystem and, more troubling to me, the tooling seems a little wonky. Maybe I’m not doing it right but getting things working on my Mac wasn’t nearly as easy as Rust or Go or Zig. I am 100% sure I have no idea what I’m doing so correct me if I’m wrong.

                            1. 4

                              I havent tried Mac, but Linux and Windows have worked well for me. Grab GNAT Community edition, most of what you need is built in if you look under project “dependencies”, but theres a project called Alire, which aims to be a package manager. Theres a silly amount of stuff in those bundled libraries already: json parsing, sockets, regular expressions, containers and such, which has made me pick it for projects I would have done in C++. I had to rebind a bunch of keybindings in the IDE to be sane for me, and you have to treat tab as “I trust my ide to indent” and use Pretty Print (i rebound it, if I get time I’ll see if i can contribute “format on save” or something back to the ide) to just fix things up for you.

                              It was slow getting started, but my velocity is steadily going up rather than falling off. If this wasn’t true, I wouldnt be recommending it.

                          3. 7

                            am I considering just going back to C++. The compile times are astronomical, which make me not want to compile or run my test programs.

                            That’s strange, Rust shouldn’t compile significantly slower than C++ most of the time (*). Have you tried figuring out why it’s so slow in your case? cargo build -Ztimings and cargo-llvm-lines are helpful tools here.

                            Less specifically, but I personally found that writing simple, “C with classes” Rust makes the language much more enjoyable. A rule of thumb is avoiding dependencies that require using traits or macros. Especially avoiding something that visibly stretches the language to its limits (HLists and GenericArray are big red flags). And yeah, in this case the advice clashes with “don’t roll your own crypto”, which obviously is more important.

                            (*) the case where Rust does compile slowly than C++ is when you build an enormous project on a machine with a huge number of cores — typical Rust build is not as parallel as typical C++ build.

                            1. 4

                              I’d be super interested in a comprehensive tutorial/guide on “How to quickly write slow but barely passable Rust”, aimed at complete newbies who didn’t read/internalize The Rust Book. I.e. something that would give me a minimal subset of Rust that I could use to write any Turing-complete stuff, yet not in a most efficient or pretty way possible. E.g. maybe using RefCells (or what’s the name) everywhere, to mimic GC-like attitude. I heard this advice “just use RefCells for everything if you’re a beginner and don’t care about performance”, the problem is I tried but I don’t really have a slightest idea how to do that :( Currently, I’d have to first learn whole Rust (which I repeatedly failed to do), to then understand what and how I can drop for less efficient coding. I’d love a guide teaching me “pidgin Rust”, enough of it that I could be dangerous and scorned with disgust by Rust gurus. Yet able to get the job done, in Rust (and then slowly start advancing into more fancy stuff).

                              1. 3

                                This is something I am unsure about. I too often here advice about Rc RefCelling your way out of borrowchecker fights. I think this is a bad advice, but this is just my own reasoning, rather than empirical observation on many different people learning Rust. To me, interior mutability is one of the hardest aspects of the language, and, while it sometimes can be used to mimic some GC language patterns, it brings a lot of accidental complexity. It’s much harder than doing the Rust thing with owned values and references.

                                To me, this advice seems a bit like “you can embed imperative language in Haskell via state monad, so, to learn haskell, just use state monad”.

                                My own take on learning Rust is that one really needs to sit down and learn the inner logic of the language. Not sure what’s the best way to do this though, I’d say:

                                1. 1

                                  I must check out the Programming Rust book (I assume you mean O’Reilly) - the ToC looks solid; thanks for the recommendation!

                                2. 3

                                  You can use Rust while mostly ignoring generics, macros, overloading, and fancy zero-copy code, but I don’t think you’ll get far without internalizing ownership.

                                  Rc<RefCell> is not a reasonable GC replacement. It’s fine if you want a graph structure, but spamming it everywhere is not going to make Rust a Python. You’ll be just as likely get stuck fighting with temporaries returned by borrow().

                                  I think that properly knowing the difference between String and &str (and alike) is a fundamental requirement in Rust, and it’s better to learn it properly than invent workarounds.

                                  If you need a compiled language to get something done quickly, then golang is fine.

                              2. 1

                                I think the issues you mention about rust are things that with experience you’ll struggle a lot less with over time. Compile times are a cultural issue in the ecosystem, but you can write code that compiles without spending minutes and minutes waiting on deps. “Experts write baby code” and when you learn which features of rust you don’t need at all, the whole language feels a lot nicer - until you have to read or use other people’s rust lol…

                              3. 7

                                the argument that Rust prevents the “goto fail” ( https://en.wikipedia.org/wiki/Unreachable_code#goto_fail_bug ) is .. weak.

                                the thing that prevents it is an unreachable-code-warning, and that is available for the C language too (even the linked wikipedia article mentions this)

                                1. 5

                                  IMHO it’s a very solid argument. Rust prevents it on many levels, much deeper than a lint:

                                  • Rust’s if always requires {}. The 2-line form of if that caused goto fail doesn’t exist in Rust.
                                  • Rust doesn’t pass values through =, so the if (err = call()) form doesn’t exist in Rust either.
                                  • Rust doesn’t have goto. Rust’s automatic Drop makes the goto cleanup pattern unnecessary.
                                  • Rust uses Result/? for error handling. It’s rare to need an err mutable variable.

                                  The code quoted on that Wiki page in Rust is:

                                  hashCtx.update(&serverRandom)?;
                                  hashCtx.update(&signedParams)?;
                                  let hashOut = hashCtx.finalize()?;
                                  
                                  1. 2

                                    Available how? Separate linter?