HN user

floofy222

51 karma
Posts0
Comments22
View on HN
No posts found.
Rust Cookbook 7 years ago

I feel that the quality of auto-generated docs is generally better for Rust than for other languages like C++ (e.g. via doxygen). This is because the tools make it trival to publish and distribute docs for your crate, and people make use of that because it is so easy.

Obviously, these tools don't solve the problem for you. In the same way that some C++ projects use doxygen without writing doc comments and say "but we have auto-docs!", some Rust projects (the rust compiler libraries and official projects, e.g., cargo, libsyntax, etc.) almost completely lack API docs. They do have books (rustc book and implementors guide, cargo book, etc.) so it isn't that they are completely undocumented, but if you want to use these as libraries, the auto-generated API docs are useless.

Usually these inform tools that can be used to detect rule violations.

For example, the rust constant evaluator can execute almost all Rust at run-time except for FFI. This allows you to write `cargo miri test` in your project, and run your unit tests in the constant evaluator.

The constant evaluator executes the program based on rules given by models like this, and if you perform an action that violates one of the rules, they report an error.

For example, this program mutates a variable while a shared borrow (which excludes mutation) is alive via a raw pointer

    fn main() {
        let mut a = 13;
        let b = &a;
        let c = b as *const _ as *mut _;
        unsafe { *c = 42; }
        println!("b = {}", b);
    }

