1. 9

    I do like the juxtaposition between what an incredibly good idea this is and what an incredibly silly name it has. Oh well. It’s not actively offensive, at least. ♥

    1. 9

      why thank you

    1. 17

      if err != nil { gets old even faster.

      I just started using Go recently and really find this to be annoying.

      1. 6

        I remember reading (on the Go blog maybe?) about doing a small “assert” function for things that can fail (like command line utilities), it’s been one of my favorites since then:

        func assert(err error) {
            if err != nil {
                log.Fatalf("Fatal error: %s\n", err.Error()) //or panic(err) if you want the debug info
            }
        }
        

        then you can just do something like:

        func readConfig(path string) (cfg Config) {
            file, err := os.Open(path)
            assert(err)
        
            err = json.NewDecoder(file).Decode(&cfg)
            assert(err)
        }
        

        Of course, if you’re doing web services or any sort of daemon you’d want to handle errors gracefully, without having them kill your app (unless you’re doing startup)

        1. 4

          I felt the same way for a while but eventually you get over it. There are other things that in other languages would take a lot to express but are short in Go (e.g., interface behavior).

          1. 4

            Personally I prefer this feture than exception, it’s more explicit than exception, and not that cubersome. Exceptions always make me worried that there may be some unhandled mess deep down the function call so I have to wrap the call with try catch block and finally it indents the main logic futher and gets ugly.

            EDIT: Besides, It’s extremely terrible to mix return error and throw exception in the same application, which is very common if you use different libraries with different error handling styles, while golang makes it consistent.

            1. 7

              Personally I prefer this feture than exception, it’s more explicit than exception, and not that cubersome.

              But it’s not a binary choice of nullable error types versus exceptions. Sum types solve this problem quite elegantly, especially combined with some facilities to ‘unwrap’ instances of such types safely (e.g. try! in Rust or the Maybe/Either monads in Haskell).

            2. 5

              A lot of Go’s features are slick, but this error handling is indeed pretty ugly. I wonder what the underlying reasons were for them to implement it like this.

              1. 19

                Explicit over magic.

                1. 5

                  This, so much this.

                  It’s ugly, but it’s clean enough that I miss it when working with other languages. I always find myself having to deal with C++ functions that might throw exceptions, PHP functions that either use exceptions or have their own get_last_error() function. Haskell which has just about a bajillion ways to do errors (and this 15 pages guide only covers some of them).

                  Go’s error handling is one of those things that make it boring as hell, but also what makes it so easy to be productive at. I just never overthink stuff as much as I do with other languages.

                  1. 4

                    What about error handling in Rust? It’s basically unwrap() if you want to ignore the error or propagating it (via try!). Other things like ignore and use default value X are also possible.

                    The main benefit over Go is that you have to handle the error somehow. You can’t forget to ignore it, and you have to ignore it explicitly if you want to.

                    1. 2

                      Haven’t had to deal with Rust yet, so I really don’t know what you’re talking about, sorry!

                      Maybe I should try it again at some point (never seriously considered in the past due to the constantly changing API).

                      1. 3

                        The API has been stable for over a year now, so if you’re interested, now would be a good time to try it out!

                      2. 1

                        Don’t forget that Rust still has panics, which for me show up most commonly on array and Vec indexing when I’ve got a bug. Granted, this kind of exception almost always shows up in testing for me, and I rarely encounter libraries which panic on their own, but it’s worth remembering that Result<T, E> isn’t the only way that Rust handles error conditions. I personally don’t worry nearly as much about panics as I do unchecked exceptions in Java or Python, but nonetheless it’s worth noting that Rust doesn’t offer a panacea here, just different tradeoffs (which I’m quite happy with).

                        1. 1

                          Go also has panics though, so it’s not really a differentiator.

                          1. 1

                            I wasn’t attempting to differentiate Rust vs. Go though. If I wanted to differentiate Rust and Go re: error handling, I would point out that the Rust Result<T, E> type issues compiler warnings if you neglect to use it, whereas Go doesn’t appear to do that (although I haven’t written more than hello world in Go). I was pointing out that Result isn’t the whole error handling story in Rust.

                    2. 1

                      arguably the key aspect of djb’s coding style that leads to fewer bugs in practice is extremely explicit error handling. I’m sure the OpenBSD folks handle errors the same way.

                      1. -3

                        Laziness, more like.

                        1. 6

                          I’d believe that for most other teams. But Go is really a language that has been designed. Even OCaml, a language I like very much, with tons of very fancy features, feels less cohesive and cleanly designed than Go.

                          1. 2

                            That’s well possible since MLs like OCaml consist of the core language and the module language and these feel a bit different. There is 1ML which tries to unify these in a coherent whole. Plus OCaml has a lot of syntax and type system featured plastered over the the underlying ML type system which make it a more flexible language but also a more complex.

                            Maybe it’s also because languages which can be completely understandstood feel more “designed” because it is easier to grasp the design and see how things fit together?

                            1. 2

                              More intellectual laziness. “Return values worked for me, why should I do anything else?” Thompson et al are certainly smart and accomplished, but definitely fossilized in their thinking.

                      2. 1

                        Learning the Maybe monad in Haskell started my love affair with the language. After my mixed experience with Go it was particularly prescient.

                        1. 1

                          I will take the balance of good enough features plus fast builds over richer features and painful builds every time. This is definitely an area where personal preference is the deciding factor.

                      1. 14

                        This is a really useful description of current affairs. I run a bi-weekly Rust Hack & Learn for over a year now and am member of the rust-community team. After all this time “find an easy description of Rust that tells people why it is cool in 5 minutes”, I’d describe this as the hardest problem in Rust.

                        I believe that problem stems from the fact that many of the features of Rust (safe sharing of mutable and immutable data) click rather late and are rather boring in short example. Most of these relate to the borrow management and the whole ownership system. The great thing about them is that they scale really well to large codebases and enable a lot of guarantees, especially in the face of concurrency. But that’s something for people that are 3 weeks in. Before that, Rust is a fancy new C dialect with iterators :).

                        1. 11

                          My biggest problem learning Rust isn’t it’s “cool factor” (I already think it is), it’s that the interesting projects I’ve come up with that Rust might be a good fit for are scarily big (ex: Writing a Unikernel, Building the storage layer for a database, Game Engine/ECS stuff). I think that’s partially because Rust’s benefits are evident for large codebases, so my mind goes there. More than “why is Rust cool”, I need to find a project that doesn’t overlap with my typical usage of other languages like Haskell (mostly web services)… or I need to figure out how to break down one of the bigger ones like a unikernel. /shrug

                          On the other hand, after writing this comment, maybe I should just get over my “fear of a large project” in a domain I’m unfamiliar with.

                          1. 5

                            i’ve bounced off rust several times because every time i think i’ll start a project in it, and start reading docs, it always ends up being “oh, this is both easier and more concise in ocaml”. i think i just don’t write the sort of programs rust is best suited for.

                            1. 2

                              i think i just don’t write the sort of programs rust is best suited for.

                              I feel exactly the same way. Also applies to Erlang, where you’d be nuts to use anything else for writing a cluster of non-HTTP network servers, but I can nearly always find an off-the-shelf solution for that kind of problem instead of writing my own.

                              1. 4

                                I can totally feel that. Rust has interesting limitations, but it grows on you over a few months. I really don’t want to code in a another language for the time being.

                                Also, the language does not care so much about being concise, but I also don’t care about conciseness too much. (that used to be worse)

                                That said though, that’s probably true for many languages and not a feature of Rust.

                            2. 4

                              I there any reason why you wouldn’t just write a component to a larger system, e.g. the rumprun unikernel (which is a supported target for Rust).

                              1. 3

                                For contributing to an existing project, I’m more motivated to contribute to MirageOS or HaLVM which unfortunately doesn’t help my Rust interests.

                                1. 6

                                  The Mirage project has interest in Rust support but no one to take point. Two birds, one stone.

                                  https://mirage.io/wiki/weekly-2015-08-26

                                  1. 2

                                    That looks great :) Thanks for digging that up!

                              2. 1

                                What about a rust backend for GHC?

                                1. 5

                                  rustc is already a frontend to LLVM – doesn’t Haskell have an LLVM backend?

                                  1. 4

                                    GHC does as of 7, and I believe it was improved in 8 (although I haven’t checked in on it)

                              3. 4

                                I recently saw a talk about implementing an TLS library in Rust in a way that the type system guarantees resistance to timing attacks.

                                I thought that was cool, but I don’t know how much that will help you.

                                1. 3

                                  Could you find a link to it? That sounds super cool!

                                  1. 3

                                    I don’t think the talk was recorded, and I don’t know if the slides are up, but the paper can be found here.

                                  2. 1

                                    That is very cool. If I end up going the Rust Unikernel route, I’ll build a TLS stack anyway. Mirage built their own, but afaik it isn’t resistant to timing attacks (and opens up an attack via GC).

                                1. -6

                                  Maybe he should’ve spent his time rather analyizing musl-code and improving it. The strlen-example may be shorter in Rust, but it definitely is way clearer in the C-case. Also, the side-effects of the C-code are much smaller, whereas I have really no idea what the Rust-compiler does with the code.

                                  What some people do with Rust can be considered Cargo cult programming. This is one of these cases.

                                  1. 20

                                    I’m not attempting to improve on musl, though. I’m trying to learn more about it and how applicable Rust is for these low-level userspace domains. That said, if I do find a bug in musl (very unlikely given the high quality of the implementation from what I’ve seen), I would of course contribute that upstream provided I’m able to supply a fix.

                                    The Rust code doesn’t have any side effects, unless the pointer isn’t a valid C string, in which case it has the exact same side effects that the C version would (dereferencing a null pointer, dereferencing past where the end of the string is if it’s not null-terminated, etc.). I don’t think anyone even passingly familiar with Rust would find the code opaque or side-effect-ful (although of course I could be wrong here).

                                    I also find it interesting when a hobbyist/learning project earns remarks like “they should have spent their time better by contributing to some other project.” If I opt to play video games instead of play around with Rust, would I still earn the same ire for failing to contribute to musl? Or is it only when I choose to spend my free time writing code to explore something new that I find interesting?

                                    Since you don’t provide any actual evidence to support your claim of cargo culting, I’m not sure how to reply to that except to say that I don’t think it’s a statement based on careful analysis.

                                    1. -3

                                      Analyze this: How is your malloc implementation in Rust supposed to be safer than the musl-malloc? If you can’t answer this question, then I made my point. If you do, I’ll excuse my error.

                                      Nevertheless, this argument about “time spent” can be approached in different ways: Of course you can spend all day playing computer games, but given I think you’re a smart fellow who wants to make a difference, I don’t think you would have a good conscience doing so. :)

                                      Now, let me give you a remark on side-effects: I wasn’t really clear about it, but what I mean is the following: Prove me wrong, but Rust is “documented by implementation”, even though there is a language reference. Now, what I mean is the following: Even a simple expression like in (https://github.com/dikaiosune/rusl/blob/master/src/string/stpcpy.rs) dest.offset(i) = source.offset(i); does a lot in the background (memory allocation for instance), and I don’t even know how it does it. Does it extend the memory region by one each time or does it allocate 512 at a time? Those are side-effects. Now, what is wrong with writing that in C? I mean, the C code in musl does exactly that, just with the main difference that it does it openly and in my opinion more efficiently (https://github.com/esmil/musl/blob/master/src/string/stpcpy.c).

                                      Now, we could argue about readability. I probably would write it in a different way, first getting the strlen, then mallocing, checking the malloc, copying the data to the new memory region and returning the address. But the musl guys know what they’re doing, and I’m sure you will already have a hard time “selling” a Rust libc to people (depending on the Rust compiler, larger, …), however, without doubt, the musl-libc will beat your Rust-libc in benchmarks. And if you can’t make your point how your Rust-reimplementation improves security, you are all alone.

                                      No matter what though, feel free to spend your free time as you wish. However, stop accusing people of “destroying your dream”. There are too many people here working on toy projects whereas they could actually make meaningful changes.

                                      I know many good ideas come from toy projects, but like in this case, you are just reiterating an idea, just like the 100th messaging app making no difference or the 1000th neuronal network implementation making no difference. Using Rust just for the sake of using Rust is like trying to “boil the ocean off” and for me looks like cargo-culting.

                                      1. 4

                                        Thank you for the compliment :). Not all time spent has to be toward an immediate improvement to an existing project for it to be enjoyable or worthwhile, though, so I think we may just have a disagreement here about the moral nature of open source contributions.

                                        Re: malloc’s safety, this is a bit tricky. For one thing, I wrote the blog post mostly to get my thoughts down and to tell other Rust developers what I’ve been working on, foolishly not expecting it to get any attention past the Rust subreddit. As a result, I wrote it about the initial stages of a project where I anticipate future work to move in the direction of more safety.

                                        That said, the Rust malloc/free is already slightly more resilient to programmer error than the C version, as it has namespacing and slightly stronger typing. I have a local branch where I’m working on using Rust’s RAII resource management for the locks which control parallel allocation, another example (in my opinion) of a potential safety improvement over the manual locking/unlocking schema used in the basic C code. I’m also working on a few different ideas for using Rust’s type system to reduce the amount of bit-twiddling needed.

                                        Anyways, if I want to avoid manually linking in C code which I’m trying to replace, I need to have a dynamic memory allocator, so that’s why it’s the first greater-than-a-single-function portion of the code I worked on porting. It’s not because malloc/free are regularly vulnerable to untrusted input. Instead, I need to have it available for working on portions of the networking code that I’m hoping to use as the real test-bed for providing low-level safety with Rust’s type system.

                                        Finally, if I can achieve any safety improvements at all, I would consider that a massive win. Given that I’ve seen many opinions that this kind of work may not even be possible in Rust, I think that achieving a level of functionality even a little bit close to musl would be a big win and a useful demonstration for what a language I love is capable of. In other words, safety improvements would be icing on the cake, but the current scope of the project is just to show that this incremental process is possible and that Rust can do this kind of work. Oh, and to learn more myself since I’ve never before worked on standard library internals or low level items like memory allocation.

                                        1. 4

                                          Re: side effects, there’s no memory allocation performed. If you like, you can look at the assembly here, although you should make sure to enable Release mode (-O2), and click ASM instead of Run. It runs without an allocator, and it just a simple string copy between two pre-allocated pointers. Per its man page, stpcpy doesn’t allocate/reallocate/extend any memory but uses a destination array passed to it by the caller. I’m not sure what exactly leads you to think that Rust has hidden memory allocations everywhere?

                                          Yes, Rust is documented by implementation. There are a number of sources of documentation, but no language standard. You may recall that the first C spec, ANSI C/C89, was a process that started in 1983 long after many compilers implemented the “C language,” and it was an effort to find common ground. Very few (if any) programming languages begin with a formal standard or specification. That process took 6 years, after the nearly a decade had passed after it was first developed (1973-83). Rust has been the language it is today for ~13 months.

                                          I probably would write it in a different way, first getting the strlen, then mallocing, checking the malloc…

                                          Then you would not be writing an implementation for stpcpy.

                                          however, without doubt, the musl-libc will beat your Rust-libc in benchmarks

                                          That remains to be seen, and in other areas Rust code has been very competitive with similar algorithms written in C. Notable excepts are those C algorithms which use SIMD intrinsics, which are still being stabilized in the Rust compiler.

                                          if you can’t make your point how your Rust-reimplementation improves security

                                          As I’ve already said, this project is not about “showing up” musl or doing any sort of magical Rust security dance. But I think my other reply to this claim does address some of what you’re talking about.

                                          There are too many people here working on toy projects whereas they could actually make meaningful changes

                                          Experimentation is an important part of what we all do. Learning is also an important part of it. What you call toy projects are for many ways to learn new things and sharpen their skills.

                                          you are just reiterating an idea

                                          Can you show me other demonstrations of using Rust for Linux code that interacts with the kernel and existing userspace code? It’s not completely novel, but it’s also not “the 1000th neural network implementation.” It’s interesting to me, and apparently interesting enough to others that it was shared around without my involvement.

                                      2. 5

                                        Why is this “cargo cult programming”?

                                        1. 2

                                          Because an “unsafe” malloc implemented in Rust is still “unsafe”. He literally disables the “safe” language features of Rust to accomodate the libc-API. I’m wondering why my post is downvoted so much, because that’s what cargo-cult is.

                                          Rust-fans claim Rust is secure and has security features (let’s not discuss that here), but if they are disabled anyway why even bother writing it in Rust? I also see no way for instance how “strlen” can be exploited in some way unless the user passes garbage to it. And even the safest Rust-musl-libc-implementation can’t cope with garbage-input.

                                          Cargo cult programming is a term used for using something that is really superfluous with no reason at all. And in this case, this is a prime example for this definition, given Rust really serves no purpose here.

                                          1. 8

                                            Rust’s safety isn’t exclusive to borrow-checking, though. For example, the rusl code requires far more explicit handling of integer types, since Rust doesn’t have implicit promotion. I believe that while it adds some verbosity, it’s a win for clarity.

                                            if they are disabled anyway why even bother writing it in Rust?

                                            I addressed this briefly under “What does Rust offer here?”

                                            Cargo cult programming is a term used for using something that is really superfluous with no reason at all.

                                            Cargo cult programming (per the link you originally shared) is about ritualistic use of code or structure which doesn’t actually serve a purpose. Extreme examples might include a small web development consultancy saying, “well Netflix has scaled like crazy using microservices, so we should use them too!” My feeling is that I’m doing is not a ritualistic use of Rust because I’ve seen it succeed elsewhere, rather it’s an investigation into whether this kind of project is possible (not just for Rust, but for me with very limited background outside of Java/Python web development).

                                            1. 4

                                              The “cargo cult” refers more specifically to doing things the old way, without understanding the reason. Maybe it works, maybe it doesn’t; but all sense has been lost.

                                              With regards to the Rust implementation of musl, this is clearly a proof-of-concept at present. Time will tell if it proves to be like the dancing bear.

                                              1. 1

                                                Cargo cult programming is a style of computer programming characterized by the ritual inclusion of code or program structures that serve no real purpose.

                                                I was building on top of this definition. I just can’t get in my head, how this is supposed to be more secure than a C-libc. Thing is: People will still call the “unsafe” libc-API. If we look at the strcpy() implementation for instance, if someone passes a non-nul-terminated string to it, it will still try to copy unmapped memory regions (if I am not mistaken).

                                                1. 6

                                                  The phrase “ritual inclusion” is key here – it refers to things people do over and over again without thinking.

                                                  Are you familiar with the origin of the phrase “cargo cult”? It is discussed at some length in Seriously You Are Joking, Mr. Feynman.

                                                  1. 0

                                                    Yeah, the John Frum cult is a very interesting piece of living history. To improve my point, we could take the “Rust-cult” and say that it ritually rewrites software in said language claiming it’s more “secure” while giving no strong points for this case.

                                                    If you look above, @dikaiosune gave a great answer in this regard. It’s a thin line between cargo culting and actually trying to introduce safe concepts into the world. We’ll see what the future will bring. My bets are on Golang rather than Rust, but YMMV and I’m open-minded.

                                                    1. 8

                                                      It really does not seem accurate to describe a new implementation of a library with new technology as “cargo cult”. Above you remark “I’m wondering why my post is downvoted so much, because that’s what cargo-cult is.” and this would be why – it seems more pejorative than descriptive.

                                                      With regards to introducing safe concepts, Rust really does seem to be meeting the challenge head on – providing safety in a way that can be slid under present-day clients of C libraries, and thus offering safe interfaces to Ruby, Python, &al – instead of taking the “boil the oceans” option that Java tried.

                                                      1. 7

                                                        claiming it’s more “secure” while giving no strong points for this case

                                                        I’ve certainly not said that, nor has anyone in relation to the hobby project I wrote about. So perhaps you’re referring to other Rust projects here? If so, would you care to share them and also what about their claims of security are false?

                                          1. 4

                                            I think one problem with this is that C programmers do not want to depend on the rust compiler. There is only one implementation of the rust language, and i don’t anticipate more any time soon.

                                            1. 6

                                              I agree that it’s an issue. I think that being backed by LLVM ameliorates some of the problem, but not all of it (esp. when it comes to embedded targets where Rust could be used for safety-critical work). There’s actually at least one alternative implementation in progress:

                                              https://github.com/thepowersgang/mrustc

                                              There’s also someone working on a Rust GCC frontend (now that GCC has something akin to LLVM IR), so we might see Rust available on GCC targets in the future. Granted, neither project is mature, so your statement is accurate for the time being.