Rust beginner notes & questions

I suspected you wouldn’t respect my request. I know this is the Internet, and that’s why it was a request. I wish your restructuring project wasn’t more important to you than the people whose words you’re restructuring.

That’s my last say on the topic. I will be participating much less.


I understand your concern with pulling out the discussions into separate threads as was done and in particular the unstructured and out-of-context way that it was done, but, I would hope that you would not permit someone else’s less than stellar judgement discouraging you from participating fully in future discussions.

Personally, I do not find this response to the concern expressed by @gilrain to be at all appropriate or fair. Might I suggest that you reconsider how you might have handled this in a more constructive fashion? At times, we all must introspect a little and ensure that we are not being that thing we are ostensibly against.


This thread is getting very close, if not already there, of going off into yet another off-topic quasi-sensitive subject. Can we please just let it die at this point? I don’t think we need more meta discussions here.


Yep. Please private message me if anyone wants to discuss further with me. Moving to private messages can be a good way to diffuse a discussion in general as well.

I’m late to this post. I tried to avoid it, but please excuse me if I’m repeating anything someone has already said. I also don’t have the time to split it up into the subtopics that were created… but here goes…

Rust is constantly developing and improving; I highly recommend taking all concrete suggestions you have to and we can flesh them out collaboratively.

I would say: Refactoring. If you have 20 common members it is a good sign that you need some more type hierarchies.

We are also currently contemplating various mechanisms for delegation to make life easier.

Rust does that; it is mostly based on region typing (or uniqueness typing). There’s also concurrent separation logic. The trait system + type parameters amount to the usual Bounded parametric polymorphism (a la System F and friends).

At least where the compiler and language teams are concerned I wouldn’t say that this is true. There’s a healthy mix of course, but what you will find is that there is much more familiarity with various functional languages (such as Haskell, Scala, Agda, …) than in the community at large. Even if these languages are not used frequently by team members, many lang team members read papers and such. This is not to say that there isn’t familiarity with C++. There is! But it is not as overwhelming as you might think.

So the following:

is very much true. I’m just a lang team shepherd, but I do consider myself proficient at Haskell :slight_smile: and not at all proficient at C++.

and I would further say that given many of the pending (RFC accepted and in nightly…) and recent additions, it is diverging from C++ becoming less like it.

There NLL and theory is concerned, there’s at least
For more theory in general, have a look at

Sure; We are adding more and more stuff from itertools over time, but unfortunately, adding things over from itertools with the same name can cause breakage, so we have to do it cautiously. Going forward, many additions to Itertools should probably be suggested for inclusion to libstd first.

It can be provided as a library type. Essentially:

struct Frozen<T>(T);

unsafe trait NoInteriorMutability {}
// implementations thereof...

