Rustacean Principles

Dancing Ferris

A DRAFT set of principles guiding Rust development and its open source organization.

What is Rust?

  • A language empowering everyone to build reliable and efficient software.
  • An open-source community focused on creating, designing, and maintaining that language and its ecosystem.

What are the Rustacean Principles?

The Rustacean principles are a set of principles which guide us in building Rust. They begin with a description of how Rust empowers its users. This section describes the various goals that we shoot for when designing elements of Rust.

Rust is developed and maintained by the members of its various teams. The next section of this site, How to Rustacean, is a guide for the ways that members of those teams are expected to act. You can think of it like a companion to the Code of Conduct: whereas the CoC describes the bare minimum expected of any Rust participant, the How to Rustacean section describes what is means to excel.

Finally, the case studies section applies both the previous sections to various examples from Rust's history, and shows how the principles can help guide us.

How can the principles be used?

For the principles to be a success, they need to be more than words on a website. The hope is that they will become something that we actively reference all the time as we go about our work in the Rust org.

As an example, when working through a design tradeoff, it may be helpful to see whether you can phrase the underlying values in terms of named values like [productivity] or [transparency]. The ordering and prioritization may help in resolving the tradeoff. We can also rate designs along these axes, which may help spur useful ideas for how designs can be improved.

When it comes to the How to Rustacean section, it's a great guide that we can all use for ourselves. It's also a good idea to look for opportunities to point out when people are doing a good job -- e.g., "great job paying it forward". The principles can also be useful when thinking about prospective members of a team. Can you come up with concrete examples where they exemplified these principles? What about places where they fell short? The principles can be a useful tool for communicating this to people without it feeling like personal criticism.

Rust empowers by being...

Rust's overall goal is to "empower everyone to build reliable and efficient software". But how do we do that? This section identifies the various things that Rust tries to be in order to empower its users. If you click on a particular entry, you will find more notes, along with a list of mechanisms that we use (for example, reliability is enhanced by type safety).

Note that these goals are often in tension. For any given design, we always want to achieve (or at least be neutral) all of these feelings. In some cases, though, we may be forced to decide between slightly penalizing one goal or another. In that case, we tend to support those goals that come earlier in the list over those that come later (but every case is different). See the case studies for examples.

βš™οΈ Reliable: "if it compiles, it works"

One of the great things about Rust is the feeling of "it if compiles, it works". This is what allows you to do a giant refactoring and find that the code runs on the first try. It is what lets you deploy code that uses parallelism or other fancy features without exhausting fuzz testing and worry about every possible corner case.

🐎 Performant: "idiomatic code runs efficiently"

In Rust, the fastest code is often the most high-level: convenient features like closures, iterators, or async-await map down to code that is at once efficient and which uses minimal memory.

πŸ₯° Supportive: "the language, tools, and community are here to help"

We strive to make our tools polished and friendly, and we look for every opportunity to guide people towards success. Part of that is building a community that eagerly shares its knowledge in a welcoming and inclusive way.

🧩 Productive: "a little effort does a lot of work"

Rust and its ecosystem offer a wide array of powerful building blocks that can be combined and recombined. The result is that standing up a quality system can be done in record time.

πŸ”§ Transparent: "you can predict and control low-level details"

The translation from Rust to underlying machine code is straightforward and predictable. If needed, you have options to control the low-level details of how your application works.

🀸 Versatile: "you can do anything with Rust"

Rust scales well both up and down: it is well-suited to building everything from simple scripts to web servers to WebAssembly programs to kernel extensions and embedded systems. It is usable on both common and esoteric platforms.

βš™οΈ Reliable: "If it compiles, it works"

One of the great things about Rust is the feeling of "if it compiles, it works". This is what allows you to do a giant refactoring and find that the code runs on the first try. It is what lets you deploy code that uses parallelism or other fancy features without exhausting fuzz testing and worry about every possible corner case.

In tension with

Making Rust reliable is most often at odds with making Rust feel productive and supportive. Reliability is often achieved by "cross checking", where various parts of the system check one another to ensure overall consistency. Cross checks can make it harder to make changes, since the various parts of the system must be brought in sync with one another.

Reliability can also be at odds with versatility. Our ability to make something reliable will always be limited. If we restrict people to only building things that whose correctness can be verified, we will limit what they can build.

Mechanisms

What are some of the ways that we make Rust feel reliable?

Type safety