On the playground it prints "b = 42" (https://play.rust-lang.org/?version=stable&mode=debug&editio...).

The playground has a `Tools` button, that allows you to run the program under `miri` (the constant evaluator). When doing so, it prints:

    error[E0080]: constant evaluation error: borrow being 
    accessed (Alias(None)) does not exist on the borrow stack
     --> src/main.rs:5:14
      |
    5 |     unsafe { *c = 42; }
      |              ^^^^^^^ borrow being accessed 
    (Alias(None)) does not exist on the borrow stack
    
    error: aborting due to previous error
The error messages of the constant evaluator aren't great yet, but that basically tells you that it couldn't find a suitable mutable borrow to mutate the variable, so the access is undefined behavior.

We’ve had 2786 distinct people contribute. And that’s only to rust-lang/rust; not Cargo, not any of the libraries the team maintains, not any of the other kinds of work that doesn’t produce a commit.

To put this into more context: a lot of the code shipped with the Rust toolchain does not live in rust-lang/rust.

Some parts of the standard library (HashMap, HashSet, C FFI, intrinsics, etc.) are used as dependencies. All of the tools (the linter, language server, rustfmt, rustup, cargo, etc.) are dependencies. Many compiler components like miri (constant evaluator), chalk (type queries), polonius (borrow checking), etc. are also dependencies. The Cranelift code generation backend can be dynamically used and does not live in rust-lang/rust, etc. Then there is the RFC repository, and probably other things.

Counting contributors for such a distributed infrastructure isn't easy, but the number of contributors to rust-lang/rust isn't super meaningful.

One might be able to do better by finding commits to rust-lang/rust that update "Rust" submodules (e.g. not LLVM), and adding the contributors to those repos from the last update. One might also want to find commits that update versions of rust-lang/rust dependencies, and for those that live in the rust project (or that have dependencies there), count the contributors from the last version, etc.

The Rust project has seen significant modularization over the last couple of years, and the more modular it gets, the less meaningful "contributors to rust-lang/rust" becomes, and the less accurate the "Thanks!" pages of each release become.

What is to stop them from lying?

Nothing, at the end of the day, whether giving someone else your data is a good idea or not remains a question of trust.

Do you trust them to stop updating the canary in case they become compromised?

If the answer is no, then you probably shouldn't be giving them valuable data.

To make the path stop resolving, you'd have to perform an action (update the server, etc.).

These canaries are not automatically updated: they are manually updated (that's the whole point).

If you receive a gag order you just do nothing.

Stuff that’s unstable isn’t in Rust; that’s why it can be changed or even wholesale removed at any time. The distinction is very important.

I've seen you talk about "writing an OS kernel in Rust", but never heard you phrase that as "writing an OS in kernel in _unstable_ Rust". I've never seen you stating: "correction: what you are using for embedded development, networking, etc. is not Rust, _but unstable Rust_" on any of the many blog posts, announcements, news, etc. about these topics over the past couple of years. I've seen you reply with that argument every now and then, when someone like me downplays the importance of the distinction, but I've never seen you address the source of that behavior.

If the distinction between Rust, and unstable Rust, is important. Why are the people at the top not making it? If you are working on the compiler, servo, etc. you are actually not programming in Rust, but in _unstable_ Rust all of the time. Are they hypocrites? I don't think so.

If I reflect on why I feel that this distinction is not important, the first thing I realize is that I do think the distinction is important. But this distinction is not binary _to me_, as opposed to how you and burntsushi are putting it.

As you mentioned, some unstable features change more than others. There is a wide range of how much continues breakage does using certain unstable features cause downstream users. Some features break every day, some features haven't broken anything in 3 years.

Are unstable features that haven't broken anything in 3 years stable? No, by definition, they aren't.

Are they practical to use? The answer isn't yes or no, the answer is "depends on how much breakage you are willing to accept". We upgrade C++ compiler ~twice per year, and even though we only write 100% standard compliant code, we have to always fix breakage due to the upgrade. Yet I wouldn't say that standard compliant C++ is an unstable programming language.

So, if consider bi-yearly breakage is stable enough for our professional C++ projects in practice, why would I judge Rust stable / unstable features using a different bar? This does not mean that I believe that using unstable (or only stable) features will never cause breakage, since that is impossible.

I've had stable Rust CI jobs break because the standard library added some new trait method, and that caused an ambiguity that broke in my stable Rust code. The answer was: your code was correct, but we are allowed to break it in this way.

In my opinion, it is not "stable vs unstable", but 99% vs what degree of stability does your project need, where choosing more stability than what it needs puts it at a technical disadvantage. It doesn't matter whether one is talking here about Rust unstable features, or using the super unstable next-gen stable Rust web framework.

The stability line does not lie where I or anybody else decides to arbitrarily put it. It lies exactly on the amount of stability that a particular project can tolerate, and it is up to the judgement of the developers of that particular project to find out where that is.

Telling someone that a particular project is not Rust because the stability line for that project does not fall where your line does feels just wrong. Particularly when those doing it don't make that distinctions about themselves and the projects their work on.

Most programming languages don't have a stable / unstable distinction at all, and unless one is "in the Rust loop", stating something like "_unstable_ Rust can do X" won't probably mean what the reader think it means.

Unstable Rust sounds very dangerous, like something that breaks every day. Definitely more dangerous than stable Rust.

Yet if one is in the Rust loop, one knows that this is often not the case. I've been using some unstable features on nightly, like const fn, specialization, function traits, etc. for years (3 years?), and I've never had a CI build job fail due to a change to the implementation of these features.

Yet some features in stable Rust like Rust2018 uniform_paths or stable SIMD have caused many build job breaks and undefined behavior due to bugs in the compiler over the last months.

So whatever stability means, it does not mean "using this feature won't result in your code not breaking". It also doesn't mean "you have to use a nightly toolchain to use the feature".

An unstable Rust feature is more like a "compiler extension" in C / C++. It is just something that hasn't fully gone through the process of standardization.

I don't think it is a fair characterization that code that uses this extensions is not Rust. Pretty much all C++ code uses compiler extensions, and nobody says that this code is not C++ just because it uses one of them.

Explaining all of this when telling someone "Rust is a technology that allows you to solve problem X nicely" isn't helpful.

Many people vocal about Rust seem to think that Rust is the end in of itself. The goal isn't solving a problem, but using Rust to solve it. I see many of these people argue that unstable Rust isn't Rust, and that people should be using stable Rust etc. For most people, using Rust isn't the goal, solving their problem is. Whether one or many compiler extensions have to be enabled for that is pretty much irrelevant to them. Sure it would be nice if one didn't need to do that, but it isn't a big deal either. The big embedded community is living proof of that. Only a small minority of this community cares about the language enough to participate in its evolution. Most people don't care enough about that, they have more interesting problems to solve.

If they want to squeeze out the last ounce of performance out of the Rust toolchain it probably wouldn't make sense to use stable Rust anyways, so I don't think that's a big downside.

Also, they are already relying on "unstable" (non-standard conforming) C++ features (e.g. the code uses non-standard attributes behind macros, etc.). Using nightly Rust isn't worse than that per se.

Using Rust does have downsides. For the type of code they are writing, the main downside would probably be losing an alternative GCC backend, which might or might not be better than LLVM for their application.

Still, they would win portable SIMD and being able to target not only x86_64 but also ARM, Power, RISCV, WASM, etc., which is always cool to show in research papers.

I'm not suggesting that Rust is a perfect trade-off, only that it's an interesting one depending on what they want to do.

I see that you are using MMX intrinsics directly, like _mm_sub_pi8, but you are never calling _mm_empty (https://software.intel.com/sites/landingpage/IntrinsicsGuide...) as required by the SysV AMD64 ABI (and pretty much all other ABIs out there).

I think the behavior of all the code that touches is undefined (it breaks the calling convention of the ABI), and while this often results in corrupted floating point values in registers, maybe you won't see much if you are not using the FPU. Still, since the function is inline, chances that this gets inlined somewhere where it could cause trouble seem high.

You might want to look into that.

Also, I wish this would all be written in Rust, there is great portable SIMD support over there. Might make your life easier trying to target other platforms.

EDIT: as burntsushi mentions below, that's not available in stable Rust, but if you want to squeeze out the last once of performance out of the Rust compiler, chances are you won't be using that anyways.

Following local news right now it seems people aren't even capable of "Rettungsgasse" (leaving a corridor for emergency vehicle access in traffic jams) anymore

The problem with the Rettungsgasse is that you only need one idiot to screw it up, but you often get many.

When I enter a traffic jam, I see most cars building it properly, but then I see one or two cars ignoring all others. I can understand that people might forget about it right when they arrive at the traffic jam, but once everybody arounds you do it, some just don't seem to get what's going on.

In other countries, like Austria, the Rettungsgasse is formed on the rightmost lanes, while in Germany, its on the left most lanes. Disparity of rules across EU countries doesn't help here either.

Also, for some reason, once the first police car goes through the Rettungsgasse, I often see many cars that just stop building it. Like "good job everybody, the police went through, we don't need the Rettungsgasse anymore!" even though there is still a jam. The ambulance comes 1-2 minutes later, and it has to fight its way through because of all these idiots.

In Germany the problem with the idiots is particularly bad, because while there are a lot of German idiots on the road, you also get a lot of international traffic with their international idiots on the Autobahn. If you learned to drive in a different country, chances are that you haven't even heard about this, and learning about all the different traffic rules of all the countries you drive through is a PITA.

t's totally OK however to not let into the lane people who're using an empty lane on purpose to pass by others and jump the queue

In Germany, this behavior is explicitly forbidden by the law.

If there is a merge, one car of each lane has to go through the merge each time.

That is, if you are at the end of the lane that gets merged, and you let one car pass, then you have the right to go and merge next. The next car in the other lane must yield, if they don't and there is a crash, it's 100% their fault.

This is so that the lanes that merge get used to their maximum capacity. If the intent were for cars to merge earlier, they would just have made these lanes shorter.

The #[rustc_layout_scalar_valid_range_start(...)] and #[rustc_layout_scalar_valid_range_end(...)] attribute allows you to specify a niche, so you can build a Non255U8 if you want. For example:

#[rustc_layout_scalar_valid_range_end(254)] struct Non255U8(u8);

I can totally relate here. I remember that when I started running, "it's too cold", "it's too windy", "it's too dark", etc. were real issues. It was too dark and I didn't had enough experience running in the dark, and for me it was indeed too cold. If one can afford the equipment, good equipment does reduce many issues and if that means that you'll go running more for me it was money well spent.

After a few years as I had more experience, ran faster (and warmer), these issues mostly disappeared. Nowadays on winter I only run with shorts, a thin hard-shell, and thin shoes (sometimes five-fingers) with temps of -5C. Some days get much colder (e.g. -10 or -15 C) but when I've used some of the warm clothes I used in the first couple of years of running they've always felt too warm. The only thing that's still an issue is running in the dark. Independently of whether I know the trail, have a head-lamp, etc. I run slower in the dark than during the day, except on the track. So now when its dark, I always go to a running track to run. Most of them have lights on till late, and some schools, most universities, etc. have one and they let you use it for free.

You don't have to pay 100$ to run a marathon. If you have a pair of running shoes and a normal running belt (for water and a gel) that will do. You just have to put them on and there you go. I've done a couple of "Sunday marathons" (aka "long aerobic run") with two friends. They have costed me ~2$ for a gel.

Equipment wise, you don't need to pay 100$ for shoes. There are many <300$ shoes from the last season (last year model) on discount pretty much all year round for 60$-80$. I burn 3 pairs of shoes a year, and even though I could afford expensive shoes, I pretty much always end up finding the ones I want for 70$ somewhere online.

Running belts price varies (from $10 to "as much as you want to pay"), but they are a one time investment. I bought a nice neopren one once, and it will probably outlive my children. If you are running enough to be able to "just go and run a marathon", chances are that you already have a running belt to carry a mobile phone, keys, id, money, gels, water, etc. They are just insanely useful.

I run around 8 hours / week, and my expenses are around 300$ per year. Some years I've paid a bit more, e.g. got a heart rate monitor for 30$, running ear phones for 80$, headlight ~20$, I don't have a running watch yet.., nice running shorts and shirts (couple of 100$s), etc. I've also gone to some races, but I've never paid more than 15-20$ for them. You can do half-marathons and marathons for that money, and some of them are non-profit, so you could deduce that from your taxes if it was worth your time. Also, most races typically give you running tshirts, gloves, and what not as a "finisher" gift.

Honestly, factoring the time I've spent running during my lifetime, and the money I've spent over the last 10 years, it's by far the cheapest hobby I have.

EDIT: That might be a lie. My absolute cheapest hobby is actually swimming. Swim shorts for 20-30$, swim googles for 5-10$, and an annual membership on a masters team (120$/year for 6h of swimming / week, where I only actually end up using 2-4 h). Swim short and googles need replacing only every couple of years, so swimming costs me around 150$/year for about half or a quarter of the hours I spend running / week.

Swimming and running, compared with my other hobbies, are negligibly cheap. I go snowboarding for 2 weeks a year, and that cost me ~2000$ + maintaining my equipment (I basically end up spending ~300-600$ on snowboarding equipment / year). I go cycling with my gf every now and then but not enough to make a 2000$ road bike + equipment cheap. And well I have a motorbike because I want to and that also costs multiple 1000$s dollars per year, I don't even want to know how much.

So yeah, swimming, running, calisthenics, etc. are damn cheap sports. You don't need to spend 1000$s/year on these. If you are tight on money you can probably manage 20h of fun per week by spending ~300$ per year without issues. Obviously, if you want 1-on-1 crossfit training wearing fashionable clothes wearing a go pro and drinking avocado toast kale smoothies you are going to end up paying a lot, but that's not necessary at all.

I just think these captchas are broken in Chrome.

Sometimes I use one of these operators by mistake and get instantaneously hellbanned from using google. The first time the captchas kept reappearing a whole day. I read somewhere that the ban is resetted the next day, but the next day I was still getting the captchas and couldn't use google for anything.

I deleted all cookies and suddenly I wasn't banned anymore. So this looks to me like a captcha bug, or a chrome bug, or both. Probably both.

Living in Germany, nobody here cares about Brexit. They don't show it in the news much. General opinion across my circles is that the UK should do whatever they want (leave or stay), but that they should stop wasting EU's politician's time with it.

So no, Germans at least are not worried about no deal. I don't think anyone talks much about Brexit in the EU, except for Britain. I don't think anyone is worried at all.

In all fairness, why would anyone outside of Britain even care ? Whether Britain wants to stay or leave the EU with or without a deal is entirely up to them. The rest of the EU or the world doesn't (and shouldn't have) any kind of say on that.

The amount of food the UK imports from the EU is irrelevant, the relevant question is how much food does the UK import ?

This is because, as an EU member, the UK has trade agreements with many countries outside of the EU. After a no deal Brexit, it has none. This affects all UK imports and exports.