1. 23
  1.  

  2. 22

    A proper mature language (with 1.0 in its version) should have a formal specification that should be useful both for people developing compilers and the programmers trying to understand certain intricacies of the language and why it does not work as expected (more on that later).

    “Should”? Says who?

    I understand the opinion that Rust would be better off with a formal specification, but part of the reason Rust is so useful today, mature or not, is precisely because the Rust community intentionally opted out of the bureaucracy required to do this. Reasonable people can disagree on this point, and no evidence fo why Rust should have a formal spec is presented, only evidence that it doesn’t.

    Furthermore, I think this post is primarily engaging with an argument nobody is making. “Rust is not a mature language” is an uncontroversial statement, I think, to most Rustaceans. That’s part of why it’s so exciting; it’s still in the phase of development where almost anything is possible (though, I would say, far less so than even two years ago.) The community has done a remarkable job of building ergonomic, powerful features without anything that really doesn’t belong, and even the most controversial features (like .await syntax) have proven themselves so far.

    1. 11

      I think the argument for having a formal spec is a strong one in the context of (operating) systems programming where the support of the language and forward compatibility are extremely important. One of the hardest (and most annoying) things in software engineering is maintaining an existing large codebase on top of a moving target. For things that are close to hardware where timings are very important and esoteric, even minor changes can offset precise timings and lead to hours of debugging and work, or worse, silent failures. To that end, the bureaucracy of formalizing a spec is a very important one because it forces there to be a discussion with different stakeholders on what their needs are, and prevents hasty changes that anger a lot of people.

      1. 5

        I work on an operating system chiefly written in C, and I agree with your assertion that small changes in the program text the compiler produces can yield defects that are difficult to diagnose, often subtle and undetected until much later after they’ve done damage.

        C has a specification, but it hasn’t really stopped new compiler versions or different compilers (GCC vs Clang, say) from introducing new and irritating differences. New optimisations that suddenly omit a loop that leant, unwittingly, on some undefined behaviour rather than, say, report a diagnostic. Differing relationships between the source input and the set of actual function symbols and sections that come out; e.g., a proliferation of clones with differing ABI observance, or what gets inlined or not.

        A specification is a good thing some of the time, but I don’t believe at least in the case of C that it has had any impact on the consistency of text generation or system performance.

        1. 1

          C has a specification, but it hasn’t really stopped new compiler versions or different compilers (GCC vs Clang, say) from introducing new and irritating differences. New optimisations that suddenly omit a loop that leant, unwittingly, on some undefined behaviour rather than, say, report a diagnostic.

          On the other hand, there is at least a “baseline” of expectations, which often makes it a lot easier to reason about the output code when it’s baffling. When I look at the source code, then at objdump’s output, and the two don’t quite seem to go together, I can always turn to the spec to see who’s right.

          This doesn’t have a direct functional impact – as you know, unless there’s a real, big actual bug (e.g. 10+ years ago, the code that gcc-msp430 emitted to access volatile variables was a bunch of NOPs – oops!), these things take a little back-and-forth before they get fixed.

          But it’s still helpful to be able to reliably label a compiler workaround as such. Better yet, it’s immensely helpful if you can compile your code with version N (and it borks), then with version N-1 (and it works!), and then you know which one’s the buggy one. Otherwise, there’s no way to know if version N has a regression, or version N-1 had a bug that just happened to emit the code you wanted if you tickled it just right.

          I wouldn’t say it has a significant impact on the consistency of text generation or system performance, either, but it helps steer large, 20 year-old codebases a bit.

        2. 4

          I think this is a pretty good argument, but it wasn’t presented in the linked article.

          1. 3

            I think the argument for having a formal spec is a strong one in the context of (operating) systems programming where the support of the language and forward compatibility are extremely important.

            It is. But the blog post does not make this argument. It makes the argument that “a proper mature language” (whatever the proper or the mature mean here) should have a formal spec by the moment it reaches 1.0. Even if this post is just a rant, this is just projection. Most languages have reached 1.0 without a full spec, and are used in the industry just fine.

            The argument you use is much narrower and leans much more towards “language X is not usable in context Y because of the missing formal spec”, which is concrete and has much more validity.

            The bureaucracy is, as you mention, not necessarily bad, but the Rust projects method for blocking of changes in anger is an elaborate RFC process and a language design team + a pretty big test suite. I am currently involved in an attempt to bring a formal spec to Rust and the general feedback from industry players is that they see the Rust project owning a lot of informal written down spec currently, which gives them a very positive view on the chance to create one.

          2. 5

            I would love a spec and competing implememtations for rust. That said, a huge number of languages past 1.0 have no formal spec, such as ruby.

            1. 1

              Ruby got standardized as ISO 30170.

              1. 3

                It’s pretty hard to find implementations of that standard, though or, alternatively, libraries that would run on standardised Ruby. Word on the street was that this was due to some requirements in sectors in Japan that wanted to use Ruby, but “ISO spec” was on the checklist.

                Which says more about specifications than about Ruby.

          3. 14

            I’d suggest “Why Rust is not yet a mature systems programming language” or even “Why Rust cannot fully replace C yet” as alternative titles. The current title is just way too dismissive of what Rust has currently achieved and also implies any kind of work done with Rust right now, systems or not, can not be stable.

            About formal specs. Python’s ecosystem, despite a language spec, is often bound to CPython-the-implementation (go into any performance critical library and see how much it assumes about ctypes and GIL+GC behavior, i’d say there’s a 70% chance you’ll find a couple of implicit assumptions). It certainly did not prevent Python from becoming a mature language either. Ruby does not have a language spec and has more alternative prod-ready runtimes than Python. JS has an extensive spec and, while having quite a few implementations, constantly finds itself in runtime/compiler oligopolies too (like most other languages outside of C btw…)

            1. 9

              That’s really too strong a statement. Maybe rust is not a mature replacement to C for low-level tasks yet (a lot of allocation related APIs are not stable, asm syntax, no spec are valid points there); but there definitely is a large subset of rust that is pretty stable, mature, and usable to write programs. “Application-level” rust, perhaps.

              1. 7

                As someone who works in Rust and JavaScript, these criticisms don’t hold much weight.

                The value I get from Rust boils down to a well designed language with the ability to write both low and high level abstractions, a modern toolchain and an ecosystem that contains libraries borrowed from best-in-class approaches in other languages.

                I’ve personally found the borrow checker to be a great (if demanding) tutor, but I could take it or leave it as a language feature.

                1. 15

                  The article is just a low quality criticism. IMO it’s not worth reading or responding to. This is why I wish we had the ability to downvote articles on lobste.rs like on Hacker News. The point of the downvote is to let the community signal when content doesn’t belong on this website and we’ve been stripped of that. Management could keep fiddling with the flag options, maybe add a “Low Quality” one, but ultimately you’re just trying to dance around what should be a downvote option.

                  1. 14

                    IMO it’s not worth reading or responding to.

                    Why do you think so? I use Rust as my daily language and I think the first two criticisms are valid: 1. no formal specification; and 2. no nice bootstrapping process. For each of the criticisms some examples are given.

                    These are not new criticism and the article is somewhat ranty. But it certainly reflects issues with Rust that may prevent some people from adopting it.

                    This is why I wish we had the ability to downvote articles on lobste.rs like on Hacker News.

                    Maybe I have insufficient karma (15435), but I certainly do not have the option to downvote articles on Hacker News, only upvote or flag?

                    1. 2

                      Why do you think so? I use Rust as my daily language and I think the first two criticisms are valid: 1. no formal specification; and 2. no nice bootstrapping process. For each of the criticisms some examples are given.

                      There’s a step up from “2 points of valid criticism”, as large as they may be, and “not mature”. The first two are factually true, the second needs a lot of weighting and an establishment of “maturity” that is not just personal opinion.

                      1. 1

                        I think people are getting a little bit too hung up on the title and semantics of “mature”; the real problem described by the author is:

                        And now to the specific problems I encounter quite often and I don’t know whether I understand it wrong or the compiler understands it wrong. And since there’s no formal specification I can’t tell which one it is (even if the former is most probable).

                        People mentioned Ruby in the comments too, and I definitely had problems like this with Ruby too. I remember one specific instance where I encountered some really odd behaviour (I forgot what the exact problem was) and eventually found something on the Ruby issue tracker from years ago, with no clear conclusion (as far as I could tell; much of the issue was in Japanese), so I still didn’t really understand what was going on.

                        We can argue endlessly about the semantics of “mature” and I still like Ruby, but I do think stuff like this takes away from the language experience, and that all other things being equal Ruby would be better if behaviour like this was clearly defined.

                        It seems to me that especially since Rust is being considered for things like the Linux kernel these kind of minutia and the long-term stability associated with it becomes more important.

                        1. 3

                          That’s the issue with the chosen genre: rants want to make a point strongly, so people focus on the strongest points. What you cite is a supplement. Had the author chosen to elaborately write about the problems of a missing spec, I would probably agree on a lot of points.

                          1. 1

                            It’s not my favourite style either, but as long as it doesn’t contain completely egregious nonsense it’s probably best to read over it and focus on the core points. That’s easier said than done, and probably easier for me than you as I’m not involved with Rust.

                    2. 16

                      If you don’t like the article, flag it and explain the problems its claims have or why they’re incorrect.

                      I found it to be an–at least as somebody not big on the Rust koolaid–reasonably stated list of problems/grievances, several of which they even noted have been superceded or were incorrect.

                      The circling of the wagons here is what I refer to when I mock the Rust Evangelion Strike Force, and what turns some of us off.

                      1. 1

                        There’s really no relevant flag for my beliefs here, I’d feel bad flagging it as off topic as that seems meant for things truly out of the scope of the community. That’s why I wish we’d just have a downvote to cover all the different cases for removing a story instead of trying to enumerate them all.

                        1. 10

                          That’s a terrible idea. The whole point of having named flags is to signal why the submission doesn’t belong here.

                          If there was a flag that meant “any other reason” it would just be a free-for-all. The submission could be flagged for being mean to your favorite language; for being written by a woman; for containing furry imagery; or for challenging the consensus of the tech community du jour.

                          Here’s what you’re expected to do when you find a submission that you find objectionable:

                          1. hide, and move on
                          2. sit down and write a comment explaining why it’s objectionable.

                          And no,

                          The article is just a low quality criticism. IMO it’s not worth reading or responding to.

                          doesn’t count.

                      2. 4

                        I think many of the criticisms are perfectly fair, even if they’re worded in Kostya’s typical.. spicy style 🌶 Especially the bit about Rust now officially being past version 1.0. One would expect quite a few things other more mature languages have at this point, like a proper spec. The poor assembly support is a significant obstacle for multimedia code, since performance is paramount.

                        1. 4

                          The poor assembly support is a significant obstacle for multimedia code, since performance is paramount.

                          The Rust standard library does have have intrinstics for some platforms though. So it is already possible to write kernels using SIMD intrinsics. I have done so for some linear algebra kernels, which gives nice speedups.

                          1. 1

                            Sounds promising. But even with intrinsics, if it’s too hard to incorporate actual assembly, or if the ABI isn’t stable enough, then it’s simply of no use for its stated goals (system programming)

                            1. 6

                              I must point out that inline assembly is not part of C language standard or C++ language standard. Inline assembly, even in C or C++, is a compiler extension that is implemented incompatibly between compilers.

                              1. 2

                                How is Rust’s support for Assembly holding you back in a way that it wouldn’t in C?

                                1. 2

                                  As an example, check out these comments on a PR I made a while back. I wanted to add RV64 support for this project, which already supports RV32. RV64 is almost the same as RV32, but loading and storing registers uses a different instruction (for historical reasons). Rust has no way to parametrize assembly at the moment, so every inline assembly block has to be completely duplicated, even though they are effectively the same code. In C or C++, creating a macro for stores and loads would solve this easily.

                                  1. 1

                                    TIL. Thanks. I wonder if this is what the OP had in mind?

                                    1. 1

                                      Maybe. To clarify,

                                      Rust has no way to parametrize assembly at the moment

                                      is better stated as “Rust has no way to parametrize over instructions in assembly at the moment.” Rust now has better syntax for inline assembly in nightly. However, in standard rust the “!llvm_asm” macro is all you get. OP is probably complaining about the poor ergonomics of that macro. It’s just like what you get in C, but it’s less featureful because it lacks C’s preprocessor.

                                      1. 1

                                        It’s just like what you get in C

                                        Yes, this is what I was getting at. This was one of the OP’s criteria for being a “mature systems language.” But since the post is low quality, there’s really no way to know what they mean. If your difference is the only difference, then I guess we are supposed to believe that, when it comes to inline Assembly support, the only thing that separates a mature systems language from an immature one is the ability to easily parameterize over instructions.

                                        Seems a little cuckoo to me. But that’s why I asked.

                                        1. 1

                                          This just occurred to me, but for another example (also from tock), check out tock’s code for reading RISC-V CSRs. For background, CSRs on RISC-V are a set of registers for controlling the processor. They have their own address space, and their own instructions for accessing that address space. Importantly, the CSR to access is encoded as an immediate within the instruction, and not as a register. So to access csrs, they have to have a monster switch statement to select the appropriate instruction. To contrast, in C one can read a CSR in a macro like

                                          #define csr_read(csr)						\
                                          ({								\
                                          	register unsigned long __v;				\
                                          	__asm__ __volatile__ ("csrr %0, " __ASM_STR(csr)	\
                                          			      : "=r" (__v) :			\
                                          			      : "memory");			\
                                          	__v;							\
                                          })
                                          

                                          Now, hopefully the rust code gets inlined and the un-taken branches get culled (in fact the tock code even adds an annotation to that effect), but it’s still much less ergonomic than in C. If a new CSR gets added, both the set and get functions must be modified to have new branches. In C you just add a define.

                                          There are couple more instructions like the above in RISC-V (not sure about x86 or ARM; I haven’t written any Rust which needs inline assembly for those arches). In addition, I don’t know if the llvm_asm! macro worked with const expressions for immediates. I’d have to check, but if you couldn’t do something like

                                                  llvm_asm!("add $0, $1, $2"
                                                       : "=r"(foo)
                                                       : "r"(bar), "i"(some_const_func())
                                                       );
                                          

                                          then that would be pretty crippling IMO. In any case, it’s something which is fixed with the new asm! macro.

                                          1. 1

                                            Ah interesting. Yeah my hope is that the new const stuff being added would also help here. And yeah, the giant switch statements can be found in the implementations of the Intel SIMD vendor intrinsics too. For basically the same reason: vendor intrinsics are “basically” high level Assembly whete each intrinsic corresponds to a particular CPU instruction and some of those require immediate arguments. I think once Rust grows a way to specify a function parameter as const, then this would be fixed in general (not just for inline Assembly).

                                            If you are doing this, then yes, I agree it is unergonomic but I would say that it is reliable as long as it is marked as inline(always).

                                  2. 1

                                    I did a bit of a brainfart there. One should be able to use FFI to link assembly code into a Rust project. I suppose it’s only really inline asm which may be an issue. But that’s possible to live with.

                            2. 3

                              The article is just a low quality criticism. IMO it’s not worth reading or responding to. This is why I wish we had the ability to downvote articles on lobste.rs

                              I disagree, mostly because “low quality” is very subjective. People tend to use that attribute a lot due to not or misunderstanding something, especially when it is about criticism. I say that as someone who feels very guilty for doing the same.

                              For a rant tagged post I think it is valid and while I also disagree that the wording is… well, very ranty I have seen the other side of this on Hacker News. Things ending up downvoted, not for content, but for opinion, often enough because of an opinion that is unreflectingly copied from someone else. And while a lot of the time I share that opinion I strongly dislike that bubble and sometimes to say it bluntly circle jerking that comes from that. Personally I do not visit HN or lobste.rs to have my opinion validated somehow, but to get something that is novel.

                              While I disagree with the article and dislike parts of it in general this is the thing I’d expect here. Also the discussion it lead to in the comment section regarding standards and what a “mature programming language” is supposed to have was interesting.

                              I think there have certainly lower quality articles submitted. Usually I end up hiding those. It would be great if they did not exist, but I don’t think and opinion poll is a good way to decide that, because in the end it will lead to (potentially valid) criticism of liked software, concept, etc. to be downvoted.

                              1. 2

                                It would seem others don’t think the same as you do with regards to the quality of this article. Maybe this is evidence of why downvotes shouldn’t be used, it would hide otherwise acceptable content due to the dislike of a minority of people who don’t really represent the views of the majority.

                                1. 2

                                  Nitpick, there’s no downvotes here on either submissions or comments, but there are flags, for which a reason has to be given when used.

                                2. 1

                                  AFAIK on HN you can downvote only comments, not submissions.

                                  1. 1

                                    You need to hit a karma threshold first but you absolutely can down vote articles.

                                    Edit: I used to be at that threshold but I’m no longer or they removed the feature - my apologies!

                                    1. 4

                                      Not according to the FAQ:

                                      There are no down arrows on stories. They appear on comments after users reach a certain karma threshold, but never on direct replies.

                                3. 6

                                  Update: I’m told that newer versions of the compiler handle it just fine but the question still stands (was it just a compiler problem or the call definition has been changed?).

                                  Neither. The definition of a borrow got more complex.

                                  https://github.com/rust-lang/rfcs/blob/master/text/2025-nested-method-calls.md