Safe Rust code is guaranteed to avoid undefined behavior.

Rust programmers never have to worry about notorious, hard-to-diagnose, harder-to-fix bugs like segfaults and data races. Rust's exposure to security vulnerabilities is much reduced as a result. However, static safety comes at the cost of increased overall complexity (works against supportive). Figuring out the correct type annotations and other details can be difficult, working against productivity.

Consider all cases

Rust doesn't hide error conditions and encourages listing all possibilities explicitly (or acknowledging that something is elided).

Rust uses a number of mechanisms to encourage code authors to list all possibilities. This thoroughness frequently helps identify bugs because it can highlight things that the programmer has forgotten about. However, it comes at a price in productivity, since it can force the programmer to deal with details that they haven't figure out yet. As an example, consider exhaustive matches: they are frequently very useful, but when a new enum variant is added, all matches must be edited to account for it (or else they must include a _ case).

Type safety (but with an unsafe escape hatch)

Safe Rust code is guaranteed to avoid undefined behavior.

Type safety is a key element to reliability. We ensure that safe Rust code is free of "undefined behavior", which is the term that compiler authors use to refer to things like segfaults, data races, and out-of-bounds memory accesses.

Type safety is not a suggestion: we don't accept almost safe APIs, which are safe so long as you don't do "unreasonable" things. For example, we would not accept a safe API that avoids undefined behavior so long as no cycles exist between ref-counted objects. Reasonable people do "unreasonable" things in code all the time, either because they don't yet know what is reasonable or not, or because the complexity of the system gets away from them. The role of the compiler is to manage that for you.

