Settings

Theme

Five Years of Rust

blog.rust-lang.org

293 points by pietroalbini 6 years ago · 132 comments

Reader

ojnabieoot 6 years ago

The progress on the error messages truly is worth highlighting, and kudos to the team for all the hard work there. It's one of the hardest things to get right in a programming language, particularly if that language has a fussy compiler.

  • pornel 6 years ago

    It is great. Rust 1.0 with the old borrow checker required knowing where to strategically place extra curly brackets, and when to add `ref` or `.as_ref()` incantations.

    Now with the smarter borrow checker and ergonomic improvements most of it is unnecessary, and the error messages know how to suggest the rest.

    • metreo 6 years ago

      Still quite a lot of circular gotchas, so it's not a panacea for studying the docs!

  • empath75 6 years ago

    I’ve been using the anyhow crate and it’s made error handling almost painless.

    • GolDDranks 6 years ago

      You are talking about different things, the grandparent was talking about the compiler error messages.

      Just a note, I agree with both of you :)

    • jrimbault 6 years ago

      Just to point out for other readers, nowadays to make a custom error type you just need :

      - an enum (or struct)

      - its Display implementation

      - its Error implementation, now just one function

      And a few `impl From<OtherError> for MyError` to make the try? operator work.

      For a library it's really not that much work. And even that can be simplified further to a few derive macros with another library : thiserror.

      • asdkhadsj 6 years ago

        To simplify even more, you don't actually need `Display` or `Error` impls. I use Error enums frequently without display or Error impls. Though, with better backtrace support coming it'll be handy to have Error and the Backtrace related APIs implemented.

        (Sidenote, I don't use `impl Error` because I never use `Box<dyn Error>`. Which isn't to say that's correct, just to say that I've never had the need to implement it)

        • JeanMertz 6 years ago

          Even though GP meant to highlight compiler error messages, I also have to take my hat off for the library/application error-handling story in Rust.

          Using a crate such as thiserror[1] combined with displaydoc[2] makes handling errors in a structured manner a great experience. I love how the error handling story has evolved over the last couple of years in Rust, and it really feels like we're entering into the final stretch of fine-tuning to get the best possible experience.

          And yes, anyhow[3] is also great, it serves a different purpose, but I frequently reach for all three crates.

          [1]: https://crates.io/crates/thiserror [2]: https://crates.io/crates/displaydoc [3]: https://crates.io/crates/anyhow

    • aliceryhl 6 years ago

      Anyhow isn't really about error handling, but about error reporting. With an ordinary enum error, I can match and easily handle the error if I want to handle some errors in special ways. If I want to handle an anyhow error, I have to do string matching on the message, or try to downcast it, which is cumbersome.

      What anyhow makes easier is to collect many types of errors together and reporting the errors to the user.

jasode 6 years ago