impl<T> Frozen<T> {
    fn new(x: T) -> Self { Self(x) }

impl<T> Deref for Frozen<T>
    T: NoInteriorMutability // Remove this bound if we tolerate interior mutability.
    type Target = T;
    fn deref(&self) -> &Self::Target { &self.0 }

This gives you immutable access to the inner T without being able to mutate it, even if Frozen<T> is moved. Whether this is useful is another matter and remains to be seen, but it is certainly possible to encode.

See for discussion on do while .... I personally like the clarity of loop { .. }.

It is the same in language design. You can write up and incredibly simple typed lambda calculus in an hour, but it will not be expressive enough. We want a simple language, but also a flexible and expressive language. These goals are at odds and it takes a lot of ingenuity to maximize both. Practical general purpose languages also face various edge cases (like union and FFI) that you need to deal with. Meeting these needs often add things that can feel inconsistent or complex. We try as best we can in the design of Rust to keep things simple yet expressive by applying design uniformly.

Predicting things takes time to sit down and do the predicting. Sometimes you just don’t have the time. :wink: You also have to consider that people disagree on what are mistakes and what are not. Inevitably, according to someone’s tastes mistakes will be made. For example, there are plenty of mistakes in the Prelude module of Haskell which the Haskell community has to live with now. This is not to say that we should be lax; but we also have to ship at some point.

Also consider that plenty of language features that would improve libraries considerably haven’t been implemented yet (because it takes time and because the design hadn’t been agreed upon yet). For example, given const generics and tuple variadics, we can eliminate a tonne of macros for implementing traits on arrays and tuples. Fortunately, a lot of improvements are in the pipeline.

This needs to be graffitied on every wall, printed on every t-shirt, reproduced in pamphlets and widely distributed everywhere. I haven’t written C++ for a long time, but I could only imagine how anxious I would be if I didn’t have an actual machine checked guarantee that the borrows are alright.

I can’t say I agree with this; But then, any object oriented language with class based subtyping is less consistent to me than what you get in most functional programming languages. That said, systems programming inevitably leads to complexities that a language like Haskell doesn’t have to deal with.
For example, what is typically a type in Haskell (like A -> B and [A]) are typically made into traits in Rust to achieve maximal performance (Fn(A) -> B and Iterator<Item = A>). Lifetimes themselves and region-typing are also a source of duplication and having to have more types (a borrowed version, and an owned one…). Hopefully GATs will improve on some of this.

For me personally, the high bar to aim for is Haskell; It’s an incredibly well designed language in my view and probably the best language for general purpose programming if you are in a position to accept a GC. In my view, it is only surpassed by the likes of Agda et al. but those are not mature or general enough for day to day programming. The major drawback of Haskell is the lack of documentation due to the academic nature of the community, but that could certainly be fixed without breaking things, but it takes effort.

Rust owes, and has paid, a great deal of gratitude towards Haskell and ML and these languages have made enormous contributions in all sorts of languages.

There’s a famous joke that I find pretty funny about C#…

1996 - James Gosling invents Java. Java is a relatively verbose, garbage collected, class based, statically typed, single dispatch, object oriented language with single implementation inheritance and multiple interface inheritance. Sun loudly heralds Java’s novelty.

2001 - Anders Hejlsberg invents C#. C# is a relatively verbose, garbage collected, class based, statically typed, single dispatch, object oriented language with single implementation inheritance and multiple interface inheritance. Microsoft loudly heralds C#'s novelty.

Sadly, the post lacks an item for Rust ^,-

You should consider that some library features are designed and stabilized before some language features that would have made it better existed. For example, once we get GATs, we would really like the Item associated type to be generic over a lifetime 'a, but we can’t, due to backwards-compatibility concerns.

This is also at odds with having a larger standard library. While the language is not as expressive as it could be, it is a good idea to iterate on things in crates and only standardize them in libstd once all language features that are needed are present.

Does this qualify to some degree?

This is solvable with tooling; for example, we could possible give a static guarantee that crate X in your chain of dependencies (and all of its transitive depends) have zero cases of unsafe, impure, panicing, and non-terminating code. So we could give you a guarantee that all code is safe, pure, and terminating. Prior art exists in this space, but we need to agree on a design (make an RFC…).

Sometimes it is, sometimes it’s not. In particular, some branches of Computer Science (Theoretical CS) is really a branch of mathematics, and sometimes you could even call Mathematics a branch of Computer Science. What you can do in mathematics/CS is to state some theorem (such as soundness according to some safety condition in your system) and then prove it. Proving that soundness holds is then good, and proving unsoundness is bad. Of course, keeping the system sound must be contrasted with the cost to expressivity, simplicity, etc. The safety condition may also be too lax or too strict. These bits require value judgements, but we can still determine some (but not all) objective truths.

I also want to distinguish between Computer Science, Software Engineering, and Computer Engineering where CS is typically more the theoretical, abstract and does not concern itself with people (organization) or computer architecture and such things.

In any case, even when we have machine checked proofs, we should still be humble and be precise about what is proven and not make overly general claims about systems. The CoC is a great thing.

PS: I hope I didn’t say Haskell too many times :stuck_out_tongue:


That’s just for you and few other persons. For most people that’s not true at all.


Let’s not ascribe things to what “most” people do and do not think. I venture a guess that most programmers have not tried Haskell and so they have nothing to base opinions on the well-designedness and greatness of Haskell either in the positive or the negative.

Most Haskell programmers I’ve met are pretty happy with the language tho. It is often an eye-opener for students at the university where I study to learn the language (as it was for me). So it seems to me beneficial to learn both a strict imperative language with side-effects everywhere and a pure lazy functional language. Then you have experienced both ends and you’ll likely be better for it. I also want to be clear that my love for Haskell and belief that it is a well designed language is my subjective personal view and in no way is it universal.

What is true in any case is that a multitude of languages, including Java, C#, Python, Elm, and in particular Rust has learned a lot from Haskell (and I expect more to be adapted over time). Plenty of invaluable results have also been provided through the PLT research done in association with developing the language.


This seems pretty far off topic.

I think this is the crux of it. C++ is a machine gun with no safety that people wave around in a terrifying fashion. Rust to me feels like a machine gun with a safety installed, but I see a bunch of people walking around with the safety off. I see too many uses of panic! and unsafe, and not enough mechanical means to ensure safety.

There’s no equivalent of the grumpy sergeant taking everybody’s clips away from them when they return to base. Nobody likes the sergeant, he’s no fun, but it just takes one crazy person on the base to make it abundantly clear that he’s necessary. In my analogy, the lack of any serious security enforcement or trust tracking in cargo / is the missing sergeant. Right now the package ecosystem is like having a buddy at the gate waving you through with a fully loaded weapon. That’s fine until it… isn’t.

The main issue with Haskell that’s a roadblock to its widespread adoption is that it is very difficult to reason about its runtime performance. I vividly remember struggling to make performant Haskell code that would have been trivial to write in plain C and would have run 50x faster. I heard a quote about this recently: “Functional programming makes difficult things easy, but easy things difficult.”

I’m having trouble finding the link at the moment, but I read a great paper that pointed out that this cute little code snippet that’s popularly used to demonstrate how elegant Haskell is doesn’t actually implement quicksort because its runtime performance is O(n^2):

quicksort [] = []
quicksort (p:xs) = (quicksort lesser) ++ [p] ++ (quicksort greater)
        lesser = filter (< p) xs
        greater = filter (>= p) xs

Properly implementing quicksort in Haskell is obscenely difficult:

[Moderator note: No, we are not going to start a whole discussion about Haskell here.]


But panicking isn’t unsafe in the machine-gun sense.

You may be right that unsafe is overused.


Yes. This is a reason why others prefer OCaml. Example:

1 Like

I think it’s critical not to conflate those two things.

It’s absolutely essentially that unsafe usage be thought through carefully. But liberal panic!ing should be encouraged, for conditions not yet handled, so long as it’s not ignored by catch_panic.

Outside of rust, I’ve seen use of a “crash if this condition isn’t true” macro substantially increase the reliability of a product. It lets to more failures in test, but that’s good: you get a nice crash dump showing the situation you hit, and you go write code to handle that now that you know what it needs to do. That’s way better than muddling along in a situation you don’t really know how to handle, or having a bunch of code that you speculatively wrote and might not actually be reachable.


Come on. Please reduce your hyperbole. It’s not that bad.

Can we please just close this discussion? We already have sub-topics for pretty much everything. I feel like this discussion is getting nowhere.

It’s absolutely essentially that unsafe usage be thought through
carefully. But liberal panic!ing should be encouraged, for conditions
not yet handled, so long as it’s not ignored by catch_panic.

I wish to respectfully disagree. For some use cases (example in mind:
embedded systems, a target Rust explicitly supports), a panic! may mean
deaths (OK so now I’m hyperboling too).

I’ve seriously thought of trying to do a “rust without panic,” but it
turns out that’s really hard to do, given even slices have the panicking
behaviour hardcoded. So I’d have had to wrap slices into a custom type…
and then things start being hard.

I guess what I’d love is an effect system “this function can panic” (or
actually rather “this function cannot panic” for backwards-compatibility
reasons) that could use catch_panic to transform panick’s enforced by
the language into Err(_) and to make the effect “vanish.”

1 Like

“safety” in Rust means “memory safety”. panic is memory safe. Code that is memory safe can still have other kinds of bugs.


“safety” in Rust means “memory safety”. panic is memory safe. Code
that is memory safe can still have other kinds of bugs.

Indeed, I’m not arguing @peter_bertok used the right Rust-y jargon, just
that there are real-world cases for wanting code that could provably not
panic :slight_smile:


  1. the computerized steering and braking systems in your autonomous car,
  2. the engine controls on a commercial airline that prevents turbine overspeed that can cause turbine blades to detach and slice through the fuselage.

Yes, this discussion is alternately going in circles or veering off-topic, so I’m closing this thread.

As a general note to everyone, please keep in mind that not every comment needs to be replied to. I think we need to get better at stating our cases and then not repeating ourselves, and at refraining from continuing off-topic or inappropriate discussions.

Update: An additional follow-up thread: Effect system for panics and transitive unsafe