However, type safety carries a cost, too. It adds complexity, which can work against Rust feeling [productive]. It also makes Rust more complex and hard to learn, which can work against feeling [supportive] -- we work hard on our error messages and documentation precisely to help mitigate this cost. Precisely because of these costs, we have imposed some limits on what Rust's type system tries to achieve:

  • We employ runtime checks for certain kinds of error conditions. For example, we do not try to prove that indexes are within bounds, but instead check an expression like vec[i] to ensure that i < vec.len(). Proving conditions about the specific value of a variable (in this case, i or the length of a vector) would be a "big step up" in complexity of the type system. Rust's choice not to do so decreases that feeling of reliability, but with massive benefits to [productivity].
  • We permit unsafe code, which gives authors an escape hatch from the type system. This means that we can support many kinds of systems programming patterns while keeping the type system itself relatively simple. (For example, the system of ownership and borrowing cannot express doubly linked lists, but they can be implemented with unsafe code.)
    • However, we do expect authors to encapsulate their unsafe code, presenting a safe interface to the world at large. This works against the feeling of [productivity] for unsafe code authors (it's more complex to think about how to encapsulate things) but with great benefits for reliability for the rest of the world.

Consider all cases

Rust doesn't hide error conditions and encourages listing all possibilities explicitly (or acknowledging that something is elided).

Rust generally aims to make sure that you 'acknowledge' or consider all cases. You can see this in match statements, which require exhaustive matching (many other languages permit you to leave off match arms that you believe cannot occur); when matching, we also require that users list all fields in a struct, or acknowledge (with ..) that they have not done so. Forcing users to consider all cases helps make Rust feel reliable, but it can come at the cost of feeling [productive]. This is why we frequently pay careful attention to the details of

A good case study for the tradeoffs involved is error handling. The traditional approach to error handling for a long time was exceptions. Exceptions are great for feeling [productive], as they allow errors to quietly pass through any amount of code. However, the result is a proliferation of hidden control-flow paths that are very hard to reason about. In practice, recovering from exceptions is fraught with error, and hence they work against the feeling of reliability. The problem is that typical mechanisms such as returning an error code are also not reliable; it's too easy to forget to check for an error.

Rust instead adopts the approach pioneered in functional languages of returning an enum. The Result enum allows one to signal an error in a way that forces the error to be considered. Still, the most common way to handle an error is to propagate it to your caller, and in order to feel productive, it's important that this operation be concise. Rust's ? operator was added to restore productivity while ensuring that error paths are still visible to users and are not completely overlooked.

πŸ‡ Performant: "idiomatic code runs efficiently"

In Rust, the fastest code is often the most high-level: convenient features like closures, iterators, or async-await map down to code that is at once efficient and which uses minimal memory.

In tension with

Making Rust feel performant can be in tension with Rust feeling supportive, and in some cases productive. The problem is that making abstractions efficient may mean that they aren't able to provide some of the niceties that users are accustomed to from other languages. Less obvious is that feeling performant can be in tension with feeling transparent or versatile; this is because many optimizations rely on a lack of transparency about the precise order or way in which things happen, and having more visibility, or more choices, can make those optimizations harder to do.

Examples

Iterators

Rust iterators are a good example of something which meets our goal of being performant. Code that uses iterators not only feels higher-level, it often compiles down to loops which are more efficient than if you wrote the loops with explicit iterators. This is because iterators are able to skip bounds checks on vectors or take other shortcuts.

Mechanisms

What are some of the ways that we make Rust feel performant?

Zero-cost abstractions

"What you don't use, you don't pay for. And further: What you do use, you couldn't hand code any better." -- Bjarne Stroustroup

Specify only what's necessary

Specify the details that are needed to capture the programmer's intent, but not more.

Many details of Rust are left deliberately unspecified. For example, unless users manually add a repr attribute, Rust structs and enums can be laid out in memory however the compiler sees fit. This allows us make optimizations like reordering struct fields to eliminate padding and reduce size, or representing Option<&T> as a single, nullable pointer. (Of course, reserving this freedom works against [transparency] and [versatility], which is why we have the option to specify the repr.)

Specify only what's necessary

Rust borrowed the idea of zero-cost abstractions from the C++ community. Bjarne Stroustroup defined zero-cost abstractions as, "What you don't use, you don't pay for. And further: What you do use, you couldn't hand code any better." We design our abstractions with these goals in mind as well.

TODO elaborate

Specify only what's necessary

πŸ₯° Supportive: "the language, tools, and community are here to help"

We strive to make our tools polished and friendly, and we look for every opportunity to guide people towards success. Part of that is building a community that eagerly shares its knowledge in a welcoming and inclusive way.

In tension with

Making Rust feel supportive can be in tension with Rust feeling reliable. It may also be in tension with Rust feeling versatile: often the most supportive path is to offer a simple, streamlined set of choices, but that may be too limiting.

Mechanisms

What are some of the ways that we make Rust feel supportive?

Polished developer experience

The details count.

Rust tools strive to provide a polished, smooth experience for our developers. One example is how the compiler offers quality error messages that attempt to not only indicate an error, but to teach the user how the language works, and offer helpful suggestions for how to fix their code. For tools like cargo, this manifests in careful CLI design that makes the "easy things easy" (but of course, for Rust to feel versatile, we have to go beyond that).

Polished developer experience

The details count.

Rust tools strive to provide a polished, smooth experience for our developers. One example is how the compiler offers quality error messages that attempt to not only indicate an error, but to teach the user how the language works, and offer helpful suggestions for how to fix their code. For tools like cargo, this manifests in careful CLI design that makes the "easy things easy" (but of course, for Rust to feel [versatile], we have to go beyond that).

🧩 Productive: "a little effort does a lot of work"

Rust and its ecosystem offer a wide array of powerful building blocks that can be combined and recombined. The result is that standing up quality code can be done in record time.

In tension with

Making Rust feel productive can be in tension with Rust feeling reliable and, in some cases, performant.

Mechanisms

What are some of the ways that we make Rust feel productive?

Enable a flourishing ecosystem

Stability; editions

Rust has a commitment to stability across versions. This is because stability is a key enabler of productivity: without stability across versions, you are forced to spend time resolving build failures instead of building the functionality you want to build.

Stability however can work against any of the various feelings that we strive for by giving us less "degrees of freedom" in our designs. The goal of Rust's editions system is too help finesse that tradeoff. Rust Editions permit us to make what would otherwise be breaking changes; because using the new edition is opt-in, and editions are interoperable, people can choose to adopt the newer behavior on their own schedule, thus avoiding the hit to productivity.

rustfmt

Portability

Rust code aims to be portable across all mainstream architectures by default.

Upgrades are easy and painless

Stability

πŸ”§ Transparent: "you can predict and control low-level details"

The translation from Rust to underlying machine code is straightforward and predictable. If needed, you have options to control the low-level details of how your application works.

In tension with

Feeling transparent can be in tension with supportive or productive, because transparency often requires exposing details.

Mechanisms

What are some of the ways that we make Rust feel transparent?

No global costs

Rust strives to avoid features that impose global costs (that is, impose a runtime cost even on projects that don't use them). This is a key part of Stroustroup's definition of zero-cost abstractions, "What you don't use, you don't pay for". This is the mechanism that encourages us to use ownership instead of a garbage collector, for example, since if any part of the code uses a garbage collector, call code can easily pay the price in terms of having to be scanned and so forth.

No global costs

🀸 Versatile: "you can do anything with Rust"

Rust scales well both up and down: it is well-suited to building everything from simple scripts to web servers to WebAssembly programs to kernel extensions and embedded systems. It is usable on both common and esoteric platforms.

In tension with...

Feeling versatile can be in tension with feeling supportive and productive.

Mechanisms

What are some of the ways that we make Rust feel versatile?

Expose all system capabilities

We aim to expose all the core system capabilities to Rust programs in some way, even if accessing them or using them correctly can be difficult. We don't want Rust users to feel they have to "drop down" to C or some other language; they should be able to use unsafe Rust to get their job done. Features like "inline assembly" are following in this vein.

An example of this mechanism in action is repr(C). Although our default struct layout is not defined ()

Expose all system capabilities

How to Rustacean

πŸ’– Be kind and considerate

Building Rust is hard enough without being disrespectful to one another. You don't have to agree, but you do have to be kind and considerate.

✨ Bring joy to the user

Our top goal is for Rust users to be productive and empowered. We want people to love using Rust and, if they so choose, to love participating in its community.

πŸ‘‹ Show up

Bring your expertise and be willing to argue for what you think is right.

πŸ”­ Recognize others' knowledge

Nobody has a monopoly on good ideas. We are always looking for opportunities to improve our designs and seeking input from those with experience and expertise.

πŸ” Start somewhere

Finding the perfect design requires iteration. Think big but start small; don't be afraid to change course as you learn more.

βœ… Follow through

Say what you will do, do what you say, and speak up if you know you can’t (it’s ok).

🀝 Pay it forward

Project members recognize exceptional potential, intentionally develop new members, and take their coaching role seriously.

🎁 Trust and delegate

Empowering others means being willing to let them make decisions in the way that they see best.

πŸ’– Be kind and considerate

Building Rust is hard enough without being disrespectful to one another. You don't have to agree, but you do have to be kind and considerate.

✨ Bring joy to the user

Our top goal is for Rust users to be productive and empowered. We want people to love using Rust and, if they so choose, to love participating in its community.

This covers both the design of Rust itself but also the way that you interact with users. Keep in mind that the more prominent you are within the Rust community, the more that you represent Rust wherever you go, even if it's on twitter or other places that are arguably a mix of public and private space. Some important aspects of this:

  • We are all beginners at something. We always keep the needs of new users in mind and try to avoid "".

At the same time:

  • Rust has a lot of users with a lot of needs. Sometimes those needs are in conflict, or they seem to be, and so we have to avoid going too far in one direction.
  • You have our own needs and limits too. Just because somebody has a problem doesn't mean you have to fix it. Often the right response is a polite no (or just no response at all).

Examples

Improving Rust's compiler messages

Somebody tweets about a terrible error message. It has a type that is 16K long and is completely opaque. "What a stupid language", they say.

Just right: You reply, "Oh, yeah, that message is terrible. Is the code that caused it something I can see?" You can tell they're frustrated, and that's why they're saying how stupid Rust is. Looking at the code, you realize both (a) how to fix their problem and (b) that a quick patch to the compiler would fix it. You do both. They're happy.

What do you do?

Responding on an issue

Someone opens an issue claiming a bug in Rust. In fact, the problem is that their code was relying on an implementation detail of a method in the standard library -- this is despite the fact that the documentation for the function clearly states that this detail may change.

What do you do?

Improving Rust's compiler messages

Somebody tweets about a terrible error message. It has a type that is 16K long and is completely opaque. "What a stupid language", they say.

Just right: You reply, "Oh, yeah, that message is terrible. Is the code that caused it something I can see?" You can tell they're frustrated, and that's why they're saying how stupid Rust is. Looking at the code, you realize both (a) how to fix their problem and (b) that a quick patch to the compiler would fix it. You do both. They're happy.

Too much: As above, but you put aside the work you've been doing and embark on a refactoring odyssey that slows down compilation time by 22% but also does improve this particular error message.

Too little: You reply, telling them that they just don't appreciate what Rust is doing for them.

Note: I suppose the right response really depends on what you're focused on! In truth, there's no harm in shrugging and moving on here, or just helping them to fix their code, if fixing error messages is not your thing. There's also no harm in doing a lot of work to address this error, if it's a common case and it's your thing. Slowing down the compiler by 22%, though, that's probably not so great (it will not bring joy to users). But no matter what you do, there's no sense in getting angry at them because they think Rust is stupid. The compiler is pretty stupid a lot of the time (like every computer program...).

πŸ‘‹ Show up

Bring your expertise and be willing to argue for what you think is right.

There are a few key points here:

  • You have to have a good sense of what you know and what you don't.
  • If you see people making a mistake, and it's about an area that you know, don't be afraid to point it out.
  • People don't always understand the first time, so sometimes you have to stick with it a bit.

At the same time:

  • If you are going to raise an objection, you have to be willing to make your case. You can't raise concerns and block indefinitely.
  • It may well be that others do understand your point, but just don't agree about how important it is. Ultimately, you have to trust that others have the best interest of Rust at heart, too.
  • The hardest disagreements to resolve often have underlying disagreements in values or the priorities of those values. Resolving such disagreements in an ideal way often requires introspecting on your own values, and understanding and empathizing with the values of others.

Examples

Raising an objection about a design

You are a member of the Rust lang team and you are concerned about the proposed syntax for a design.

What do you do?

Raising an objection about a design

You are a member of the Rust lang team and you are concerned about the proposed syntax for a design.

Just right (and you convince the others): You raise the objection and make your case for why the syntax is wrong. At first, nobody seems to understand the point you are making, but they extend some trust that you may have a valid point. You try again, this time explaining it from a different angle, and trying to understand and bridge the gap to other people's perspectives and values. This time, it works, and a few members of the team see what you're getting at. After a few more days of discussion, the consensus has shifted, possibly to your proposal or possibly to a new solution that satisfies everyone.

Just right (and you don't): You raise the objection and make your case for why the syntax is wrong. At first, nobody seems to understand the point you are making, so you try again, this time explaining it from a different angle. Still, the other members of the team don't agree. They are able to repeat back what you said, including the values you hold that it relates to, and they seem to understand it. but they just don't feel the problem will be as serious as you do, or they feel it's outweighed by other concerns of comparable value and there isn't a solution that satisfies everything. (We should hesitate to select "satisficing" solutions, but sometimes they may be necessary.) At that point, you release your objection. You record a "dissenting opinion", and that opinion is reflected in the "unresolved questions" of subsequent tracking issues, for later re-evaluation before stabilization.

Too much (blocking progress): You raise your objection but the rest of the team doesn't seem to agree. You insist that they are wrong and block progress. The team doesn't understand your position and values, and/or you don't understand theirs, so people talk past each other or don't talk at all. Eventually, the whole feature is dropped out of frustration.

Not enough (giving up too easily): You raise the objection and make your case for why the syntax is wrong. There is some pushback, and you feel pressure or discomfort maintaining your objection, so you give up and withdraw your concern. Sure enough, though, when the feature is released, the syntax proves to be a major obstacle. You wish you had made your case a bit more forcefully. The overall process would benefit from "forceful" not being a required property of a well-reasoned objection, and would benefit from recording the objection for further examination later in the process.

Not enough (cookie licking): You leave a comment on the issue stating that you have concerns, but you refuse to engage and discuss them in detail. "I object to this course of action, but I don't have time to get into it right now, and I don't know when I will." This does not mean you're wrong for not having the time or energy to get into it, but rather that the process of making a blocking objection requires someone to take the time and energy to explain, discuss it with other members of the team, and convince others; that's part of the expectations from a team member.

πŸ”­ Recognize others' knowledge

Nobody has a monopoly on good ideas. We are always looking for opportunities to improve our designs and seeking input from those with experience and expertise.

πŸ” Start somewhere

Finding the perfect design requires iteration. Think big but start small; don't be afraid to change course as you learn more.

βœ… Follow through

Say what you will do, do what you say, and speak up if you know you can’t (it’s ok).

🀝 Pay it forward

Project members recognize exceptional potential, intentionally develop new members, and take their coaching role seriously.

Examples

Spreading knowledge

There's an area of Rust that you may be the only expert on, or one of only a few experts on. You're spending much of your time dealing with issues in that area.

What do you do?

Spreading knowledge

There's an area of Rust that you may be the only expert on, or one of only a few experts on. You're spending much of your time dealing with issues in that area.

  • Just right: You give feedback to colleagues, fellow team members, and potentially the broader community, that Rust needs more experts in this area. You prioritize work that allows new or intermediate users to ramp up into your area of expertise. You spend time mentoring others, producing documentation, and similar, sometimes (not always) at the expense of doing the work yourself. You sometimes turn down action items that only you could do, and instead discuss what would need to happen so that that action item doesn't need to get done as urgently.

  • Too much: You push back on other changes and obstruct other work on Rust. You try to suggest that further work in a broader area shouldn't happen because you're too overloaded. You propose to give up on the whole area because you don't have time for it. You consider the merits of taking up alpaca farming instead of teaching sand to think.

  • Too little: You lean into your position as the sole expert in the area. You start to brush off new users, other interesting projects, or other aspects of the community, because you don't have the time or bandwidth. You have less fun working on Rust than you used to.

🎁 Trust and delegate

Empowering others means being willing to let them make decisions in the way that they see best.

Case studies

What follows are a list of short examples of elements of Rust's design. For each one, we elaborate on some of the

Key:

  • πŸ’š -- strong improvement
  • 🟑 -- mildly better or mildly worse
  • ❌

Type safety, unsafe code, and verification: a delicate balance

FeatureReliablePerformantProductiveSupportiveTransparentVersatile
Type safetyπŸ˜ŽπŸ˜ŽπŸ˜“πŸ˜“

The ? operator: a delicate balance

FeatureReliablePerformantProductiveSupportiveTransparentVersatile
The ? operatorπŸ’šπŸŸ‘πŸŸ‘πŸŸ‘πŸ’šπŸ’š

Coherence: a key feature, but one perhaps ready to be revisited

FeatureReliablePerformantProductiveSupportiveTransparentVersatile
CoherenceπŸ’šπŸ’šβŒβŒ

Rust's "coherence rules" are limits on the sets of impls that people are allowed to write in their crates. The goal is to ensure that, no matter what crates you grab from crates.io and add to your dependency list, there is also a consistent (one might say "coherent") set of impls -- and we never have the problem where there are two different Hash impls defined for a given type (for example). Those kinds of situations can lead to subtle bugs or other errors.

These rules serve an essential function, but they can also be severely limiting and a source of frustration. They are probably a good example of a language feature that ought to be adjusted, because of their severe impact on versatility and transparency (but which cannot be removed entirely, because they are needed for reliability and productivity).

😎 Productive: It may surprise you to hear coherence described as a win for producitivity, given that it prevents you from writing impls you might have otherwise liked to write (and indeed this is reflected in its impact on versatility). The reason that coherence helps productivity is because the rules are setup to ensure that any two crates on crates.io can be combined without linker errors or surprising behavior.

😎 Reliabie: Coherence

❓ FAQ

What are these principles?

The Rustacean principles are a set of principles which guide us in building Rust and shaping the Rust open source organization. Read more here.

Who developed these principles? Are they "official"?

No -- right now, this is a work-in-progress being developed by nikomatsakis, joshtriplett, and others within the Rust community. When it takes settled shape, it may indeed move to the Rust org as something more official.

Are these principles complete?

No! They are still in draft form. We are still iterating on them and are interested in hearing from people who are active in the Rust community about whether they reflect what you love about Rust (and, if not, what might be changed). That said, some aspects have gone through more iteration than others. Here is a list of some aspects of site and how well understood they are:

AspectConfidence
The qualities listed in How Rust empowersHigh: we've iterated quite a bit on these
Ordering of the qualitiesMedium: might still change this a bit
Mechanisms (e.g., type safety)Low: these have not seen a lot of iteration
The qualities listed in How to RustaceanMedium: expect to tweak these
Examples in the qualities listed in How to RustaceanLow: most of these aren't even written yet!
Case studiesLow: these have not seen a lot of iteration

Why develop these principles?

The goal of these principles is to help us to be more precise as we go about our work in the Rust org. The Rust empowers by being... section is primarily intended to help guide discussions about the effects of features on our users. The How to Rustacean section is meant to help us in describing the kinds of behaviors that we are looking for when we select Rust team members. This makes it hard for people to know what they ought to do, but it also makes it very hard for us to communicate where improvement is needed.

How can these principles be used?

These principles can guide us when having design discussions or questions of team membership. Read more here..