Now that there's been 5 years since v1.0, is there any consensus on design mistakes that Rust made? Any mistakes that people wish they could turn back time and do differently but can't because it would break compatibility with too much existing code out there? That's the more interesting list to me.

  • pornel 6 years ago

    There isn't much. Rust has deprecated some mistakes (like Error::cause). The editions mechanism allowed fixing some issues (like unintuitive module paths).

    https://github.com/rust-lang/rust/issues?q=label%3Arust-2-br...

    • Struct literal syntax should have used C99 syntax. The language uses `name:type` everywhere except struct literals which use `name:value`, and this gets in the way of adding new syntax (type ascriptions).

    • `Box` is semi-magical. Maybe it could have been a regular struct. Or maybe magical all the way to allow placement new and destructuring.

    • Types are in borrowed, owned-fixed-size and owned-growable variants, but naming of them is a bit ad-hoc. There's str/String, but Path/PathBuf (instead of e.g. String/StringBuf or path/Path).

    • Split between libcore and libstd is awkward to manage and not a good fit for WASM. It could have been one libstd with feature toggles (this might still happen).

    • Some people think split between Eq and PartialEq is an overkill, and just makes floats annoying.

    There are things that are still unsolved in Rust, like umovable types and self-referential structs. But it's hard to say they're a mistake — as far as we know, they're a necessary limitation to make other useful features work.

  • bryanlarsen 6 years ago

    The "2018 edition" of Rust made breaking changes to the syntax (but the core stayed compatible, so 2015 edition and 2018 edition Rust can be used simultaneously on the same project).

    They then said that they'd probably do the same thing in 2021.

    Now they're debating whether a 2021 edition is needed since there aren't any breaking changes with broad support except for the removal of deprecated syntax and APIs.

    This is strong evidence that the answer to your question is "no".

  • ainar-g 6 years ago

    One way to reason about what could have been done better from the beginning is looking at stuff that is marked as [deprecated] in the standard library. E.g. how the "try!()" macro was deprecated in favour of the "?" operator.

    • cesarb 6 years ago

      I would say the try!() macro is an exception to that rule: if the ? operator existed since the beginning, it would be seen as "too much magic" (in a language that already used up most of its "strangeness budget" in lifetimes/borrowing), while try!() is just a very simple macro you could write yourself, with no special compiler support. Only later, after people got used to try!() everywhere, the ? operator became viable, as "just a shortcut to try!() with better precedence (and it also works on Option)".

      That is, there's a path dependence, where the existence of try!() made the ? operator viable.

      • jasode 6 years ago

        >if the ? operator existed since the beginning, it would be seen as "too much magic" [...] That is, there's a path dependence, where the existence of try!() made the ? operator viable.

        Yes, C++ creator Bjarne Stroustrup made a similar observation:

        - For new features, people insist on LOUD explicit syntax.

        - For established features, people want terse notation.

        There seems to be an invisible "Overton Window" of evolving programming language features and syntax.

      • zanny 6 years ago

        Having both the terse and the verbose is so valuable for onboarding.

        I feel like the reason pointers as a mechanism in native languages is such a barrier to cross for a newbie is because they are this magical star symbol * just floating around doing... something?

        If people started out writing pointer<string> foo instead of string* foo and had to use explicit derefrencing via name rather than by magical glyphs onboarding would be so much easier.

        I think it applies to almost all programming concepts too. Starting a language with a baseline grammar of just function invocation -f(x) = y as <noun>.<verb>(<noun>...) - and extrapolating from there and introducing terse grammar progressively as shortcuts would serve much better to get concepts in heads rather than arcane ritualistic glyphs. Introduce x.add(y) then say x + y is the shorthand.

        Rust does a really great job "functionizing" almost everything in the language - it has the add trait after all https://doc.rust-lang.org/std/ops/trait.Add.html. You can actually write tons of Rust in just function call form and make it look like Lisp.

    • ChrisSD 6 years ago

      I think more interesting would be something we're truly stuck with (at least until Rust 2.0, which may never come).

      • steveklabnik 6 years ago

        (Stuff that’s deprecated in the standard library is stuff we’re stuck with; they cannot be removed in editions.)

        • littlestymaar 6 years ago

          I've seen this said many times, but I don't really understand why.

          Why couldn't a new Rust edition create a new std2021 (for instance), and automagically use it when importing a std submodule in a project using the new edition (and in the prelude)? The old implementation would still be imported using std in crates using prior edition, and could still be imported in the new edition, but named std2018.

          If all the implementation (except the now deleted stuff) is put in the std2021 module and the old std2018 () simply re-export it (and re-implement the old stuff), you wouldn't break anything would you?

          I'm probably missing something, but so far I don't know what and I'd be really happy if somebody enlightened me.

          • steveklabnik 6 years ago

            > Why couldn't

            There may be possible ways of doing this, but you're approaching this from the wrong angle. Right now, this is not possible, due to policy. This policy is informed by the technical restrictions right now. There may be possible ways in the future to handle this, but as of right now, there are not.

            The reason this is true right now is that there is one copy of the standard library for every program. So it needs to support all editions, because code from multiple editions may call standard library functions.

            If we had multiple copies of the standard library, you may end up with issues where two different programs can't interoperate because they'd be using different versions of the same crate, and given that one of the most important features of the standard library is interoperation, this is a huge drawback for the stdlib specifically.

            (There may be other technical issues, I am not an expert here, but that's the biggest hurdle as far as I know.)

            • littlestymaar 6 years ago

              This isn't the answer I wanted, but it's a good answer. Thank you

              • steveklabnik 6 years ago

                You’re welcome. (I imagine that you’d get the same version conflict situation with your idea btw: std::2018::Option is not the same type as std::2021::Option.)

        • ChrisSD 6 years ago

          Sure but you don't have to use them, is the point I'm trying to make. They don't affect modern code and while it's annoying they are used in older code there is at least a path forward to "upgrade" the code to the modern equivalents.

        • pas 6 years ago

          Could a lint check for them and warn if some code uses them?

          This way slowly the ecosystem could move and stuff could be eventually removed.

          • steveklabnik 6 years ago

            If you use something that's deprecated, you get a warning, yes.

            > could be eventually removed.

            It can not be used according to our stability policy. There's a lot of closed source Rust out there.

            • ChrisSD 6 years ago

              There has been talk on the internals forum of "gating" deprecated parts of the std on a new edition. So the deprecated feature will be hidden for crates that declare `edition = '2030'` but will be available for crates using an older edition. Essentially turning the warning into an error.

              But this is just talk at the moment. Currently there is no mechanism to implement this. It would also be a challenge for documentation.

              • steveklabnik 6 years ago

                Yes; this is so far off, and is not even at the RFC stage, that I didn't mention it. But you're right that maybe, someday, we could make it even harder for folks to call these things in newer editions.

    • eximius 6 years ago

      No, this was intentional. The point was to see how the user base used the language before adding permanent language features.

  • twic 6 years ago

    The planned const generics syntax is going to look pretty weird, because it builds on type generics. If Rust had chosen a different syntax for type generics, const generics might look less weird.

    The futures design was built with epoll in mind, and now people are trying to wrap it round io_uring, they are feeling some pain. Would a different design have worked better, without massive drawbacks?

    • masklinn 6 years ago

      > The planned const generics syntax is going to look pretty weird, because it builds on type generics. If Rust had chosen a different syntax for type generics, const generics might look less weird.

      Could you provide an example? Because I don't really see it, except by requiring that non-const generics also be explicitly annotated?

      • twic 6 years ago

        I'm thinking of the need to have blocks wrapping expressions in types [1]:

          const X: usize = 7;
          
          let x: RectangularArray<i32, 2, 4>;
          let y: RectangularArray<i32, X, {2 * 2}>;
        
        Simple cases are fine, but i suspect a lot of real-world use of const generics are going to require blocks.

        AIUI, this is only because <> was chosen as the container for type arguments, and > is also a legal operator in expressions. So, for example, if Rust had used Scala-esque [] for type arguments, this would not be a problem.

        [1] https://rust-lang.github.io/rfcs/2000-const-generics.html#ap...

        • Uther 6 years ago

          While I would prefer brackets, that would not be enought to solve all the problems since, there would be conflict with array syntax too.

          • twic 6 years ago

            But the square brackets used in array access nest, so the parsing is never ambiguous.

            The reason > needs braces is that without them, if you're parsing and so far you've seen these characters:

              let y: RectangularArray<i32, X, 2>
            
            You don't know if that final > is ending the argument list, or is a greater-than operator, with the rest of an expression coming after it.

            But if it was square brackets, then a closing square bracket on its own can only ever be the end of the list:

              let y: RectangularArray[i32, X, 2]
            
            Because if it was closing an array access, there would have to have been an opening square bracket:

              let y: RectangularArray[i32, X, a[1]
          • masklinn 6 years ago

            That's what I originally thought about, but the thing is `]` in and of itself is not an operator while `>` is, so

                foo<bar, qux>corge>
            
            "is" valid syntax while

                foo[bar, qux]corge]
            
            is not. The former requires some sort of disambiguation, while the latter is not. Put an other way, in terms of syntax `[]` always parses the same way (with `[` is infix and `]` terminates it), there can be ambiguity between indexing and generics but it doesn't really matter for the original parsing.

            For `<>` however, the parsing itself can be ambiguous as `>` could either be the terminator of an earlier `<` or it could be the infix `>` operator. That is where the issue lies, you can't know how to build the AST without either explicit disambiguation, or infinite lookaheads.

  • Ericson2314 6 years ago

    I've been complaining for a long time that `Drop` is fundamentally wrong. Rust's "just write a new function" fixed C++'s "construction is mutation of location", but Rust's Drop makes the same mistakes as C++: destruction needs to be for consuming data, not borrowing it and mutating it.

    Now, we can't just do

      drop<T>(T)
    
    because of DSTs, so we we'll need a new type of consuming reference. And the dual to that, an initializing reference, would also solve the problem of creating DSTs with preallocated memory.

    Now both could use MaybeUninit, but it would be better to just have types that vary with the CFG, so one can insure that no matter how one get to point b, the memory is now initialized.

    • Manishearth 6 years ago

      > but Rust's Drop makes the same mistakes as C++: destruction needs to be for consuming data, not borrowing it and mutating it.

      but Rust's drop isn't for that purpose. It's not for the actual cleanup of the struct and its children it is for additional cleanup before the children are deleted. So it has to be mutable. The compiler synthesizes the "delete children" code.

      (I don't understand your point about drop<T>)

      • Ericson2314 6 years ago

        > It's not for the actual cleanup of the struct and its children it is for additional cleanup

        I think that purpose is the tail wagging the dog, an explanation of the current method rather than an actual requirement.

        The simpler thing to do is just have drop on the aggregate calls drop on the fields, just as new on the aggregate can call new on the fields.

        • Manishearth 6 years ago

          This does not seem simpler to me, this seems easier to mess up. The most common use case is dropping all fields.

          Furthermore, you still have to special-case Drop because now you have to support destructive destructuring for Drop types because it isn't allowed anywhere else.

          And plus, if you forget to do this, the failure mode is a stack overflow.

          The current design is absolutely based on practical requirements here, it is not a retroactive justification. This is by and large how destructors work, for good reason.

        • Ericson2314 6 years ago

          > (I don't understand your point about drop<T>)

          Ah I meant to write the function signature:

          > fn drop<T>(T);

          contrasted with the:

          > fn drop<T>(&mut T);

          that we have today

  • brutt 6 years ago

    Incompatibility between C enums and Rust enums forces to use integers instead, which leads to errors. (Rust doesn't allow to enum variables to be forward compatible, i.e. it cannot have a value outside of enum).

    • ChrisSD 6 years ago

      I think that's a good thing. A C "enum" is just a shorthand for declaring an int alias and some constants. You can do that in Rust easily enough.

      A Rust enum is an actual enumeration type, which C does not have. This is far more powerful.

      • brutt 6 years ago

        It's good thing, but it leads to error in code which must talk to C or network, where enum's are not cast in stone.

        • CameronNemo 6 years ago

          You really should not be casting data structures sent over the network directly to local data structures, unless you are using capnproto or another zero copy protocol that does that safely.

        • mlindner 6 years ago

          You can assign any value to a C enum, they literally are just integers.

    • masklinn 6 years ago

      > Rust doesn't allow to enum variables to be forward compatible, i.e. it cannot have a value outside of enum

      AKA Rust's enums are type-safe, not aliases for integers with some named constants.

      Rather than Rust's, I'd say the mistake is C's enums. If you don't want enums, don't have them.

      I guess that's one place where Go did something good: they didn't want to improve on C's enums with proper ADTs so they just stripped out the entire thing, an "enum" is an integer and a bunch of constants. Which you can also use to represent these non-enums in Rust though it doesn't have the iota / step convenience. A simple recursive macro might be able to handle it though.

    • bluejekyll 6 years ago

      To future proof an enum in rust you use the #[non_exhaustive] annotation.

      For C compatibility you have lots of options like #[repr(C)] or #[repr(i32)] to be C compatible. So not sure what you are referring to?

      • brutt 6 years ago

        The problem is that #[repr(C)] enum is not compatible with C, even with #[non_exhaustive] annotation, and will never be, because C enum can be described in Rust terms as:

          #[repr(C)]
          enum Foo {
            A = 1, 
            B = 2,
            C = 3,
            UNKNOWN(i32),
          }
        
        which is not possible to define in current version of Rust.
  • PudgePacket 6 years ago

    Those topics come up on reddit.com/r/rust quite frequently, along the lines of "What are the biggest mistakes in Rust" etc, you can find a bunch by searching something similar.

  • RazrFalcon 6 years ago

    Three chars limit for keywords and some std types, e.g. `Vec`, `len`, `str`.

    • _nalply 6 years ago

      I respect your opinion, but I tend to disagree. The terseness is a feature I like.

Multicomp 6 years ago

Is now the time to start learning rust? In your estimation, are there going to be lots of job opportunities for people who have 15 years experience with rust?

I primarily live in the .Net world, but rust seems extremely close to f# in terms of compiler safety, and I'm trying to decide what programming language to learn next.

  • afandian 6 years ago

    I learned it a few years ago, just for fun. I have it in my back pocket for a personal project. The language has some odd corners to learn (and they are what make it special), but it's not so difficult you can't forget about it for a year and then come back to your project, as I have.

    There's some highly specialist aspects you _could_ learn (like anything I suppose), but I've got enough to get by and be as productive as I'd like without needing to get to that level.

    So there's no harm in learning enough to get by for fun.

    Compare to e.g. Haskell, which I learned at university, I have a memory that you'd have to invest quite heavily to make it do something useful.

  • doteka 6 years ago

    My job is about 50% Rust, 40% Typescript, 10% Python with regards to language.

    I would say Rust is the best day to day experience out of these 3 except for glitchy editor tooling and the long compile times. We have 1000 line services that take close to 10 minutes for a release build which is not ideal.

    I would not necessarily suggest learning Rust to get a job though. We mostly stopped mentioning it in our job ads because we don’t want people applying for the “hip stack”. Usually, competent programmers with some basic understanding of how manual memory management works have no trouble picking it up as they go.

    • mlindner 6 years ago

      > We mostly stopped mentioning it in our job ads because we don’t want people applying for the “hip stack”.

      Can you elaborate on that? I'm maybe thinking of changing jobs soon and my #1 want is that I can commonly program in Rust as opposed to C. Why would you explicitly avoid mentioning Rust?

      • doteka 6 years ago

        Yeah, sure. What I have seen a lot when hiring, is "magpie developers". These guys always have the hippest CV - if it's on the HN front page regularly, you bet it's on there.

        We found in practice, these people tend not to be the best additions to a team. They are mostly interested in the new thing, and only for so long as it is new. When something new comes along, that's what they want to flock to. They'll be an endless source of rewrite suggestions, but tend to struggle when they need to actually dive in and solve complex problems with these tools.

        In contrast, we are not really using Rust because it's the new thing on the block. We are using it because we write complex software that needs to run fast for the business to be viable, and Rust's got the best tradeoffs for that right now. If Rust wasn't a thing, we'd likely be using C++.

      • doteka 6 years ago

        Also, a word of advice: the language in use should be one of the last things you're considering when looking for jobs. It really doesn't make a difference in your day-to-day happiness.

        Instead, try to look for a team you fit in with, a manager you can trust, growth opportunities, and the chance to work on interesting projects that have impact. Case in point, one of my most enjoyable (and beneficial to my career) jobs was mostly Java 8 - and that's certainly near the bottom of my "good programming languages" list.

  • lllr_finger 6 years ago

    Now is a great time to learn it, because there's nothing huge on the horizon that will make your life easier or harder.

    I started learning just as the async/await and futures features started causing churn and confusion in the ecosystem - it was slightly irritating at the time, but in hindsight, I'm still glad I started learning then.

  • WilliamEdward 6 years ago

    Plenty of big name companies (discord, amazon) and even universities (georgia tech) are using and teaching rust. That's enough for me to say you should jump on the train.

  • lhdj 6 years ago

    I started a company while also learning Rust. It seemed like the right choice given that we needed something which emphasized memory safety and was also blazingly quick, but I was essentially forced onto it while dealing with the pressure of having to deliver on tight deadlines.

    Our core tech is in pure Rust and I have to admit that coming from Javaland it's refreshing to deeply trust your code. It's hard to convey this idea of 'if it compiles it works' but I no longer worry about showing off prototypes to people. If they compile they work.

    There is a learning curve as you are introduced to new ideas and design patterns but it's worth it! Rust has made me a better programmer.

manaskarekar 6 years ago

Non-Lexical Lifetimes was huge. Impressive list.

I hope the next 5 years bring compiler speed ups.

lllr_finger 6 years ago

One of my favorite things with Rust is how other things are starting to use it. Just yesterday I started playing with Deno and was anticipating a severe lack of database bindings. Some people used the built-in Typescript->Rust message passing to make a tiny shim around the Rust bindings for things like MongoDB: https://github.com/manyuanrong/deno_mongo

mindv0rtex 6 years ago

I hope Rust adds the major anticipated features (GATs, const generics, specialization) soon, or alternatively decides to not implement them altogether. I'm a rather new Rust developer, but still I very quickly ran into the issue of needing a nightly version of rustc because one of my dependencies (PyO3) relied on one of these features. It would be awesome to have some periodic updates from the compiler team on the progress thereof.

  • pas 6 years ago

    There are many places to follow:

    https://github.com/rust-lang/wg-traits/tree/master/minutes

    https://github.com/rust-lang/lang-team/tree/master/minutes

    https://rust-lang.github.io/compiler-team/

    There's a youtube channel too. (Also start here: https://blog.rust-lang.org/inside-rust/2020/03/28/traits-spr... )

    The important thing is the `chalk` work. And basically the rust-analyzer approach drives that.

    Hah, this branch PR got merged 6 days ago into rust master: https://github.com/rust-lang/rust/pull/69406

  • bluejekyll 6 years ago

    Technically speaking, those are implemented, just not stabilized, if you’re using them in the nightly, they’re just disabled in stable.

    So I would anticipate they will eventually stabilize like many other features have and become part of stable.

    • estebank 6 years ago

      Just want to clarify that an implementation being present in nightly doesn't ensure a timeline for stabilization or even that it will happen, as unexpected bugs in the implementation or design of the original RFC might crop up once it's actually used that makes us take the decision to push the stabilization back. This has happened multiple times (from a single version delay to things that are perma-unstable). That being said, the majority of the unstable features you're waiting for "only" need baking time.

    • pas 6 years ago

      GAT and specialization still needs a lot of magic, mostly chalk/polonius integration, doesn't it?

  • lzutao 6 years ago

    We need more volunteers to help implement those features!

    • mindv0rtex 6 years ago

      Is there a meaningful help that a Rust beginner can provide here?

      • swsieber 6 years ago

        Many tickets are scored with a difficulty, and sometimes comes with a mentor: https://github.com/rust-lang/rust/labels?q=E-

        I think there are meaningful things a beginner can do. I'd be surprised if improving error messages would be terribly hard. And working on the small issues will help you become familiar enough to help with the bigger things.

        Edit: Also perhaps a way to get some exposure to the rust compiler is to help implement lints (in clippy) - it's basically a compiler plugin and relies on the same things available in the compiler.

        • estebank 6 years ago

          The D-papercut diagnostics tickets are in my mind a great source of these kind of newcomers tasks, as some are quite small and don't require full context of the codebase.

aey 6 years ago

The killer feature of rust is rapid incremental improvement of the language. Every quarter something gets better.

  • busterarm 6 years ago

    That's a feature of several languages right now/at times.

    • fastball 6 years ago

      I agree. That's how I've felt about Python with every release since 3.5

      • BiteCode_dev 6 years ago

        And yet there are people complaining it's too slow, or too fast.

        I don't think there is any pace of language evolution that will never be criticized.

        • aey 6 years ago

          Rust has been really great at incremental language upgrades because of clippy. Stuff get deprecated, clippy issues warnings, buy the time support is dropped your code has been patched.

          It feels like we are in some new weird software engineering world where the code is only alive while its actively maintained and worked on. The libraries that are shipped in the OS seem as constant and fixed in time as x86, basically completely abstracted by the constantly evolving software on top of it.

ncmncm 6 years ago

Rust is on track to soon--within ten years--become an industrially important language. I see no other language on the horizon that could take Rust's place alongside C++, in the places where they both excel.

That is not to say it will certainly become industrially important. It depends entirely on the numbers. Today, the total number of working Rust coders may be less than the number who start coding C++ in any given week. (This is a simple consequence of the difference between a base of thousands vs. millions.) But if it can sustain exponential growth long enough, and nothing else comes up in the meantime to take the wind from its sails, it should get there.

arcadeparade 6 years ago

What’s the best resource to get started with Rust and make a desktop app?

  • qwe098cube 6 years ago

    https://areweguiyet.com/ gives a broad overview, but is slightly outdated i believe. I recommend all raph linus' research on this topic, fairly recent blog: https://raphlinus.github.io/rust/druid/2019/10/31/rust-2020....

    Personally I used iced [1] a bit and found it very pleasant to use. iced is cross platform, sponsored and very active.

    https://github.com/hecrj/iced

    • rvz 6 years ago

      Well, at least read the small prints and footnotes of this GUI library.

      > Iced moves fast and the master branch can contain breaking changes!

      Even in general, this crate is not even 1.0 or stable for production use. I'd rather wait until it is mature before touching it. Until then, Qt is the way to go.

  • davidhyde 6 years ago

    Search for the following in your browser: “the rust book” for the official free online rust book. “rustlings” for a set of code exercises to get you used to fixing your code when the compiler shows you an error. “iced github” for a cross platform gui library and, lastly, “rust by example book” for a different angle on learning the language.

  • jayflux 6 years ago

    I personally started with the rust book, then went from there.

    https://doc.rust-lang.org/stable/book/

  • eximius 6 years ago

    There's always Electron, Wasm, and the few smatterings of decent GUI frameworks being worked on. Also https://github.com/tauri-apps/tauri which claims to be a... Light, more native Electron?

    Just depends what you want. A common pattern is essentially to build your app as a Rust library or CLI binary that your GUI wraps in whatever is most convenient for the GUI

jeffdavis 6 years ago

I've been working on postgres-extension.rs[1]. The idea is that, instead of writing a PostgreSQL extension in C (which is the only option for interesting extensions), you can also write one in pure rust.

I've eagerly awaited many features to make this work reasonably well, and I've been very pleased how much rust has helped my use case over the last few years.

Although lots of languages have a C FFI, that's really not enough to extend a complex codebase. Postgres has it's own setjmp/longjmp-based error handling, it's own system of allocators, it needs a way to find the right functions in an extension and call them the right way, its own way of dealing with signals, etc. There are zillions of internal structs, and the extension needs to be able to read/modify them without copying/translation. Oh, and also, postgres doesn't like threads at all, so the extension better not make any (at least not ones that call back into postgres APIs).

The only language even close to getting all of this right is rust:

* it has no runtime that causes problems with threading, scheduling, signal handling, or garbage collection

* typically GC'd languages can't operate very well on unmodified C structs; rust doesn't have a GC so it can

* rust goes out of its way to support C-compatible structs without any copying/translation, and can even treat some plain C representations as more interesting types in a binary-compatible way (like a nullable pointer in C could be treated as an Option<&MyStruct> in rust)

* the tokio library allows nice concurrency without creating threads if you use the CurrentThread runtime

* it supports changing the global allocator to be the postgres allocator

* rust has good procedural macro support, which is important because a lot of postgres APIs heavily use macros, so making the rust version ergonomic requires similar macro magic

Areas rust could be more helpful, but which I'm trying to address on my own to the extent that I can:

* Support for setjmp/longjmp. I know this is not easy, but important for interacting with C code that already uses it. I realize it would be unsafe, and that it can't be wrapped up in a safe way directly, and it would be delicate to create safe APIs that use it at all. But I still want it. I made a crate[2] that adds support, but it has a few issues that can't be resolved without compiler support.

* Better support for cdylib shared libraries that might call back into the host program that loads the library. Right now, you have to pass platform-specific flags to get it to link without complaining about undefined symbols (because they won't be resolve until the library is loaded into the host program). Also, it's difficult to test the shared library, because you have to guess at the location of the built library to be able to tell the host program where to find it before you can begin your test. I made a crate[3] to help with these things also, but it would be nice to have better support.

Oh, and one more thing on my wishlist not directly related to this project is that it would be nice to have support for datastructure-specific allocators (like a mini-allocator just for a hash table). Then, you'd be able to monitor and control memory usage by inspecting that allocator; and when you destroy or reset the hash table, you can know that the memory is freed/cleared as well (without worrying about fragmentation). Maybe these mini-allocators could also be used in other contexts, too, but it would probably be easiest to get the lifetimes to work out if it was tied to a data structure.

[1] https://github.com/jeff-davis/postgres-extension.rs [2] https://github.com/jeff-davis/setjmp.rs [3] https://github.com/jeff-davis/cdylib-plugin.rs

joshlk 6 years ago

Is there a roadmap for the next 1/2/5 years?

easytiger 6 years ago

Rust mods have to stop listening to the elite language intelligentsia.

Successful eco systems are pragmatic and idiomatically straightforward.

Everything & the kitchen sink in a language is not a recipe for success.

Every language that has a long lifespan spent a long time in feature minimal stasis too. The world won't learn a moving target.

  • rcxdude 6 years ago

    Rust is not particularly adventerous as far as PL theory is concerned: all of the ideas in it are actually quite old (just newer than the ideas in established languages, like C). It's fundamentally quite pragmatic and you see that in most of the decisions it makes. I also don't agree that minimal features is necessary for success (even though it may be a desireable attribute of a language). Many extremely successful languages have piled on features over time, some in a far less reasoned way than rust (C actually a big outlier in how slowly it has evolved: C++, Java, C#, python, perl, PHP, etc are all large languages, with complexity in terms of number of features similar to Rust).

  • carlmr 6 years ago

    Rust is barely a moving target since 1.0. If you only read the version releases it might seem so, but for the pragmatic programmer not much is changing. Many of the changes concern very special features that only a few libraries make use of. As a library user you don't need to learn them.

    I learned Rust a few years ago and without keeping up with the latest changes too much I still feel confident I can work on current code.

    • bennofs 6 years ago

      Having these "very special features" means that there are some things with are added to the language but rarely used. That means that you might come across code in a library that you don't understand, especially if you're not using those features in your own code.

      So, I think the argument that "very special features" shouldn't be counted toward language complexity/growth is wrong, IMO. I would even say that there needs to be even more focus on those features, since they tend to be not widely known, not familar, and often there is less documentation about them, so the likelyhood that they make code hard to understand is even higher.

      This is not to say that those features are unnecessary. I just don't think the justification "they are not what a pragmatic programmer will see" is good.

      • estebank 6 years ago

        If you look at the changes and cathegorize them they all fall in one if three camps:

        - sugar for quality of life improvements that benefits everyone (like ? or NLL)

        - new feature that lets you do something that couldn't be done before (like impl Trait or global allocators)

        - new feature that removes a special case of the semantics that can be extrapolated from already present features (like associated consts and subslice patterns)

      • FreeFull 6 years ago

        I'd say having special features is ok, as long as these criteria are met:

        1) It's obvious the feature is being used.

        2) The feature is easy to look up without knowing what it's called, just based on how it's been used.

        3) It's easy to understand what the feature actually does, with the appropriate context.

        • estebank 6 years ago

          The ? operator doesn't fulfill at least two of the three points, yet it's way more loved than hated. As a general guideline I agree with your points, but it is not to be taken as rigid gospel either.

  • ReactiveJelly 6 years ago

    The ecosystem _is_ one of my favorite parts of Rust.

    Building C++ (or C) projects is such a clusterfuck that it's given rise to header-only libraries.

    In Rust, everything is "cargo build", and adding a dependency is one line. This has only failed for me when there's a dependency on a C system library that I can't satisfy.

    Is it bad to have too many dependencies? Sure, maybe. Is that an excuse to have artificial friction? No. I eagerly await the day when meson or conan or whatever becomes The C++ Dependency And Package Manager.

    My other favorite part of Rust is the elitist language features like iterators, immutable borrows, functional programming, etc.

    • tragomaskhalos 6 years ago

      Related to this is how easy it is when looking at someone's code on say GitHub to (a) see how the whole project is structured - because it's basically always the same with the familiar landmarks of src/, cargo.toml etc, and (b) to track down the definition / implementation of a type or function (just by applying knowledge of the module system + looking at the mod and use statements). This is a completely different experience from trying to pick apart some C or C++, where you are, essentially, at the mercy of the implementor's idiosyncratic view of how code should be structured, and really need either an IDE or vast reserves of patience to help navigate it.

  • asdkhadsj 6 years ago

    While I agree with you, I think you underestimate the number of features that help Rust be great in the face of a Lifetimes and Generics. One feature tends to lead to another. For example, Traits with Associated Types are amazing, but they then lead to a desire for GATs. GATs aren't (in this context) some fancy feature of its own, it fills in a noticeable void in an existing feature, Traits.

    So many of these features Rust adds just fill in holes in an already extensive ecosystem.

    I agree some feature development could be toned down to mitigate the moving target problem.. hell I think last years poll expressed roughly that. But, I think there's still a ton of features yet to come that merely complete what we already have.

sandGorgon 6 years ago

Is the current status of Rust that it is slower than Go ? According to this previous post - https://news.ycombinator.com/item?id=23058147

  • melling 6 years ago

    I don’t think that was the conclusion.

    “ as some keen HN commenters have pointed out, it looks like the rust program is not actually equivalent to the go program. The go program parses the string once, while the rust program parses it repeatedly inside every loop.”

  • nindalf 6 years ago

    I don't think it is. The top comment in that thread indicates why.

    In general for most long lived workloads, I would expect Go to be approximately 15-25% slower than an equivalent C/C++/Rust program because of the CPU overhead of the Go GC. The Go team have done a lot of great work to optimize pause times and memory consumption though.

  • manaskarekar 6 years ago

    While Go may be faster somewhere, that post was not a good comparison.

    See the discussion around it and the patches made by the community and the final results.

    See the individual benchmarks: https://github.com/christianscott/levenshtein-distance-bench...

    • Tuna-Fish 6 years ago

      And just to help the lazy people, after making the benchmarked loads equivalent, the results are:

      hyperfine go/out 'node javascript/main.js' rust/target/release/rust 1 Benchmark #1: go/out

        Time (mean ± σ):      1.888 s ±  0.013 s    [User: 2.040 s, System: 0.045 s]
      
        Range (min … max):    1.875 s …  1.918 s    10 runs
      
      Benchmark #2: node javascript/main.js

        Time (mean ± σ):      4.257 s ±  0.033 s    [User: 4.295 s, System: 0.042 s]
      
        Range (min … max):    4.221 s …  4.338 s    10 runs
      
      Benchmark #3: rust/target/release/rust

        Time (mean ± σ):     874.1 ms ±  50.8 ms    [User: 5.688 s, System: 0.830 s]
      
        Range (min … max):   813.5 ms … 1001.9 ms    10 runs
      
      Summary

        'rust/target/release/rust' ran
      
          2.16 ± 0.13 times faster than 'go/out'
      
          4.87 ± 0.29 times faster than 'node javascript/main.js'
  • GolDDranks 6 years ago

    Rust is usually faster than Go. Note the edit in the previous post.

  • empath75 6 years ago

    As someone who is not a particularly good programmer who has done quite a bit of coding in both at this point, it seems to be easier to accidentally write extremely slow code in rust than it is in go, but once you start optimizing, rust will generally be faster, sometimes by quite a lot. I’ve also run into fewer pathological cases as I’ve learned more of the idiomatic rust patterns.

    • jdub 6 years ago

      And yet, a lot of experienced programmers have noted that even when they write their first time naïve Rust, it turns out to be really fast.

    • aliceryhl 6 years ago

      I have the opposite feeling. Every time I do something that could be expensive or incorrect, the language makes sure that I notice, which I find extremely helpful in writing fast code the first time around.

    • rat9988 6 years ago

      >it seems to be easier to accidentally write extremely slow code in rust than it is in go

      Never felt about it this way.

      • baq 6 years ago

        likely depends on your background; if you come from GC languages and are used to everything-is-a-reference, you might end up surprised that Copy types are a thing. right after that you might want to box everything so .clone() works everywhere when you find that some types aren't Copy.

        • empath75 6 years ago

          Yeah it’s definitely around using clones everywhere.

          • masklinn 6 years ago

            I don't know that clones are problems in and of themselves rather than what they do behind the scenes: allocations. Cloning an Rc is completely innocent, cloning a HashMap<String, Vec<String>> is deadly in a way you may not expect if you're used to shallow-copying hashmaps (or even deep-copying them).

            And it's true that if you think of allocations as being no big deal unless you're aiming for very high performance, your Rust is going to be slow (also your C++ and your C).

Keyboard Shortcuts

j
Next item
k
Previous item
o / Enter
Open selected item
?
Show this help
Esc
Close modal / clear selection