diff --git a/README.md b/README.md index 96d1a177..9620754f 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ implemented and reviewed via the normal GitHub pull request workflow. Some changes though are "substantial", and we ask that these be put through a bit of a design process and produce a consensus among the Rust -community and the [core team]. +community and the [sub-team]s. The "RFC" (request for comments) process is intended to provide a consistent and controlled path for new features to enter the language @@ -80,19 +80,21 @@ the direction the language is evolving in. * [RFC Postponement] * [Help this is all too informal!] + ## When you need to follow this process [When you need to follow this process]: #when-you-need-to-follow-this-process -You need to follow this process if you intend to make "substantial" -changes to Rust, Cargo, Crates.io, or the RFC process itself. What constitutes -a "substantial" change is evolving based on community norms, but may include -the following. +You need to follow this process if you intend to make "substantial" changes to +Rust, Cargo, Crates.io, or the RFC process itself. What constitutes a +"substantial" change is evolving based on community norms and varies depending +on what part of the ecosystem you are proposing to change, but may include the +following. - Any semantic or syntactic change to the language that is not a bugfix. - Removing language features, including those that are feature-gated. - - Changes to the interface between the compiler and libraries, -including lang items and intrinsics. - - Additions to `std` + - Changes to the interface between the compiler and libraries, including lang + items and intrinsics. + - Additions to `std`. Some changes do not require an RFC: @@ -108,6 +110,15 @@ If you submit a pull request to implement a new feature without going through the RFC process, it may be closed with a polite request to submit an RFC first. +For more details on when an RFC is required, please see the following specific +guidelines, these correspond with some of the Rust community's +[sub-teams](http://www.rust-lang.org/team.html): + +* [language changes](lang_changes.md), +* [library changes](libs_changes.md), +* [compiler changes](compiler_changes.md). + + ## Before creating an RFC [Before creating an RFC]: #before-creating-an-rfc @@ -130,12 +141,12 @@ on the [RFC issue tracker][issues], and occasionally posting review. As a rule of thumb, receiving encouraging feedback from long-standing -project developers, and particularly members of the [core team][core] +project developers, and particularly members of the relevant [sub-team] is a good indication that the RFC is worth pursuing. [issues]: https://github.com/rust-lang/rfcs/issues [discuss]: http://discuss.rust-lang.org/ -[core]: https://github.com/rust-lang/rust/wiki/Note-core-team + ## What the process is [What the process is]: #what-the-process-is @@ -146,49 +157,57 @@ is 'active' and may be implemented with the goal of eventual inclusion into Rust. * Fork the RFC repo http://github.com/rust-lang/rfcs -* Copy `0000-template.md` to `text/0000-my-feature.md` (where -'my-feature' is descriptive. don't assign an RFC number yet). -* Fill in the RFC. Put care into the details: RFCs that do not -present convincing motivation, demonstrate understanding of the -impact of the design, or are disingenuous about the drawbacks or -alternatives tend to be poorly-received. -* Submit a pull request. As a pull request the RFC will receive design -feedback from the larger community, and the author should be prepared -to revise it in response. -* During Rust triage, the pull request will either be closed (for RFCs -that clearly will not be accepted) or assigned a *shepherd*. The -shepherd is a trusted developer who is familiar with the process, who -will help to move the RFC forward, and ensure that the right people -see and review it. -* Build consensus and integrate feedback. RFCs that have broad support -are much more likely to make progress than those that don't receive -any comments. The shepherd assigned to your RFC should help you get -feedback from Rust developers as well. +* Copy `0000-template.md` to `text/0000-my-feature.md` (where 'my-feature' is +descriptive. don't assign an RFC number yet). +* Fill in the RFC. Put care into the details: RFCs that do not present +convincing motivation, demonstrate understanding of the impact of the design, or +are disingenuous about the drawbacks or alternatives tend to be poorly-received. +* Submit a pull request. As a pull request the RFC will receive design feedback +from the larger community, and the author should be prepared to revise it in +response. +* Each pull request will be labeled with the most relevant [sub-team]. +* Each sub-team triages its RFC PRs. The sub-team will will either close the PR +(for RFCs that clearly will not be accepted) or assign it a *shepherd*. The +shepherd is a trusted developer who is familiar with the RFC process, who will +help to move the RFC forward, and ensure that the right people see and review +it. +* Build consensus and integrate feedback. RFCs that have broad support are much +more likely to make progress than those that don't receive any comments. The +shepherd assigned to your RFC should help you get feedback from Rust developers +as well. * The shepherd may schedule meetings with the author and/or relevant -stakeholders to discuss the issues in greater detail, and in some -cases the topic may be discussed at the larger [weekly meeting]. In -either case a summary from the meeting will be posted back to the RFC -pull request. -* Once both proponents and opponents have clarified and defended -positions and the conversation has settled, the shepherd will take it -to the [core team] for a final decision. -* Eventually, someone from the [core team] will either accept the RFC -by merging the pull request, assigning the RFC a number (corresponding -to the pull request number), at which point the RFC is 'active', or -reject it by closing the pull request. +stakeholders to discuss the issues in greater detail. +* The sub-team will discuss the RFC PR, as much as possible in the comment +thread of the PR itself. Offline discussion will be summarized on the PR comment +thread. +* Once both proponents and opponents have clarified and defended positions and +the conversation has settled, the RFC will enter its *final comment period* +(FCP). This is a final opportunity for the community to comment on the PR and is +a reminder for all members of the sub-team to be aware of the RFC. +* The FCP lasts one week. It may be extended if consensus between sub-team +members cannot be reached. At the end of the FCP, the [sub-team] will either +accept the RFC by merging the pull request, assigning the RFC a number +(corresponding to the pull request number), at which point the RFC is 'active', +or reject it by closing the pull request. How exactly the sub-team decide on an +RFC is up to the sub-team. + ## The role of the shepherd [The role of the shepherd]: #the-role-of-the-shepherd -During triage, every RFC will either be closed or assigned a shepherd. -The role of the shepherd is to move the RFC through the process. This -starts with simply reading the RFC in detail and providing initial -feedback. The shepherd should also solicit feedback from people who -are likely to have strong opinions about the RFC. Finally, when this -feedback has been incorporated and the RFC seems to be in a steady -state, the shepherd will bring it to the meeting. In general, the idea -here is to "front-load" as much of the feedback as possible before the -point where we actually reach a decision. +During triage, every RFC will either be closed or assigned a shepherd from the +relevant sub-team. The role of the shepherd is to move the RFC through the +process. This starts with simply reading the RFC in detail and providing initial +feedback. The shepherd should also solicit feedback from people who are likely +to have strong opinions about the RFC. When this feedback has been incorporated +and the RFC seems to be in a steady state, the shepherd and/or sub-team leader +will announce an FCP. In general, the idea here is to "front-load" as much of +the feedback as possible before the point where we actually reach a decision - +by the end of the FCP, the decision on whether or not to accept the RFC should +usually be obvious from the RFC discussion thread. On occasion, there may not be +consensus but discussion has stalled. In this case, the relevant team will make +a decision. + ## The RFC life-cycle [The RFC life-cycle]: #the-rfc-life-cycle @@ -210,35 +229,36 @@ through to completion: authors should not expect that other project developers will take on responsibility for implementing their accepted feature. -Modifications to active RFC's can be done in followup PR's. We strive +Modifications to active RFC's can be done in follow-up PR's. We strive to write each RFC in a manner that it will reflect the final design of the feature; but the nature of the process means that we cannot expect every merged RFC to actually reflect what the end result will be at -the time of the next major release; therefore we try to keep each RFC -document somewhat in sync with the language feature as planned, -tracking such changes via followup pull requests to the document. +the time of the next major release. + +In general, once accepted, RFCs should not be substantially changed. Only very +minor changes should be submitted as amendments. More substantial changes should +be new RFCs, with a note added to the original RFC. Exactly what counts as a +"very minor change" is up to the sub-team to decide. There are some more +specific guidelines in the sub-team RFC guidelines for the [language](lang_changes.md), +[libraries](libs_changes.md), and [compiler](compiler_changes.md). -An RFC that makes it through the entire process to implementation is -considered 'complete' and is moved to the 'complete' folder; an RFC -that fails after becoming active is 'inactive' and moves to the -'inactive' folder. ## Reviewing RFC's [Reviewing RFC's]: #reviewing-rfcs While the RFC PR is up, the shepherd may schedule meetings with the author and/or relevant stakeholders to discuss the issues in greater -detail, and in some cases the topic may be discussed at the larger -[weekly meeting]. In either case a summary from the meeting will be +detail, and in some cases the topic may be discussed at a sub-team +meeting. In either case a summary from the meeting will be posted back to the RFC pull request. -The core team makes final decisions about RFCs after the benefits and -drawbacks are well understood. These decisions can be made at any -time, but the core team will regularly issue decisions on at least a -weekly basis. When a decision is made, the RFC PR will either be -merged or closed, in either case with a comment describing the -rationale for the decision. The comment should largely be a summary of -discussion already on the comment thread. +A sub-team makes final decisions about RFCs after the benefits and drawbacks are +well understood. These decisions can be made at any time, but the sub-team will +regularly issue decisions. When a decision is made, the RFC PR will either be +merged or closed. In either case, if the reasoning is not clear from the +discussion in thread, the sub-team will add a comment describing the rationale +for the decision. + ## Implementing an RFC [Implementing an RFC]: #implementing-an-rfc @@ -248,7 +268,7 @@ implemented right away. Other accepted RFC's can represent features that can wait until some arbitrary developer feels like doing the work. Every accepted RFC has an associated issue tracking its implementation in the Rust repository; thus that associated issue can -be assigned a priority via the [triage process] that the team uses for +be assigned a priority via the triage process that the team uses for all issues in the Rust repository. The author of an RFC is not obligated to implement it. Of course, the @@ -259,15 +279,18 @@ If you are interested in working on the implementation for an 'active' RFC, but cannot determine if someone else is already working on it, feel free to ask (e.g. by leaving a comment on the associated issue). + ## RFC Postponement [RFC Postponement]: #rfc-postponement -Some RFC pull requests are tagged with the 'postponed' label when they -are closed (as part of the rejection process). An RFC closed with -“postponed” is marked as such because we want neither to think about -evaluating the proposal nor about implementing the described feature -until after the next major release, and we believe that we can afford -to wait until then to do so. +Some RFC pull requests are tagged with the 'postponed' label when they are +closed (as part of the rejection process). An RFC closed with “postponed” is +marked as such because we want neither to think about evaluating the proposal +nor about implementing the described feature until some time in the future, and +we believe that we can afford to wait until then to do so. Historically, +"postponed" was used to postpone features until after 1.0. Postponed PRs may be +re-opened when the time is right. We don't have any formal process for that, you +should ask members of the relevant sub-team. Usually an RFC pull request marked as “postponed” has already passed an informal first round of evaluation, namely the round of “do we @@ -285,6 +308,4 @@ present circumstances. As usual, we are trying to let the process be driven by consensus and community norms, not impose more structure than necessary. -[core team]: https://github.com/mozilla/rust/wiki/Note-core-team -[triage process]: https://github.com/rust-lang/rust/wiki/Note-development-policy#milestone-and-priority-nomination-and-triage -[weekly meeting]: https://github.com/rust-lang/meeting-minutes +[sub-team]: http://www.rust-lang.org/team.html diff --git a/compiler_changes.md b/compiler_changes.md new file mode 100644 index 00000000..75137743 --- /dev/null +++ b/compiler_changes.md @@ -0,0 +1,52 @@ +# RFC policy - the compiler + +We have not previously had an RFC system for compiler changes, so policy here is +likely to change as we get the hang of things. We don't want to slow down most +compiler development, but on the other hand we do want to do more design work +ahead of time on large additions and refactorings. + +Compiler RFCs will be managed by the compiler sub-team, and tagged `T-compiler`. +The compiler sub-team will do an initial triage of new PRs within a week of +submission. The result of triage will either be that the PR is assigned to a +member of the sub-team for shepherding, the PR is closed because the sub-team +believe it should be done without an RFC, or closed because the sub-team feel it +should clearly not be done and further discussion is not necessary. We'll follow +the standard procedure for shepherding, final comment period, etc. + +Where there is significant design work for the implementation of a language +feature, the preferred workflow is to submit two RFCs - one for the language +design and one for the implementation design. The implementation RFC may be +submitted later if there is scope for large changes to the language RFC. + + +## Changes which need an RFC + +* Large refactorings or redesigns of the compiler +* Changing the API presented to syntax extensions or other compiler plugins in + non-trivial ways +* Adding, removing, or changing a stable compiler flag +* The implementation of new language features where there is significant change + or addition to the compiler. There is obviously some room for interpretation + about what consitutes a "significant" change and how much detail the + implementation RFC needs. For guidance, [associated items](text/0195-associated-items.md) + and [UFCS](text/0132-ufcs.md) would clearly need an implementation RFC, + [type ascription](text/0803-type-ascription.md) and + [lifetime elision](text/0141-lifetime-elision.md) would not. +* Any other change which causes backwards incompatible changes to stable + behaviour of the compiler, language, or libraries + + +## Changes which don't need an RFC + +* Bug fixes, improved error messages, etc. +* Minor refactoring/tidying up +* Implmenting language features which have an accepted RFC, where the + implementation does not significantly change the compiler or require + significant new design work +* Adding unstable API for tools (note that all compiler API is currently unstable) +* Adding, removing, or changing an unstable compiler flag (if the compiler flag + is widely used there should be at least some discussion on discuss, or an RFC + in some cases) + +If in doubt it is probably best to just announce the change you want to make to +the compiler subteam on discuss or IRC, and see if anyone feels it needs an RFC. diff --git a/lang_changes.md b/lang_changes.md new file mode 100644 index 00000000..7e7e6a73 --- /dev/null +++ b/lang_changes.md @@ -0,0 +1,36 @@ +# RFC policy - language design + +Pretty much every change to the language needs an RFC. + +Language RFCs are managed by the language sub-team, and tagged `T-lang`. The +language sub-team will do an initial triage of new PRs within a week of +submission. The result of triage will either be that the PR is assigned to a +member of the sub-team for shepherding, the PR is closed as postponed because +the subteam believe it might be a good idea, but is not currently aligned with +Rust's priorities, or the PR is closed because the sub-team feel it should +clearly not be done and further discussion is not necessary. In the latter two +cases, the sub-team will give a detailed explanation. We'll follow the standard +procedure for shepherding, final comment period, etc. + + +## Amendments + +Sometimes in the implementation of an RFC, changes are required. In general +these don't require an RFC as long as they are very minor and in the spirit of +the accepted RFC (essentially bug fixes). In this case implementers should +submit an RFC PR which amends the accepted RFC with the new details. Although +the RFC repository is not intended as a reference manual, it is preferred that +RFCs do reflect what was actually implemented. Amendment RFCs will go through +the same process as regular RFCs, but should be less controversial and thus +should move more quickly. + +When a change is more dramatic, it is better to create a new RFC. The RFC should +be standalone and reference the original, rather than modifying the existing +RFC. You should add a comment to the original RFC with referencing the new RFC +as part of the PR. + +Obviously there is some scope for judgment here. As a guideline, if a change +affects more than one part of the RFC (i.e., is a non-local change), affects the +applicability of the RFC to its motivating use cases, or there are multiple +possible new solutions, then the feature is probably not 'minor' and should get +a new RFC. diff --git a/libs_changes.md b/libs_changes.md new file mode 100644 index 00000000..31f1de02 --- /dev/null +++ b/libs_changes.md @@ -0,0 +1,114 @@ +# RFC guidelines - libraries sub-team + +# Motivation + +* RFCs are heavyweight: + * RFCs generally take at minimum 2 weeks from posting to land. In + practice it can be more on the order of months for particularly + controversial changes. + * RFCs are a lot of effort to write; especially for non-native speakers or + for members of the community whose strengths are more technical than literary. + * RFCs may involve pre-RFCs and several rewrites to accommodate feedback. + * RFCs require a dedicated shepherd to herd the community and author towards + consensus. + * RFCs require review from a majority of the subteam, as well as an official + vote. + * RFCs can't be downgraded based on their complexity. Full process always applies. + Easy RFCs may certainly land faster, though. + * RFCs can be very abstract and hard to grok the consequences of (no implementation). + +* PRs are low *overhead* but potentially expensive nonetheless: + * Easy PRs can get insta-merged by any rust-lang contributor. + * Harder PRs can be easily escalated. You can ping subject-matter experts for second + opinions. Ping the whole team! + * Easier to grok the full consequences. Lots of tests and Crater to save the day. + * PRs can be accepted optimistically with bors, buildbot, and the trains to guard + us from major mistakes making it into stable. The size of the nightly community + at this point in time can still mean major community breakage regardless of trains, + however. + * HOWEVER: Big PRs can be a lot of work to make only to have that work rejected for + details that could have been hashed out first. + +* RFCs are *only* meaningful if a significant and diverse portion of the +community actively participates in them. The official teams are not +sufficiently diverse to establish meaningful community consensus by agreeing +amongst themselves. + +* If there are *tons* of RFCs -- especially trivial ones -- people are less +likely to engage with them. Official team members are super busy. Domain experts +and industry professionals are super busy *and* have no responsibility to engage +in RFCs. Since these are *exactly* the most important people to get involved in +the RFC process, it is important that we be maximally friendly towards their +needs. + + +# Is an RFC required? + +The overarching philosophy is: *do whatever is easiest*. If an RFC +would be less work than an implementation, that's a good sign that an RFC is +necessary. That said, if you anticipate controversy, you might want to short-circuit +straight to an RFC. For instance new APIs almost certainly merit an RFC. Especially +as `std` has become more conservative in favour of the much more agile cargoverse. + +* **Submit a PR** if the change is a: + * Bugfix + * Docfix + * Obvious API hole patch, such as adding an API from one type to a symmetric type. + e.g. `Vec -> Box<[T]>` clearly motivates adding `String -> Box` + * Minor tweak to an unstable API (renaming, generalizing) + * Implementing an "obvious" trait like Clone/Debug/etc +* **Submit an RFC** if the change is a: + * New API + * Semantic Change to a stable API + * Generalization of a stable API (e.g. how we added Pattern or Borrow) + * Deprecation of a stable API + * Nontrivial trait impl (because all trait impls are insta-stable) +* **Do the easier thing** if uncertain. (choosing a path is not final) + + +# Non-RFC process + +* A (non-RFC) PR is likely to be **closed** if clearly not acceptable: + * Disproportionate breaking change (small inference breakage may be acceptable) + * Unsound + * Doesn't fit our general design philosophy around the problem + * Better as a crate + * Too marginal for std + * Significant implementation problems + +* A PR may also be closed because an RFC is approriate. + +* A (non-RFC) PR may be **merged as unstable**. In this case, the feature +should have a fresh feature gate and an associated tracking issue for +stabilisation. Note that trait impls and docs are insta-stable and thus have no +tracking issue. This may imply requiring a higher level of scrutiny for such +changes. + +However, an accepted RFC is not a rubber-stamp for merging an implementation PR. +Nor must an implementation PR perfectly match the RFC text. Implementation details +may merit deviations, though obviously they should be justified. The RFC may be +amended if deviations are substantial, but are not generally necessary. RFCs should +favour immutability. The RFC + Issue + PR should form a total explanation of the +current implementation. + +* Once something has been merged as unstable, a shepherd should be assigned + to promote and obtain feedback on the design. + +* Every time a release cycle ends, the libs teams assesses the current unstable + APIs and selects some number of them for potential stabilization during the + next cycle. These are announced for FCP at the beginning of the cycle, and + (possibly) stabilized just before the beta is cut. + +* After the final comment period, an API should ideally take one of two paths: + * **Stabilize** if the change is desired, and consensus is reached + * **Deprecate** is the change is undesired, and consensus is reached + * **Extend the FCP** is the change cannot meet consensus + * If consensus *still* can't be reached, consider requiring a new RFC or + just deprecating as "too controversial for std". + +* If any problems are found with a newly stabilized API during its beta period, + *strongly* favour reverting stability in order to prevent stabilizing a bad + API. Due to the speed of the trains, this is not a serious delay (~2-3 months + if it's not a major problem). + + diff --git a/text/0560-integer-overflow.md b/text/0560-integer-overflow.md index de14896f..539f225c 100644 --- a/text/0560-integer-overflow.md +++ b/text/0560-integer-overflow.md @@ -125,10 +125,15 @@ The error conditions that can arise, and their defined results, are as follows. The intention is that the defined results are the same as the defined results today. The only change is that now a panic may result. -- The operations `+`, `-`, `*`, `/`, `%` can underflow and - overflow. -- Shift operations (`<<`, `>>`) can shift a value of width `N` by more - than `N` bits. +- The operations `+`, `-`, `*`, can underflow and overflow. When checking is + enabled this will panic. When checking is disabled this will two's complement + wrap. +- The operations `/`, `%` for the arguments `INT_MIN` and `-1` + will unconditionally panic. This is unconditional for legacy reasons. +- Shift operations (`<<`, `>>`) on a value of with `N` can be passed a shift value + >= `N`. It is unclear what behaviour should result from this, so the shift value + is unconditionally masked to be modulo `N` to ensure that the argument is always + in range. ## Enabling overflow checking @@ -145,7 +150,7 @@ potential overflow (and, in particular, for code where overflow is expected and normal, they will be immediately guided to use the wrapping methods introduced below). However, because these checks will be compiled out whenever an optimized build is produced, final code -wilil not pay a performance penalty. +will not pay a performance penalty. In the future, we may add additional means to control when overflow is checked, such as scoped attributes or a global, independent @@ -451,17 +456,7 @@ were: # Unresolved questions -The C semantics of wrapping operations in some cases are undefined: - -- `INT_MIN / -1`, `INT_MIN % -1` -- Shifts by an excessive number of bits - -This RFC takes no position on the correct semantics of these -operations, simply preserving the existing semantics. However, it may -be worth trying to define the wrapping semantics of these operations -in a portable way, even if that implies some runtime cost. Since these -are all error conditions, this is an orthogonal topic to the matter of -overflow. +None today (see Updates section below). # Future work @@ -491,6 +486,10 @@ Since it was accepted, the RFC has been updated as follows: 2. `as` was changed to restore the behavior before the RFC (that is, it truncates to the target bitwidth and reinterprets the highest order bit, a.k.a. sign-bit, as necessary, as a C cast would). +3. Shifts were specified to mask off the bits of over-long shifts. +4. Overflow was specified to be two's complement wrapping (this was mostly + a clarification). +5. `INT_MIN / -1` and `INT_MIN % -1` panics. # Acknowledgements and further reading