├── CNAME ├── .gitignore ├── triagebot.toml ├── .editorconfig ├── CODE_OF_CONDUCT.md ├── .env ├── .gitattributes ├── src ├── about.md ├── breaking-changes │ ├── summary.md │ ├── doc-changes.md │ ├── prelude.md │ └── new-trait-impls.md ├── development │ ├── building-and-debugging.md │ ├── how-to-write-documentation.md │ ├── feature-lifecycle.md │ ├── perf-benchmarking.md │ └── stabilization.md ├── policy │ ├── extension-traits.md │ ├── target-code.md │ ├── inline.md │ ├── unsafe-preconditions.md │ ├── must-use.md │ ├── doc-alias.md │ ├── safety-comments.md │ └── specialization.md ├── SUMMARY.md ├── team │ ├── meetings.md │ ├── membership.md │ ├── reviewing.md │ └── summary.md └── tricky │ ├── generics-and-unsafe.md │ └── may-dangle.md ├── book.toml ├── ci ├── linkcheck.sh ├── check_line_lengths.sh ├── check-in.sh └── ghpages-deploy.sh ├── LICENSE-MIT ├── README.md ├── .github └── workflows │ ├── gh-pages.yml │ └── ci.yml └── LICENSE-APACHE /CNAME: -------------------------------------------------------------------------------- 1 | std-dev-guide.rust-lang.org 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | book 2 | 3 | # prevent accidentally changes 4 | book.toml 5 | -------------------------------------------------------------------------------- /triagebot.toml: -------------------------------------------------------------------------------- 1 | [assign] 2 | 3 | [relabel] 4 | allow-unauthenticated = [ 5 | "waiting-on-review", 6 | "waiting-on-author", 7 | "blocked", 8 | ] 9 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [src/*] 4 | end_of_line = lf 5 | insert_final_newline = true 6 | 7 | [ci/*.sh] 8 | indent_style = space 9 | indent_size = 2 10 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # The Rust Code of Conduct 2 | 3 | This repository follows the [Code of Conduct](https://www.rust-lang.org/conduct.html) of the Rust organization. 4 | -------------------------------------------------------------------------------- /.env: -------------------------------------------------------------------------------- 1 | MDBOOK_VERSION=0.4.25 2 | MDBOOK_LINKCHECK_VERSION=0.7.7 3 | MDBOOK_TOC_VERSION=0.11.0 4 | 5 | GIT_DEPLOY_DIR=book/html 6 | GIT_DEPLOY_BRANCH=gh-pages 7 | GIT_DEPLOY_REPO=https://github.com/rust-lang/std-dev-guide 8 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Set the default behavior, in case people don't have core.autocrlf set. 2 | * text=auto eol=lf 3 | 4 | # Older git versions try to fix line endings on images, this prevents it. 5 | *.png binary 6 | *.jpg binary 7 | *.ico binary 8 | -------------------------------------------------------------------------------- /src/about.md: -------------------------------------------------------------------------------- 1 | # About this Guide 2 | 3 | Welcome to the std dev guide. 4 | 5 | This guide is maintained by the library team. 6 | 7 | The guide is not very complete yet. 8 | Contributions to this guide are very welcome. 9 | 10 | Other useful documentation: 11 | 12 | - 13 | - 14 | -------------------------------------------------------------------------------- /src/breaking-changes/summary.md: -------------------------------------------------------------------------------- 1 | # Breaking changes 2 | 3 | Breaking changes should be avoided when possible. 4 | [RFC 1105](https://rust-lang.github.io/rfcs/1105-api-evolution.html) lays the foundations for what constitutes a breaking change. 5 | Breakage may be deemed acceptable or not based on its actual impact, 6 | which can be approximated with a [crater](https://github.com/rust-lang/crater/blob/master/docs/bot-usage.md) run. 7 | 8 | If the impact isn't too high, looping in maintainers of broken crates and submitting PRs to fix them can be a valid strategy. 9 | -------------------------------------------------------------------------------- /book.toml: -------------------------------------------------------------------------------- 1 | [book] 2 | title = "Standard library developers Guide" 3 | authors = ["the rust-lang authors"] 4 | description = "Guide for standard library developers" 5 | language = "en" 6 | multilingual = false 7 | src = "./src" 8 | 9 | [build] 10 | create-missing = true 11 | 12 | [rust] 13 | edition = "2018" 14 | 15 | [preprocessor.toc] 16 | command = "mdbook-toc" 17 | renderer = ["html"] 18 | 19 | [output.linkcheck] 20 | 21 | [output.html] 22 | git-repository-icon = "fa-github" 23 | git-repository-url = "https://github.com/rust-lang/std-dev-guide" 24 | edit-url-template = "https://github.com/rust-lang/std-dev-guide/edit/master/{path}" 25 | 26 | [output.html.redirect] 27 | "/feature-lifecycle/stabilization.html" = "/development/stabilization.html" 28 | -------------------------------------------------------------------------------- /src/breaking-changes/doc-changes.md: -------------------------------------------------------------------------------- 1 | # Breaking documentation changes 2 | 3 | First, short explanation about what a stability guarantee is: a statement in 4 | the document which explains what the item is doing in a precise case. For 5 | example: 6 | 7 | * Showing precisely how a function on floats handles `NaN`. 8 | * Saying that a sort method has a particular running-time bound. 9 | 10 | So if a doc change updates/adds/removes a stability guarantee, it has to be 11 | **very** carefully handled and needs to go through the 12 | [libs API team FCP](https://rustc-dev-guide.rust-lang.org/stabilization_guide.html?highlight=fcp#fcp). 13 | 14 | It can be circumvented by adding a `# Current Implementation` section 15 | [like done here](https://github.com/rust-lang/rust/blob/4a8d2e3856c0c75c71998b6c85937203839b946d/library/alloc/src/slice.rs#L250). 16 | -------------------------------------------------------------------------------- /ci/linkcheck.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | set -o pipefail 5 | 6 | # https://docs.travis-ci.com/user/environment-variables/#default-environment-variables 7 | if [ "$TRAVIS_EVENT_TYPE" = "cron" ] ; then # running in cron job 8 | FLAGS="" 9 | 10 | echo "Doing full link check." 11 | set -x 12 | elif [ "$CI" = "true" ] ; then # running in PR CI build 13 | if [ -z "$TRAVIS_COMMIT_RANGE" ]; then 14 | echo "error: unexpected state: TRAVIS_COMMIT_RANGE must be non-empty in CI" 15 | exit 1 16 | fi 17 | 18 | CHANGED_FILES=$(git diff --name-only $TRAVIS_COMMIT_RANGE | tr '\n' ' ') 19 | FLAGS="--no-cache -f $CHANGED_FILES" 20 | 21 | echo "Checking files changed in $TRAVIS_COMMIT_RANGE: $CHANGED_FILES" 22 | set -x 23 | else # running locally 24 | COMMIT_RANGE=master... 25 | CHANGED_FILES=$(git diff --name-only $COMMIT_RANGE | tr '\n' ' ') 26 | FLAGS="-f $CHANGED_FILES" 27 | 28 | echo "Checking files changed in $COMMIT_RANGE: $CHANGED_FILES" 29 | fi 30 | 31 | exec mdbook-linkcheck $FLAGS -- $TRAVIS_BUILD_DIR 32 | -------------------------------------------------------------------------------- /LICENSE-MIT: -------------------------------------------------------------------------------- 1 | Permission is hereby granted, free of charge, to any 2 | person obtaining a copy of this software and associated 3 | documentation files (the "Software"), to deal in the 4 | Software without restriction, including without 5 | limitation the rights to use, copy, modify, merge, 6 | publish, distribute, sublicense, and/or sell copies of 7 | the Software, and to permit persons to whom the Software 8 | is furnished to do so, subject to the following 9 | conditions: 10 | 11 | The above copyright notice and this permission notice 12 | shall be included in all copies or substantial portions 13 | of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 16 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 17 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 18 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 19 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 20 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 21 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 22 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 23 | DEALINGS IN THE SOFTWARE. 24 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![GitHub Actions Badge](https://github.com/rust-lang/std-dev-guide/workflows/Continuous%20Integration/badge.svg)](https://github.com/rust-lang/std-dev-guide/actions) 2 | 3 | Welcome to the Standard Library Development Guide! This book is for anybody who is contributing to, or who is reviewing contributions to, the standard library. It aims to capture everything you need to know through the whole lifecycle of a standard library feature, from inception through to an initial unstable implementation, through to stabilization, and eventually maybe deprecation. 4 | 5 | **The latest version of this guide is available on https://std-dev-guide.rust-lang.org/** 6 | 7 | ### Contributing to the guide 8 | 9 | The guide is a very early work in progress. It still has big gaps. If there's a section you'd like to flesh out, please feel free to submit a PR or raise an issue! 10 | 11 | ### See also 12 | 13 | - [The Rustc Dev Guide](https://github.com/rust-lang/rustc-dev-guide): A similar resource for the Rust compiler itself. 14 | - [The Libs Team Repository](https://github.com/rust-lang/libs-team): The home of the Library Team, who maintain this book. 15 | -------------------------------------------------------------------------------- /ci/check_line_lengths.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | if [ "$1" == "--help" ]; then 4 | echo 'Usage:' "[MAX_LINE_LENGTH=n] $0 [file ...]" 5 | exit 1 6 | fi 7 | 8 | if [ "$MAX_LINE_LENGTH" == "" ]; then 9 | MAX_LINE_LENGTH=100 10 | fi 11 | 12 | if [ "$1" == "" ]; then 13 | files=( src/**/*.md ) 14 | else 15 | files=( "$@" ) 16 | fi 17 | 18 | echo "Checking line lengths in all source files <= $MAX_LINE_LENGTH chars..." 19 | 20 | echo "Offending files and lines:" 21 | (( bad_lines = 0 )) 22 | (( inside_block = 0 )) 23 | for file in "${files[@]}"; do 24 | echo "$file" 25 | (( line_no = 0 )) 26 | while IFS="" read -r line || [[ -n "$line" ]] ; do 27 | (( line_no++ )) 28 | if [[ "$line" =~ ^'```' ]] ; then 29 | (( inside_block = !$inside_block )) 30 | continue 31 | fi 32 | if ! (( $inside_block )) \ 33 | && ! [[ "$line" =~ " | "|"-|-"|"://"|"]:"|\[\^[^\ ]+\]: ]] \ 34 | && (( "${#line}" > $MAX_LINE_LENGTH )) ; then 35 | (( bad_lines++ )) 36 | echo -e "\t$line_no : $line" 37 | fi 38 | done < "$file" 39 | done 40 | 41 | echo "$bad_lines offending lines found." 42 | (( $bad_lines == 0 )) 43 | -------------------------------------------------------------------------------- /src/breaking-changes/prelude.md: -------------------------------------------------------------------------------- 1 | # Breaking changes to the prelude 2 | 3 | Making changes to the prelude can easily cause breakage because it impacts all Rust code. 4 | In most cases the impact is limited since prelude items have the lowest priority in name lookup (lower than glob imports), but there are two cases where this doesn't work. 5 | 6 | ## Traits 7 | 8 | Adding a new trait to the prelude causes new methods to become available for existing types. 9 | This can cause name resolution errors in user code if a method with the same name is also available from a different trait. 10 | 11 | For this reason, [`TryFrom` and `TryInto`](https://github.com/rust-lang/rust/issues/33417) were only added to the prelude for the 2021 edition despite being stabilized in 2019. 12 | 13 | ## Macros 14 | 15 | Unlike other item types, rustc's name resolution for macros does not support giving prelude macros a lower priority than other macros, even if the macro is unstable. 16 | As a general rule, avoid adding macros to the prelude except at edition boundaries. 17 | 18 | This issues was encoutered when trying to land the [`assert_matches!` macro](https://github.com/rust-lang/rust/issues/82913). 19 | -------------------------------------------------------------------------------- /ci/check-in.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -eu 4 | 5 | # This is not a very smart script 6 | if [ $# != 2 ]; then 7 | echo "usage: $0 " 8 | if [ $# = 1 ] ; then 9 | echo "help: you can find the number of PRs merged at" \ 10 | "https://github.com/rust-lang/rustc-dev-guide/pulls?q=is%3Apr+is%3Amerged+updated%3A%3E$1" 11 | fi 12 | exit 1 13 | fi 14 | 15 | curl() { 16 | command curl -s "$@" 17 | } 18 | 19 | # Get recently updated PRs 20 | curl "https://api.github.com/repos/rust-lang/rustc-dev-guide/pulls?state=closed&per_page=$2" \ 21 | | jq '[.[] | select(.merged_at > "'"$1"'")]' > pulls.json 22 | 23 | show_pulls() { 24 | jq -r '.[] | { title, number, html_url, user: .user.login } | "- " + .title + " [#" + (.number | tostring) + "](" + .html_url + ")"' 25 | } 26 | 27 | echo "### Authors" 28 | jq -r '{ login: .[].user.login } | "- **@" + .login + "**"' < pulls.json \ 29 | | sort -u 30 | echo 31 | echo "### Changes" 32 | echo 33 | show_pulls < pulls.json 34 | echo 35 | echo "### Changes in progress" 36 | echo 37 | # If there are more than 30 PRs open at a time, you'll need to set `per_page`. 38 | # For now this seems unlikely. 39 | curl "https://api.github.com/repos/rust-lang/rustc-dev-guide/pulls?state=open" | show_pulls 40 | -------------------------------------------------------------------------------- /src/development/building-and-debugging.md: -------------------------------------------------------------------------------- 1 | 2 | # Building and Debugging the library crates 3 | 4 | Most of the [instructions from the rustc-dev-guide][rustc-guide] also apply to the standard library since 5 | it is built with the same build system, so it is recommended to read it first. 6 | 7 | [rustc-guide]: https://rustc-dev-guide.rust-lang.org/building/how-to-build-and-run.html 8 | 9 | # Println-debugging alloc and core 10 | 11 | Since logging and IO APIs are not available in `alloc` and `core` advice meant for the rest of the compiler 12 | is not applicable here. 13 | 14 | Instead one can either extract the code that should be tested to a normal crate and add debugging statements there or 15 | on POSIX systems one can use the following hack: 16 | 17 | ```rust 18 | extern "C" { 19 | fn dprintf(fd: i32, s: *const u8, ...); 20 | } 21 | 22 | macro_rules! dbg_printf { 23 | ($s:expr) => { 24 | unsafe { dprintf(2, "%s\0".as_ptr(), $s as *const u8); } 25 | } 26 | } 27 | 28 | fn function_to_debug() { 29 | let dbg_str = format!("debug: {}\n\0", "hello world"); 30 | dbg_printf!(dbg_str.as_bytes().as_ptr()); 31 | } 32 | ``` 33 | 34 | Then one can run a test which exercises the code to debug and show the error output via 35 | 36 | ```shell,ignore 37 | ./x.py test library/alloc --test-args --test-args --nocapture 38 | ``` -------------------------------------------------------------------------------- /src/policy/extension-traits.md: -------------------------------------------------------------------------------- 1 | # Why the standard library uses extension traits (and not `cfg`-guarded items) 2 | 3 | A common pattern in the standard library is to put target-specific methods into 4 | extension traits, rather than providing them as `cfg`-guarded methods directly 5 | on objects themselves. For example, the many extension traits in 6 | [`std::os::unix::prelude`](https://doc.rust-lang.org/std/os/unix/prelude/index.html) 7 | provide UNIX-specific methods on standard types. 8 | 9 | The standard library could, instead, provide these methods directly on the 10 | standard types, guarded by `#[cfg(unix)]`. However, it does not do so, and PRs 11 | adding `cfg`-guarded methods are often rejected. 12 | 13 | Providing these methods via extension traits forces code to explicitly use 14 | those extension traits in order to access the methods. This, effectively, 15 | requires code to declare whether it depends on target-specific functionality, 16 | either because the code is target-specific, or because it has appropriately 17 | `cfg`-guarded code for different targets. Without these extension traits, code 18 | could more easily use target-specific functionality "accidentally". 19 | 20 | This policy may change in the future if Rust develops better mechanisms for 21 | helping code explicitly declare its portability, or lack of portability, before 22 | accessing target-specific functionality. 23 | -------------------------------------------------------------------------------- /src/policy/target-code.md: -------------------------------------------------------------------------------- 1 | # Reviewing target-specific code 2 | 3 | When reviewing target-specific code, depending on the [tier] of the target in 4 | question, different level of scrutiny is expected from reviewers. 5 | 6 | For tier 1 targets, the reviewer should perform a full review of the code. 7 | Essentially treat the code as *not* platform specific. 8 | 9 | For tier 2 and tier 3 targets, the reviewer should confirm that the code: 10 | 11 | * Only affects 1 or more of such targets (i.e., is truly target-specific) 12 | * Does not introduce new licensing hazards (e.g., license headers or similar) 13 | * Is either proposed by a target maintainer[^1] or has pinged and received +1s 14 | from at least one target maintainer. Where no maintainer is present, look for 15 | whether the author is reputable and/or affiliated with the target in some way 16 | (e.g., authored original code, works for a company maintaining the target, etc.). 17 | 18 | Note that this review does *not* include checking for correctness or for code 19 | quality. We lack the review bandwidth or expertise to perform detailed reviews 20 | of tier 2 and tier 3 targets. 21 | 22 | [^1]: Target maintainers are listed for most targets in the [platform support] documentation. 23 | 24 | [tier]: https://doc.rust-lang.org/nightly/rustc/platform-support.html 25 | [platform support]: https://doc.rust-lang.org/nightly/rustc/platform-support.html 26 | -------------------------------------------------------------------------------- /src/SUMMARY.md: -------------------------------------------------------------------------------- 1 | # Summary 2 | 3 | - [About this Guide](about.md) 4 | 5 | - [Contributing to the standard libraries]() 6 | - [Building and debugging](./development/building-and-debugging.md) 7 | - [Performance optimizations and benchmarking](./development/perf-benchmarking.md) 8 | - [Writing documentation](./development/how-to-write-documentation.md) 9 | - [Feature lifecycle](./development/feature-lifecycle.md) 10 | - [Stabilizing a feature](./development/stabilization.md) 11 | 12 | - [Breaking changes](./breaking-changes/summary.md) 13 | - [New trait implementations](./breaking-changes/new-trait-impls.md) 14 | - [Prelude](./breaking-changes/prelude.md) 15 | - [Doc changes](./breaking-changes/doc-changes.md) 16 | 17 | - [Policies]() 18 | - [When to add `#[must_use]`](./policy/must-use.md) 19 | - [Specialization](./policy/specialization.md) 20 | - [When to `#[inline]`](./policy/inline.md) 21 | - [Doc alias policy](./policy/doc-alias.md) 22 | - [Safety comments policy](./policy/safety-comments.md) 23 | - [Reviewing target-specific code](./policy/target-code.md) 24 | - [Why the standard library uses extension traits](./policy/extension-traits.md) 25 | 26 | - [Tricky situations]() 27 | - [Drop and `#[may_dangle]`](./tricky/may-dangle.md) 28 | - [Generics and unsafe](./tricky/generics-and-unsafe.md) 29 | 30 | - [The library team](./team/summary.md) 31 | - [Meetings](./team/meetings.md) 32 | - [Membership](./team/membership.md) 33 | - [Reviewing](./team/reviewing.md) 34 | -------------------------------------------------------------------------------- /src/policy/inline.md: -------------------------------------------------------------------------------- 1 | # When to `#[inline]` 2 | 3 | Inlining is a trade-off between potential execution speed, compile time and code size. There's some discussion about it in [this PR to the `hashbrown` crate](https://github.com/rust-lang/hashbrown/pull/119). From the thread: 4 | 5 | > `#[inline]` is very different than simply just an inline hint. As I mentioned before, there's no equivalent in C++ for what `#[inline]` does. In debug mode rustc basically ignores `#[inline]`, pretending you didn't even write it. In release mode the compiler will, by default, codegen an `#[inline]` function into every single referencing codegen unit, and then it will also add `inlinehint`. This means that if you have 16 CGUs and they all reference an item, every single one is getting the entire item's implementation inlined into it. 6 | 7 | You can add `#[inline]`: 8 | 9 | - To public, small, non-generic functions. 10 | 11 | You shouldn't need `#[inline]`: 12 | 13 | - On methods that have any generics in scope. 14 | - On methods on traits that don't have a default implementation. 15 | 16 | `#[inline]` can always be introduced later, so if you're in doubt they can just be removed. 17 | 18 | ## What about `#[inline(always)]`? 19 | 20 | You should just about never need `#[inline(always)]`. It may be beneficial for private helper methods that are used in a limited number of places or for trivial operators. A micro benchmark should justify the attribute. 21 | 22 | ## For reviewers 23 | 24 | `#[inline]` can always be added later, so if there's any debate about whether it's appropriate feel free to defer it by removing the annotations for a start. 25 | -------------------------------------------------------------------------------- /src/team/meetings.md: -------------------------------------------------------------------------------- 1 | # Meetings 2 | 3 | Currently, both the Library Team and the Library API Team have a weekly hour-long meeting. 4 | Both meetings are open to non-members by default, although some might be (partially) private when agenda topics require that. 5 | 6 | The meetings are held as video calls through [Jitsi](https://meet.jit.si/), but everyone is welcome to join without video or even audio. 7 | If you want to participate in meeting discussions through text, you can do so through Jitsi's chat function. 8 | 9 | Meetings and their agendas are announced in the [#t-libs/meetings](https://rust-lang.zulipchat.com/#narrow/stream/259402-t-libs.2Fmeetings) channel on Zulip. 10 | 11 | Agendas are generated by the [`fully-automatic-rust-libs-team-triage-meeting-agenda-generator`](https://github.com/rust-lang/libs-team/tree/main/tools/agenda-generator), 12 | which will include all relevant issues and PRs, such as those tagged with `I-nominated` or `S-waiting-on-team`. 13 | 14 | If you have any specific topics you'd like to have discussed in a meeting, feel free to open an issue on the [`libs-team`](https://github.com/rust-lang/libs-team/) repository 15 | and mark it as `I-nominated` and `T-libs` or `T-libs-api`. Or just leave a message in the Zulip channel. 16 | 17 | All the meetings, including those of the library working groups, can be found on our Google Calendar: 18 | 19 | 20 | 21 | [ICS link](https://calendar.google.com/calendar/ical/9kuu8evq4eh6uacm262k0phri8%40group.calendar.google.com/public/basic.ics) 22 | -------------------------------------------------------------------------------- /src/tricky/generics-and-unsafe.md: -------------------------------------------------------------------------------- 1 | # Generics and unsafe 2 | 3 | Be careful of generic types that interact with unsafe code. Unless the generic type is bounded by an unsafe trait that specifies its contract, we can't rely on the results of generic types being reliable or correct. 4 | 5 | A place where this commonly comes up is with the `RangeBounds` trait. You might assume that the start and end bounds given by a `RangeBounds` implementation will remain the same since it works through shared references. That's not necessarily the case though, an adversarial implementation may change the bounds between calls: 6 | 7 | ```rust,ignore 8 | struct EvilRange(Cell); 9 | 10 | impl RangeBounds for EvilRange { 11 | fn start_bound(&self) -> Bound<&usize> { 12 | Bound::Included(if self.0.get() { 13 | &1 14 | } else { 15 | self.0.set(true); 16 | &0 17 | }) 18 | } 19 | fn end_bound(&self) -> Bound<&usize> { 20 | Bound::Unbounded 21 | } 22 | } 23 | ``` 24 | 25 | This has [caused problems in the past](https://github.com/rust-lang/rust/issues/81138) for code making safety assumptions based on bounds without asserting they stay the same. 26 | 27 | Code using generic types to interact with unsafe should try convert them into known types first, then work with those instead of the generic. For our example with `RangeBounds`, this may mean converting into a concrete `Range`, or a tuple of `(Bound, Bound)`. 28 | 29 | ## For reviewers 30 | 31 | Look out for generic functions that also contain unsafe blocks and consider how adversarial implementations of those generics could violate safety. 32 | -------------------------------------------------------------------------------- /src/policy/unsafe-preconditions.md: -------------------------------------------------------------------------------- 1 | # Runtime checks for preconditions of `unsafe fn` 2 | 3 | When possible, a debug assertion for the preconditions of an `unsafe fn` should be added inside the body of said function, before the implementation exploits the precondition. 4 | 5 | The compiler supports two kinds of debug assertions. Those that branch on `cfg(debug_assertions)` such as `debug_assert!` or `debug_assert_nounwind!` will be compiled out of the standard library distributed by rustup. Such checks are still valuable to add because they can be used by external tools like [cargo-careful](https://crates.io/crates/cargo-careful) or [cargo-fuzz](https://crates.io/crates/cargo-fuzz), users of `-Zbuild-std` or just our own CI (because it enables both optimizations and debug assertions). 6 | 7 | When it does not impose a significant compile-time burden, debug assertions should be implemented by branching on `intrinsics::debug_assertions()`. That intrinsic is only lowered after monomorphization, so calls to that intrinsic which appear in public and `#[inline]` or generic functions will be enabled by users in builds that enable debug assertions. We have a macro for automating the best use pattern for this intrinsic, `intrinsics::assert_unsafe_precondition!`. This macro shifts all the actual checking logic into a monomorphic and `#[inline(never)]` function, which ensures that the check and error reporting logic is compiled once instead of again and again for each monomorphization that uses the check. 8 | 9 | `assert_unsafe_precondition!` also uses `const_eval_select` internally so that it is only enabled at runtime. When you need a runtime-only check (for example, if your precondition is about pointer alignment) but the compile-time overhead of the branch and call that it expands to is too significant, it is fine to write `#[cfg(debug_assertions)] assert_unsafe_precondition!`. 10 | -------------------------------------------------------------------------------- /src/policy/must-use.md: -------------------------------------------------------------------------------- 1 | # When to add `#[must_use]` 2 | 3 | The `#[must_use]` attribute can be applied to types or functions when failing to explicitly consider them or their output is almost certainly a bug. 4 | 5 | As an example, `Result` is `#[must_use]` because failing to consider it may indicate a caller didn't realise a method was fallible: 6 | 7 | ```rust,ignore 8 | // Is `check_status` infallible? Or did we forget to look at its `Result`? 9 | check_status(); 10 | ``` 11 | 12 | Operators like `saturating_add` are also `#[must_use]` because failing to consider their output might indicate a caller didn't realise they don't mutate the left-hand-side: 13 | 14 | ```rust,ignore 15 | // A caller might assume this method mutates `a` 16 | a.saturating_add(b); 17 | ``` 18 | 19 | Combinators produced by the `Iterator` trait are `#[must_use]` because failing to use them might indicate a caller didn't realize `Iterator`s are lazy and won't actually do anything unless you drive them: 20 | 21 | ```rust,ignore 22 | // A caller might not realise this code won't do anything 23 | // unless they call `collect`, `count`, etc. 24 | v.iter().map(|x| println!("{}", x)); 25 | ``` 26 | 27 | On the other hand, `thread::JoinHandle` isn't `#[must_use]` because spawning fire-and-forget work is a legitimate pattern and forcing callers to explicitly ignore handles could be a nuisance rather than an indication of a bug: 28 | 29 | ```rust,ignore 30 | thread::spawn(|| { 31 | // this background work isn't waited on 32 | }); 33 | ``` 34 | 35 | ## For reviewers 36 | 37 | Look for any legitimate use-cases where `#[must_use]` will cause callers to explicitly ignore values. If these are common then `#[must_use]` probably isn't appropriate. 38 | 39 | The `#[must_use]` attribute only produces warnings, so it can technically be introduced at any time. To avoid accumulating nuisance warnings though ping `@rust-lang/libs` for input before adding new `#[must_use]` attributes to existing types and functions. 40 | -------------------------------------------------------------------------------- /.github/workflows/gh-pages.yml: -------------------------------------------------------------------------------- 1 | name: github pages 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | 8 | jobs: 9 | deploy: 10 | runs-on: ubuntu-22.04 11 | steps: 12 | - uses: actions/checkout@v3 13 | 14 | - name: Read .env 15 | id: mdbook-version 16 | run: | 17 | . ./.env 18 | echo "MDBOOK_VERSION=${MDBOOK_VERSION}" >> $GITHUB_OUTPUT 19 | echo "MDBOOK_LINKCHECK_VERSION=${MDBOOK_LINKCHECK_VERSION}" >> $GITHUB_OUTPUT 20 | echo "MDBOOK_TOC_VERSION=${MDBOOK_TOC_VERSION}" >> $GITHUB_OUTPUT 21 | 22 | - name: Cache binaries 23 | id: mdbook-cache 24 | uses: actions/cache@v3 25 | with: 26 | path: | 27 | ~/.cargo/bin 28 | key: ${{ runner.os }}-${{ steps.mdbook-version.outputs.MDBOOK_VERSION }}--${{ steps.mdbook-version.outputs.MDBOOK_LINKCHECK_VERSION }}--${{ steps.mdbook-version.outputs.MDBOOK_TOC_VERSION }} 29 | 30 | - name: Install latest stable Rust toolchain 31 | if: steps.mdbook-cache.outputs.cache-hit != 'true' 32 | run: | 33 | rustup update stable 34 | rustup override set stable 35 | 36 | - name: Install Dependencies 37 | if: steps.mdbook-cache.outputs.cache-hit != 'true' 38 | run: | 39 | cargo install mdbook --version ${{ steps.mdbook-version.outputs.MDBOOK_VERSION }} 40 | cargo install mdbook-linkcheck --version ${{ steps.mdbook-version.outputs.MDBOOK_LINKCHECK_VERSION }} 41 | cargo install mdbook-toc --version ${{ steps.mdbook-version.outputs.MDBOOK_TOC_VERSION }} 42 | 43 | - name: Build book 44 | run: | 45 | . ./.env 46 | mdbook build 47 | cp CNAME $GIT_DEPLOY_DIR 48 | 49 | - name: Deploy to gh-pages 50 | run: | 51 | git config --global user.email "Runner@GH Actions Deployment" 52 | git config --global user.name "GH Actions Runner" 53 | chmod u+x ci/ghpages-deploy.sh 54 | ./ci/ghpages-deploy.sh 55 | -------------------------------------------------------------------------------- /src/team/membership.md: -------------------------------------------------------------------------------- 1 | # Membership 2 | 3 | ## Library Contributors 4 | 5 | Membership to Library Contributors can be offered by the Library Team once 6 | a regular contributor has made a number of significant contributions over some period of time, 7 | and has shown to have a good judgement on what changes are acceptable. 8 | 9 | ## The Library Team and Library API Team 10 | 11 | The Library Team and Library API Team pick their own members, 12 | although it's expected that new members come from the Library Contributors or another Rust team, 13 | and have already been involved in relevant library work. 14 | 15 | ## The process 16 | 17 | In all cases, the process of adding a new members goes as follows: 18 | 19 | 1. A member of the Library (API) Team proposes the addition of a contributor on our private Zulip channel. 20 | This proposal includes: 21 | - A short description of what this person has been working on; how they have been contributing. 22 | - A few specific examples of cases where this person clearly communicated their ideas. 23 | - A few specific examples that show this person understands what are and what aren't acceptable changes.\ 24 | Someone who makes significant contributions but usually needs to make large adjustments to their PRs might be a wonderful external contributor, 25 | but might not yet be a good match for membership with review permissions expecting to judge other contributions. 26 | 2. Every single team member is asked for their input. No team member must have any objections. 27 | - Objections are ideally shared with the entire team, but may also be shared privately with the team lead or the moderation team. 28 | - Objections ideally include examples showing behavior not in line with the expectations described under step 1 29 | (or the code of conduct). 30 | 3. The team lead reaches out to the moderation team to ask if they are aware of any objections. 31 | 4. Only once the team members and the moderation team agree, the new contributor is invited to join. 32 | 5. If the new contributor agrees too, a PR is sent to the `team` repository to add them. 33 | 6. A blog post is published in the Internals Blog with a short introduction of the new contributor. 34 | The contents of this post can be based on some of the points brought up in the email from step 1. 35 | The contents are first checked with the new contributor before it is published. 36 | -------------------------------------------------------------------------------- /src/tricky/may-dangle.md: -------------------------------------------------------------------------------- 1 | # Drop and `#[may_dangle]` 2 | 3 | A generic `Type` that manually implements `Drop` should consider whether a `#[may_dangle]` attribute is appropriate on `T`. The [Nomicon](https://doc.rust-lang.org/nomicon/dropck.html) has some details on what `#[may_dangle]` is all about. 4 | 5 | If a generic `Type` has a manual drop implementation that may also involve dropping `T` then dropck needs to know about it. If `Type`'s ownership of `T` is expressed through types that don't drop `T` themselves such as `ManuallyDrop`, `*mut T`, or `MaybeUninit` then `Type` also [needs a `PhantomData` field](https://rust-lang.github.io/rfcs/0769-sound-generic-drop.html#phantom-data) to tell dropck that `T` may be dropped. Types in the standard library that use the internal `Unique` pointer type don't need a `PhantomData` marker field. That's taken care of for them by `Unique`. 6 | 7 | As a real-world example of where this can go wrong, consider an `OptionCell` that looks something like this: 8 | 9 | ```rust,ignore 10 | struct OptionCell { 11 | is_init: bool, 12 | value: MaybeUninit, 13 | } 14 | 15 | impl Drop for OptionCell { 16 | fn drop(&mut self) { 17 | if self.is_init { 18 | // Safety: `value` is guaranteed to be fully initialized when `is_init` is true. 19 | // Safety: The cell is being dropped, so it can't be accessed again. 20 | unsafe { self.value.assume_init_drop() }; 21 | } 22 | } 23 | } 24 | ``` 25 | 26 | Adding a `#[may_dangle]` attribute to this `OptionCell` that didn't have a `PhantomData` marker field opened up [a soundness hole](https://github.com/rust-lang/rust/issues/76367) for `T`'s that didn't strictly outlive the `OptionCell`, and so could be accessed after being dropped in their own `Drop` implementations. The correct application of `#[may_dangle]` also required a `PhantomData` field: 27 | 28 | ```diff,ignore 29 | struct OptionCell { 30 | is_init: bool, 31 | value: MaybeUninit, 32 | + _marker: PhantomData, 33 | } 34 | 35 | - impl Drop for OptionCell { 36 | + unsafe impl<#[may_dangle] T> Drop for OptionCell { 37 | ``` 38 | 39 | ## For reviewers 40 | 41 | If there's a manual `Drop` implementation, consider whether `#[may_dangle]` is appropriate. If it is, make sure there's a `PhantomData` too either through `Unique` or as a field directly. 42 | -------------------------------------------------------------------------------- /src/policy/doc-alias.md: -------------------------------------------------------------------------------- 1 | doc alias policy 2 | ================ 3 | 4 | Rust's documentation supports adding aliases to any declaration (such as a 5 | function, type, or constant), using the syntax `#[doc(alias = "name")]`. We 6 | want to use doc aliases to help people find what they're looking for, while 7 | keeping those aliases maintainable and high-value. This policy outlines the 8 | cases where we add doc aliases, and the cases where we omit those aliases. 9 | 10 | - We must have a reasonable expectation that people might search for the term 11 | in the documentation search. Rust's documentation provides a name search, not 12 | a full-text search; as such, we expect that people may search for plausible 13 | names, but that for more general documentation searches they'll turn to a web 14 | search engine. 15 | - Related: we don't expect that people are currently searching Rust 16 | documentation for language-specific names from arbitrary languages they're 17 | familiar with, and we don't want to add that as a new documentation search 18 | feature; please don't add aliases based on your favorite language. Those 19 | mappings should live in separate guides or references. We do expect that 20 | people might look for the Rust name of a function they reasonably expect to 21 | exist in Rust (e.g. a system function or a C library function), to try to 22 | figure out what Rust called that function. 23 | - The proposed alias must be a name we would plausibly have used for the 24 | declaration. For instance, `mkdir` for `create_dir`, or `rmdir` for 25 | `remove_dir`, or `popcnt` and `popcount` for `count_ones`, or `umask` for 26 | `mode`. This feeds into the reasonable expectation that someone might search 27 | for the name and expect to find it ("what did Rust call `mkdir`"). 28 | - There must be an obvious single target for the alias that is an *exact* 29 | analogue of the aliased name. We will not add the same alias to multiple 30 | declarations. (`const` and non-`const` versions of the same function are 31 | fine.) We will also not add an alias for a function that's only somewhat 32 | similar or related. 33 | - The alias must not conflict with the actual name of any existing declaration. 34 | - As a special case for stdarch, aliases from exact assembly instruction names 35 | to the corresponding intrinsic function are welcome, as long as they don't 36 | conflict with other names. 37 | -------------------------------------------------------------------------------- /src/team/reviewing.md: -------------------------------------------------------------------------------- 1 | # Reviewing 2 | 3 | Every member of the Library Team, Library API Team, and Library Contributors has 'r+ rights'. 4 | That is, the ability to approve a PR and instruct [`@bors`](https://bors.rust-lang.org/) 5 | to test and merge it into Rust nightly. 6 | 7 | If you decide to review a PR, thank you! 8 | But please keep in mind: 9 | 10 | - You are always welcome to review any PR, regardless of who it is assigned to. 11 | However, do not approve PRs unless: 12 | - You are confident that nobody else wants to review it first. If you think someone else on the team would be a better person to review it, feel free to reassign it to them. 13 | - You are confident in that part of the code. 14 | - You are confident it will not cause any breakage or regress performance. 15 | - It does not change the public API, including any stable promises we make in documentation, unless there's a finished FCP for the change. 16 | - For unstable API changes/additions, it can be acceptable to skip the RFC process if the design is small and the change is uncontroversial. 17 | Make sure to involve `@rust-lang/libs-api` on such changes. 18 | - Always be polite when reviewing: you are a representative of the Rust project, so it is expected that you will go above and beyond when it comes to the Code of Conduct. 19 | 20 | See for more information on reviewing. 21 | 22 | ## High-five rotation 23 | 24 | Some of the members of the team are part of the 'high-five rotation'; 25 | the list from which the high-five bot picks reviewers to assign new PRs to. 26 | 27 | Being a member of one of the teams does not come with the expectation to be on this list. 28 | However, members of this list should be on at least one of the three library teams. 29 | 30 | If the bot assigns you a PR for which you do not have the time or expertise to review it, 31 | feel free to reassign it to someone else. 32 | To assign it to another random person picked from the high-five rotation, 33 | use `r? rust-lang/libs`. 34 | 35 | If you find yourself unable to do any reviews for an extended period of time, 36 | it might be a good idea to (temporarily) remove yourself from the list. 37 | To add or remove yourself from the list, send a PR to change the 38 | [triagebot configuration file](https://github.com/rust-lang/rust/blob/master/triagebot.toml). 39 | 40 | ## Rolling up 41 | 42 | For library PRs, rolling up (`@bors r+ rollup`) is often fine, 43 | in particular if it's only a new unstable addition or if it only touches docs. 44 | PRs that impact performance should not be rolled up (`@bors rollup=never`), 45 | PRs with subtle platform specific changes might also not be great candiates for rolling up. 46 | See the [rollup guidelines](https://forge.rust-lang.org/compiler/reviews.html#rollups) for more 47 | details on when to rollup. 48 | -------------------------------------------------------------------------------- /src/breaking-changes/new-trait-impls.md: -------------------------------------------------------------------------------- 1 | # Breakage from new trait impls 2 | 3 | A lot of PRs to the standard library are adding new impls for already stable traits, 4 | which can break consumers in many weird and wonderful ways. 5 | Below are some examples of breakage from new trait impls that 6 | may not be obvious just from the change made to the standard library. 7 | 8 | ## Inference breaks when a second generic impl is introduced 9 | 10 | Rust will use the fact that there's only a single impl for a generic trait during inference. 11 | This breaks once a second impl makes the type of that generic ambiguous. 12 | Say we have: 13 | 14 | ```rust,ignore 15 | // in `std` 16 | impl From<&str> for Arc { .. } 17 | ``` 18 | 19 | ```rust,ignore 20 | // in an external `lib` 21 | let b = Arc::from("a"); 22 | ``` 23 | 24 | then we add: 25 | 26 | ```diff 27 | impl From<&str> for Arc { .. } 28 | + impl From<&str> for Arc { .. } 29 | ``` 30 | 31 | then 32 | 33 | ```rust,ignore 34 | let b = Arc::from("a"); 35 | ``` 36 | 37 | will no longer compile, because we've previously been relying on inference to figure out the `T` in `Box`. 38 | 39 | This kind of breakage can be ok, but a [crater](https://github.com/rust-lang/crater/blob/master/docs/bot-usage.md) run should estimate the scope. 40 | 41 | ## Deref coercion breaks when a new impl is introduced 42 | 43 | Rust will use deref coercion to find a valid trait impl if the arguments don't type check directly. 44 | This only seems to occur if there's a single impl so introducing a new one may break consumers relying on deref coercion. 45 | Say we have: 46 | 47 | ```rust,ignore 48 | // in `std` 49 | impl Add<&str> for String { .. } 50 | 51 | impl Deref for String { type Target = str; .. } 52 | ``` 53 | 54 | ```rust,ignore 55 | // in an external `lib` 56 | let a = String::from("a"); 57 | let b = String::from("b"); 58 | 59 | let c = a + &b; 60 | ``` 61 | 62 | then we add: 63 | 64 | ```diff,ignore 65 | impl Add<&str> for String { .. } 66 | + impl Add for String { .. } 67 | ``` 68 | 69 | then 70 | 71 | ```rust,ignore 72 | let c = a + &b; 73 | ``` 74 | 75 | will no longer compile, because we won't attempt to use deref to coerce the `&String` into `&str`. 76 | 77 | This kind of breakage can be ok, but a [crater](https://github.com/rust-lang/crater/blob/master/docs/bot-usage.md) run should estimate the scope. 78 | 79 | ## `#[fundamental]` types 80 | 81 | Type annotated with the `#[fundamental]` attribute have different coherence rules. 82 | See [RFC 1023](https://rust-lang.github.io/rfcs/1023-rebalancing-coherence.html) for details. 83 | That includes: 84 | 85 | - `&T` 86 | - `&mut T` 87 | - `Box` 88 | - `Pin` 89 | 90 | Typically, the scope of breakage in new trait impls is limited to inference and deref-coercion. 91 | New trait impls on `#[fundamental]` types may overlap with downstream impls and cause other kinds of breakage. 92 | 93 | [RFC 1023]: https://rust-lang.github.io/rfcs/1023-rebalancing-coherence.html 94 | -------------------------------------------------------------------------------- /src/team/summary.md: -------------------------------------------------------------------------------- 1 | # The Library Team 2 | 3 | The Rust standard library and the official `rust-lang` crates are 4 | the responsibility of the Library Team. 5 | The Library team makes sure the libraries are maintained, 6 | PRs get reviewed, and issues get handled in time, 7 | although that does not mean the team members are doing all the work themselves. 8 | Many team members and other contributors are involved in this work, 9 | and the team's main task is to guide and enable that work. 10 | 11 | ## The Library API Team 12 | 13 | A very critical aspect of maintaining and evolving the standard library is its stability. 14 | Unlike other crates, we can not release a new major version once in a while for backwards 15 | incompatible changes. Every version of the standard library is semver-compatible 16 | with all previous versions since Rust 1.0. 17 | 18 | This means that we have to be very careful with additions and changes to the public interface. 19 | We can deprecate things if necessary, 20 | but removing items or changing signatures is almost never an option. 21 | As a result, we are very careful with stabilizing additions to the standard library. 22 | Once something is stable, we're basically stuck with it forever. 23 | 24 | To guard the stability and prevent us from adding things we'll regret later, 25 | we have a team that specifically focuses on the public API. 26 | Every RFC and stabilization of a library addition/change goes through a FCP process 27 | in which the members of the Library API Team are asked to sign off on the change. 28 | 29 | The members of this team are not necessarily familiar with the implementation details 30 | of the standard library, but are experienced with API design and understand the details 31 | of breaking changes and how they are avoided. 32 | 33 | ## The Library Contributors 34 | 35 | In addition to the two teams above, we also have the Library Contributors, 36 | which is a somewhat more loosely defined team consisting of those who regularly contribute 37 | or review changes to the standard libraries. 38 | 39 | Many of these contributors have a specific area of expertise, 40 | for example certain data structures or a specific operating system. 41 | 42 | ## Team Membership 43 | 44 | The Library Team will privately discuss potential new members for itself and Library Contributors, 45 | and extend an invitation after all members and the moderation team is on board with the potential addition. 46 | 47 | See [Membership](./membership.md) for details. 48 | 49 | ### r+ permission 50 | 51 | All members of the Library Team, the Library API Team, and the Library Contributors 52 | have the permission to approve PRs, and are expected to handle this with care. 53 | See [Reviewing](./reviewing.md) for details. 54 | 55 | ### high-five rotation 56 | 57 | Some of the members of the team are part of the 'high-five rotation'; 58 | the list from which the high-five bot picks reviewers to assign new PRs to. 59 | 60 | Being a member of one of the teams does not come with the expectation to be on this list. 61 | However, members of this list should be on at least one of the three library teams. 62 | See [Reviewing](./reviewing.md) for details. 63 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: Continuous Integration 2 | 3 | on: 4 | push: 5 | branches: [master] 6 | pull_request: 7 | 8 | jobs: 9 | book-test: 10 | runs-on: ubuntu-22.04 11 | steps: 12 | - uses: actions/checkout@v3 13 | 14 | - name: Read .env 15 | id: mdbook-version 16 | run: | 17 | . ./.env 18 | echo "MDBOOK_VERSION=${MDBOOK_VERSION}" >> $GITHUB_OUTPUT 19 | echo "MDBOOK_LINKCHECK_VERSION=${MDBOOK_LINKCHECK_VERSION}" >> $GITHUB_OUTPUT 20 | echo "MDBOOK_TOC_VERSION=${MDBOOK_TOC_VERSION}" >> $GITHUB_OUTPUT 21 | 22 | - name: Cache binaries 23 | id: mdbook-cache 24 | uses: actions/cache@v3 25 | with: 26 | path: | 27 | ~/.cargo/bin 28 | key: ${{ runner.os }}-${{ steps.mdbook-version.outputs.MDBOOK_VERSION }}--${{ steps.mdbook-version.outputs.MDBOOK_LINKCHECK_VERSION }}--${{ steps.mdbook-version.outputs.MDBOOK_TOC_VERSION }} 29 | 30 | - name: Install latest stable Rust toolchain 31 | if: steps.mdbook-cache.outputs.cache-hit != 'true' 32 | run: | 33 | rustup update stable 34 | rustup override set stable 35 | 36 | - name: Install Dependencies 37 | if: steps.mdbook-cache.outputs.cache-hit != 'true' 38 | run: | 39 | cargo install mdbook --version ${{ steps.mdbook-version.outputs.MDBOOK_VERSION }} 40 | cargo install mdbook-linkcheck --version ${{ steps.mdbook-version.outputs.MDBOOK_LINKCHECK_VERSION }} 41 | cargo install mdbook-toc --version ${{ steps.mdbook-version.outputs.MDBOOK_TOC_VERSION }} 42 | 43 | - name: Test book 44 | run: mdbook test 45 | 46 | book-build: 47 | runs-on: ubuntu-22.04 48 | steps: 49 | - uses: actions/checkout@v3 50 | 51 | - name: Read .env 52 | id: mdbook-version 53 | run: | 54 | . ./.env 55 | echo "MDBOOK_VERSION=${MDBOOK_VERSION}" >> $GITHUB_OUTPUT 56 | echo "MDBOOK_LINKCHECK_VERSION=${MDBOOK_LINKCHECK_VERSION}" >> $GITHUB_OUTPUT 57 | echo "MDBOOK_TOC_VERSION=${MDBOOK_TOC_VERSION}" >> $GITHUB_OUTPUT 58 | 59 | - name: Cache binaries 60 | id: mdbook-cache 61 | uses: actions/cache@v3 62 | with: 63 | path: | 64 | ~/.cargo/bin 65 | key: ${{ runner.os }}-${{ steps.mdbook-version.outputs.MDBOOK_VERSION }}--${{ steps.mdbook-version.outputs.MDBOOK_LINKCHECK_VERSION }}--${{ steps.mdbook-version.outputs.MDBOOK_TOC_VERSION }} 66 | 67 | - name: Install latest stable Rust toolchain 68 | if: steps.mdbook-cache.outputs.cache-hit != 'true' 69 | run: | 70 | rustup update stable 71 | rustup override set stable 72 | 73 | - name: Install Dependencies 74 | if: steps.mdbook-cache.outputs.cache-hit != 'true' 75 | run: | 76 | cargo install mdbook --version ${{ steps.mdbook-version.outputs.MDBOOK_VERSION }} 77 | cargo install mdbook-linkcheck --version ${{ steps.mdbook-version.outputs.MDBOOK_LINKCHECK_VERSION }} 78 | cargo install mdbook-toc --version ${{ steps.mdbook-version.outputs.MDBOOK_TOC_VERSION }} 79 | 80 | - name: Build book for testing 81 | run: mdbook build 82 | -------------------------------------------------------------------------------- /src/policy/safety-comments.md: -------------------------------------------------------------------------------- 1 | # Safety comments 2 | 3 | Using [`unsafe`] blocks is often required in the Rust compiler or standard 4 | library, but this is not done without rules: each `unsafe` block should have 5 | a `SAFETY:` comment explaining why the block is safe, which invariants are 6 | used and must be respected. Below are some examples taken from the standard 7 | library: 8 | 9 | [`unsafe`]: https://doc.rust-lang.org/stable/std/keyword.unsafe.html 10 | 11 | ## Inside `unsafe` elements 12 | 13 | This one shows how an `unsafe` function can pass the requirements through to its 14 | caller with the use of documentation in a `# Safety` section while still having 15 | more invariants needed that are not required from callers. `clippy` has a 16 | lint for `# Safety` sections by the way. 17 | 18 | [See the example on github][as_bytes_mut] 19 | 20 | ```rust,ignore 21 | /// Converts a mutable string slice to a mutable byte slice. 22 | /// 23 | /// # Safety 24 | /// 25 | /// The caller must ensure that the content of the slice is valid UTF-8 26 | /// before the borrow ends and the underlying `str` is used. 27 | /// 28 | /// Use of a `str` whose contents are not valid UTF-8 is undefined behavior. 29 | /// 30 | /// ... 31 | pub unsafe fn as_bytes_mut(&mut self) -> &mut [u8] { 32 | // SAFETY: the cast from `&str` to `&[u8]` is safe since `str` 33 | // has the same layout as `&[u8]` (only libstd can make this guarantee). 34 | // The pointer dereference is safe since it comes from a mutable reference which 35 | // is guaranteed to be valid for writes. 36 | unsafe { &mut *(self as *mut str as *mut [u8]) } 37 | } 38 | ``` 39 | 40 | This example is for a function but the same principle applies to `unsafe trait`s 41 | like [`Send`] or [`Sync`] for example, though they have no `# Safety` section 42 | since their entire documentation is about why they are `unsafe`. 43 | 44 | Note that in the Rust standard library, [`unsafe_op_in_unsafe_fn`] is active 45 | and so each `unsafe` operation in an `unsafe` function must be enclosed in an 46 | `unsafe` block. This makes it easier to review such functions and to document 47 | their `unsafe` parts. 48 | 49 | [`Send`]: https://doc.rust-lang.org/stable/std/marker/trait.Send.html 50 | [`Sync`]: https://doc.rust-lang.org/stable/std/marker/trait.Sync.html 51 | [as_bytes_mut]: https://github.com/rust-lang/rust/blob/a08f25a7ef2800af5525762e981c24d96c14febe/library/core/src/str/mod.rs#L278 52 | [`unsafe_op_in_unsafe_fn`]: https://doc.rust-lang.org/rustc/lints/listing/allowed-by-default.html#unsafe-op-in-unsafe-fn 53 | 54 | ## Inside *safe* elements 55 | 56 | Inside safe elements, a `SAFETY:` comment must not depend on anything from the 57 | caller beside properly constructed types and values (i.e, if your function 58 | receives a reference that is unaligned or null, it is the caller fault if it 59 | fails and not yours). 60 | 61 | `SAFETY` comments in *safe* elements often rely on checks that are done before 62 | the `unsafe` block or on type invariants, like a division by `NonZeroU8` would 63 | not check for `0` before dividing. 64 | 65 | [See the example on github][split_at] 66 | 67 | ```rust,ignore 68 | pub fn split_at(&self, mid: usize) -> (&str, &str) { 69 | // is_char_boundary checks that the index is in [0, .len()] 70 | if self.is_char_boundary(mid) { 71 | // SAFETY: just checked that `mid` is on a char boundary. 72 | unsafe { (self.get_unchecked(0..mid), self.get_unchecked(mid..self.len())) } 73 | } else { 74 | slice_error_fail(self, 0, mid) 75 | } 76 | } 77 | ``` 78 | 79 | [split_at]: https://github.com/rust-lang/rust/blob/a08f25a7ef2800af5525762e981c24d96c14febe/library/core/src/str/mod.rs#L570 80 | -------------------------------------------------------------------------------- /src/policy/specialization.md: -------------------------------------------------------------------------------- 1 | # Using specialization 2 | 3 | Specialization is currently unstable. You can track its progress [here](https://github.com/rust-lang/rust/issues/31844). 4 | 5 | We try to avoid leaning on specialization too heavily, limiting its use to optimizing specific implementations. These specialized optimizations use a private trait to find the correct implementation, rather than specializing the public method itself. Any use of specialization that changes how methods are dispatched for external callers should be carefully considered. 6 | 7 | As an example of how to use specialization in the standard library, consider the case of creating an `Rc<[T]>` from a `&[T]`: 8 | 9 | ```rust,ignore 10 | impl From<&[T]> for Rc<[T]> { 11 | #[inline] 12 | fn from(v: &[T]) -> Rc<[T]> { 13 | unsafe { Self::from_iter_exact(v.iter().cloned(), v.len()) } 14 | } 15 | } 16 | ``` 17 | 18 | It would be nice to have an optimized implementation for the case where `T: Copy`: 19 | 20 | ```rust,ignore 21 | impl From<&[T]> for Rc<[T]> { 22 | #[inline] 23 | fn from(v: &[T]) -> Rc<[T]> { 24 | unsafe { Self::copy_from_slice(v) } 25 | } 26 | } 27 | ``` 28 | 29 | Unfortunately we couldn't have both of these impls normally, because they'd overlap. This is where private specialization can be used to choose the right implementation internally. In this case, we use a trait called `RcFromSlice` that switches the implementation: 30 | 31 | ```rust,ignore 32 | impl From<&[T]> for Rc<[T]> { 33 | #[inline] 34 | fn from(v: &[T]) -> Rc<[T]> { 35 | >::from_slice(v) 36 | } 37 | } 38 | 39 | /// Specialization trait used for `From<&[T]>`. 40 | trait RcFromSlice { 41 | fn from_slice(slice: &[T]) -> Self; 42 | } 43 | 44 | impl RcFromSlice for Rc<[T]> { 45 | #[inline] 46 | default fn from_slice(v: &[T]) -> Self { 47 | unsafe { Self::from_iter_exact(v.iter().cloned(), v.len()) } 48 | } 49 | } 50 | 51 | impl RcFromSlice for Rc<[T]> { 52 | #[inline] 53 | fn from_slice(v: &[T]) -> Self { 54 | unsafe { Self::copy_from_slice(v) } 55 | } 56 | } 57 | ``` 58 | 59 | Only specialization using the `min_specialization` feature should be used. The full `specialization` feature is known to be unsound. 60 | 61 | ## Specialization attributes 62 | 63 | There are two unstable attributes that can be used to allow a trait bound in a specializing implementation that does not appear in the default implementation. 64 | 65 | `rustc_specialization_trait` restricts the implementations of a trait to be "always applicable". Implementing traits annotated with `rustc_specialization_trait` is unstable, so this should not be used on any stable traits exported from the standard library. `Sized` is an exception, and can have this attribute because it already cannot be implemented by an `impl` block. 66 | **Note**: `rustc_specialization_trait` only prevents incorrect monomorphizations, it does not prevent a type from being coerced between specialized and unspecialized types which can be important when specialization must be applied consistently. See [rust-lang/rust#85863](https://github.com/rust-lang/rust/issues/85863) for more details. 67 | 68 | `rustc_unsafe_specialization_marker` allows specializing on a trait with no associated items. The attribute is `unsafe` because lifetime constraints from the implementations of the trait are not considered when specializing. The following example demonstrates a limitation of `rustc_unsafe_specialization_marker`, the specialized implementation is used for *all* shared reference types, not just those with `'static` lifetime. Because of this, new uses of `rustc_unsafe_specialization_marker` should be avoided. 69 | 70 | ```rust,ignore 71 | #[rustc_unsafe_specialization_marker] 72 | trait StaticRef {} 73 | 74 | impl StaticRef for &'static T {} 75 | 76 | trait DoThing: Sized { 77 | fn do_thing(self); 78 | } 79 | 80 | impl DoThing for T { 81 | default fn do_thing(self) { 82 | // slow impl 83 | } 84 | } 85 | 86 | impl DoThing for T { 87 | fn do_thing(self) { 88 | // fast impl 89 | } 90 | } 91 | ``` 92 | 93 | `rustc_unsafe_specialization_marker` exists to allow existing specializations that are based on marker traits exported from `std`, such as `Copy`, `FusedIterator` or `Eq`. 94 | -------------------------------------------------------------------------------- /src/development/how-to-write-documentation.md: -------------------------------------------------------------------------------- 1 | # How to write documentation 2 | 3 | This document explains how to write documentation for the std/core public APIs. 4 | 5 | Let's start with some general information: 6 | 7 | ### When to use inline code blocks 8 | 9 | Whenever you are talking about a type or anything code related, it should be in a 10 | inline code block. As a reminder, a inline code block is created with backticks 11 | (\`). For example: 12 | 13 | 14 | ```text 15 | This a `Vec` and it has a method `push` which you can call by doing `Vec::push`. 16 | ``` 17 | 18 | ### When to use intra-doc links 19 | 20 | Intra-doc links (you can see the full explanations for the feature 21 | [here](https://doc.rust-lang.org/rustdoc/write-documentation/linking-to-items-by-name.html)) 22 | should be used as much as possible whenever a type is mentioned. 23 | 24 | Little note: when you are documenting an item, there is no need to link to it. 25 | So, if you write documentation for the `String::push_str` method, there is 26 | no need to link to the `push_str` method or the `String` type. 27 | 28 | ### Code blocks 29 | 30 | With rustdoc, code blocks are tested (because they are treated as Rust code 31 | blocks by default). It allows us to know if the documentation is up to date. As 32 | such, please avoid using `ignore` as much as possible on code blocks! If you 33 | want as a language other than Rust, simply set it in the code block tags: 34 | 35 | ````text 36 | ```text 37 | This is not rust code! 38 | ``` 39 | ```` 40 | 41 | Some special cases: 42 | * If the code example cannot be run (when documenting a I/O item for example), 43 | use `no_run`. 44 | * If it is expected to fail, use `should_panic`. 45 | * If it is expected to fail compilation (which be quite rare!), use `compile_fail`. 46 | 47 | You can find more information about code blocks 48 | [here](https://doc.rust-lang.org/rustdoc/write-documentation/documentation-tests.html). 49 | 50 | ## How to write documentation for a module 51 | 52 | A module is supposed to contain "similar" items. As such, its documentation is 53 | supposed to give an overview and eventually **a base** to understand what the 54 | items it contains are doing. 55 | 56 | You can take a look at the 57 | [f32 module](https://doc.rust-lang.org/nightly/std/f32/index.html) or at the 58 | [fmt module](https://doc.rust-lang.org/nightly/std/fmt/index.html) to see 59 | good examples. 60 | 61 | ## How to write documentation for functions/methods 62 | 63 | The basic format of each documented methods/functions should roughly look like this: 64 | 65 | ```text 66 | [explanations] 67 | 68 | [example(s)] 69 | ``` 70 | 71 | ### Explanations 72 | 73 | By `explanations` we mean that the text should explain what the method and what 74 | each of its arguments are for. Let's take this method for example: 75 | 76 | ```rust,ignore 77 | pub fn concat_str(&self, s: &str) -> String { 78 | if s.is_empty() { 79 | panic!("empty concat string"); 80 | } 81 | format!("{}{}", self.string, s) 82 | } 83 | ``` 84 | 85 | The explanation should look like this: 86 | 87 | ```text 88 | Returns a new [`String`] which contains `&self` content with `s` added at the end. 89 | ``` 90 | 91 | ### Panic? 92 | 93 | If the function/method can panic in certain circumstances, it must to be 94 | mentioned! This explanation needs to be prepended by a `Panics` title: 95 | 96 | ```text 97 | # Panics 98 | 99 | `concat_str` panics if `s` is empty. 100 | ``` 101 | 102 | ### Examples 103 | 104 | As for the examples, they have to show the usage of the function/method. Just 105 | like the `panic` section, they need to be prepended by a `Example` title (plural 106 | if there is more than one). 107 | 108 | It is better if you use `assert*!` macros at the end to ensure that the example 109 | is working as expected. It also allows the readers to understand more easily 110 | what the function is doing (or returning). 111 | 112 | ````text 113 | # Example 114 | 115 | ``` 116 | let s = MyType::new("hello "); 117 | assert_eq!("hello Georges", s.concat_str("Georges").as_str()); 118 | ``` 119 | ```` 120 | 121 | ## How to write documentation for other items 122 | 123 | It is mostly the same as for methods and functions except that the examples 124 | are (strongly) recommended and not mandatory. 125 | 126 | A good example often shows how to create the item. 127 | -------------------------------------------------------------------------------- /src/development/feature-lifecycle.md: -------------------------------------------------------------------------------- 1 | # The feature lifecycle 2 | 3 | ## Identifying the problem 4 | 5 | The first step before proposing any change to the standard library is to properly identify the problem that is trying to be solved. This helps to identify cases of the [XY problem] where a better solution exists without needing any changes to the standard library. 6 | 7 | For this reason it is helpful to focus on real problems that people are encountering, rather than theoretical concerns about API design. 8 | 9 | [XY problem]: https://en.wikipedia.org/wiki/XY_problem 10 | 11 | ## Suitability for the standard library 12 | 13 | Unlike third party crates on crates.io, the Rust standard library is not versioned. This means that any stable API that is added can *never* be removed or modified in a backwards-incompatible way. For this reason, the standard library maintainers place a high bar on any change to the standard library API. 14 | 15 | APIs that are well suited to the standard library are things that require language and/or compiler support, or that extend existing standard library types. Complex APIs that are expected to evolve over time (e.g. GUI frameworks) are a poor fit due to the lack of versioning. 16 | 17 | The API Change Proposal process is intended to be a lightweight first step to 18 | getting new APIs added to the standard library. The goal of this process is to 19 | make sure proposed API changes have the best chance of success. The ACP process 20 | accomplishes this by ensuring all changes are reviewed by the library API team, 21 | who will evaluate the proposal and accept it if they are optimistic that the proposal will 22 | be merged and pass its eventual FCP. 23 | 24 | You can create an ACP in the `rust-lang/libs-team` repo using [this issue template](https://github.com/rust-lang/libs-team/issues/new?assignees=&labels=api-change-proposal%2C+T-libs-api&template=api-change-proposal.md&title=%28My+API+Change+Proposal%29). This should include a sketch of the proposed API, but does not have to be the final design that will be implemented. 25 | 26 | Note that an ACP is not strictly required: you can just go ahead and submit a pull request with an implementation of your proposed API, with the risk of wasted effort if the library team ends up rejecting this feature. However do note that this risk is always present even if an ACP is accepted, as the library team can end up rejecting a feature in the later parts of the stabilization process. 27 | 28 | ## API design exploration 29 | 30 | Once a feature is deemed suitable for inclusion in the standard library, the exact design should be iterated on to find the best way to express it as a Rust API. This iteration should happen in community forums such as [Rust internals](https://internals.rust-lang.org/) where all members of the community can comment and propose improvements. 31 | 32 | Keep the following points in mind during the discussion: 33 | - Try to achieve a balance between generality and specificity: 34 | - An overly general API tends to be difficult to use for common use cases, and has a complex API surface. This makes it difficult to review and maintain, and it may be a better fit for an external crate. 35 | - An overly specific API does not cover all common use cases, and may require further API changes in the future to accomodate these use cases. 36 | - An alternative that should *always* be considered is simply adding this feature via a third party crate. This is even possible when adding new methods to standard library types by using extension traits. 37 | - In the case of "convenience" functions which are simply shorthands for something that is already possible with existing APIs, the cost of extending the standard library surface should be weighed against the ergonomic impact of the new functions. 38 | - For example, too many convenience methods on a type makes navigating the documentation more difficult. 39 | - Additionally, consider whether this method is likely to be deprecated in the future if a language-level improvement makes it unnecessary. 40 | 41 | The library team itself is not directly involved in this discussion, but individual members may comment to provide feedback. If significant changes have occurred since the ACP, another one may be proposed at this point to have the design validated by the library API team. 42 | 43 | ## Implementation 44 | 45 | Once the API design space has been explored, an implementation based on the favored solution should be proposed as a pull request to the `rust-lang/rust` repository. 46 | 47 | The pull request should include a summary of the alternatives that were considered. This is helpful for reviewers since it avoids duplicating this exploration work as part of the review. A PR submitted without this may be closed with a request to explore more alternatives. 48 | 49 | If an ACP has not been filed for the proposed feature, the PR will need to be reviewed by the library API team to determine its suitability for the standard library. 50 | 51 | ## Tracking and stabilization 52 | 53 | Before a PR is merged, you will be asked to open a tracking issue which will track the progress of the feature until its [stabilization](stabilization.md). 54 | 55 | There are two exceptions to this: 56 | - Modifications of an existing unstable API can re-use the existing tracking issue for this API. 57 | - Changes that are instantly stable (e.g. trait implementations on stable types) do not need a tracking issue. However, such changes need extra scrutiny as there will be no chance to adjust the API during an unstable period. 58 | -------------------------------------------------------------------------------- /src/development/perf-benchmarking.md: -------------------------------------------------------------------------------- 1 | # Library optimizations and benchmarking 2 | 3 | Recommended reading: [The Rust performance book](https://nnethercote.github.io/perf-book/title-page.html) 4 | 5 | ## What to optimize 6 | 7 | It's preferred to optimize code that shows up as significant in real-world code. 8 | E.g. it's more beneficial to speed up `[T]::sort` than it is to shave off a small allocation in `Command::spawn` 9 | because the latter is dominated by its syscall cost. 10 | 11 | Issues about slow library code are labeled as [I-slow T-libs](https://github.com/rust-lang/rust/issues?q=is%3Aissue+is%3Aopen+label%3AI-slow+label%3AT-libs) 12 | and those about code size as [I-heavy T-libs](https://github.com/rust-lang/rust/issues?q=is%3Aissue+is%3Aopen+label%3AI-heavy+label%3AT-libs) 13 | 14 | ## Vectorization 15 | 16 | Currently only baseline target features (e.g. SSE2 on x86_64-unknown-linux-gnu) can be used in core and alloc because 17 | runtime feature-detection is only available in std. 18 | Where possible the preferred way to achieve vectorization is by shaping code in a way that the compiler 19 | backend's auto-vectorization passes can understand. This benefits user crates compiled with additional target features 20 | when they instantiate generic library functions, e.g. iterators. 21 | 22 | ## rustc-perf 23 | 24 | For parts of the standard library that are heavily used by rustc itself it can be convenient to use 25 | [the benchmark server](https://github.com/rust-lang/rustc-perf/tree/master/collector#benchmarking). 26 | 27 | Since it only measures compile-time but not runtime performance of crates it can't be used to benchmark for features 28 | that aren't used by the compiler, e.g. floating point code, linked lists, mpsc channels, etc. 29 | For those explicit benchmarks must be written or extracted from real-world code. 30 | 31 | ## Built-in Microbenchmarks 32 | 33 | The built-in benchmarks use [cargo bench](https://doc.rust-lang.org/nightly/unstable-book/library-features/test.html) 34 | and can be found in the `benches` directory for `core` and `alloc` and in `test` modules in `std`. 35 | 36 | The benchmarks are automatically executed run in a loop by `Bencher::iter` to average the runtime over many loop-iterations. 37 | For CPU-bound microbenchmarks the runtime of a single iteration should be in the range of nano- to microseconds. 38 | 39 | To run a specific can be invoked without recompiling rustc 40 | via `./x bench library/ --stage 0 --test-args `. 41 | 42 | `cargo bench` measures wall-time. This often is good enough, but small changes such as saving a few instructions 43 | in a bigger function can get drowned out by system noise. In such cases the following changes can make runs more 44 | reproducible: 45 | 46 | * disable incremental builds in `config.toml` 47 | * build std and the benchmarks with `RUSTFLAGS_BOOTSTRAP="-Ccodegen-units=1"` 48 | * ensure the system is as idle as possible 49 | * [disable ASLR](https://man7.org/linux/man-pages/man8/setarch.8.html) 50 | * [pinning](https://man7.org/linux/man-pages/man1/taskset.1.html) the benchmark process to a specific core 51 | * change the CPU [scaling governor](https://wiki.archlinux.org/title/CPU_frequency_scaling#Scaling_governors) 52 | to a fixed-frequency one (`performance` or `powersave`) 53 | * [disable clock boosts](https://wiki.archlinux.org/title/CPU_frequency_scaling#Configuring_frequency_boosting), 54 | especially on thermal-limited systems such as laptops 55 | 56 | ## Standalone tests 57 | 58 | If `x` or the cargo benchmark harness get in the way it can be useful to extract the benchmark into a separate crate, 59 | e.g. to run it under `perf stat` or cachegrind. 60 | 61 | Build the standard library and link [stage0-sysroot](https://rustc-dev-guide.rust-lang.org/building/how-to-build-and-run.html#creating-a-rustup-toolchain) 62 | as rustup toolchain and then use that to build the standalone benchmark with a modified standard library. 63 | 64 | If the std rebuild times are too long for fast iteration it can be useful to not only extract the benchmark but also 65 | the code under test into a separate crate. 66 | 67 | ## Running under perf-record 68 | 69 | If extracting the code into a separate crate is impractical one can first build the benchmark and then run it again 70 | under `perf record` and then drill down to the benchmark kernel with `perf report`. 71 | 72 | ```terminal,ignore 73 | # 1CGU to reduce inlining changes and code reorderings, debuginfo for source annotations 74 | $ export RUSTFLAGS_BOOTSTRAP="-Ccodegen-units=1 -Cdebuginfo=2" 75 | 76 | # build benchmark without running it 77 | $ ./x bench --stage 0 library/core/ --test-args skipallbenches 78 | 79 | # run the benchmark under perf 80 | $ perf record --call-graph dwarf -e instructions ./x bench --stage 0 library/core/ --test-args 81 | $ perf report 82 | ``` 83 | 84 | By renaming `perf.data` to keep it from getting overwritten by subsequent runs it can be later compared to runs with 85 | a modified library with `perf diff`. 86 | 87 | ## comparing assembly 88 | 89 | While `perf report` shows assembly of the benchmark code it can sometimes be difficult to get a good overview of what 90 | changed, especially when multiple benchmarks were affected. As an alternative one can extract and diff the assembly 91 | directly from the benchmark suite. 92 | 93 | ```terminal,ignore 94 | # 1CGU to reduce inlining changes and code reorderings, debuginfo for source annotations 95 | $ export RUSTFLAGS_BOOTSTRAP="-Ccodegen-units=1 -Cdebuginfo=2" 96 | 97 | # build benchmark libs 98 | $ ./x bench --stage 0 library/core/ --test-args skipallbenches 99 | 100 | # this should print something like the following 101 | Running benches/lib.rs (build/x86_64-unknown-linux-gnu/stage0-std/x86_64-unknown-linux-gnu/release/deps/corebenches-2199e9a22e7b1f4a) 102 | 103 | # get the assembly for all the benchmarks 104 | $ objdump --source --disassemble --wide --no-show-raw-insn --no-addresses \ 105 | build/x86_64-unknown-linux-gnu/stage0-std/x86_64-unknown-linux-gnu/release/deps/corebenches-2199e9a22e7b1f4a \ 106 | | rustfilt > baseline.asm 107 | 108 | # switch to the branch with the changes 109 | $ git switch feature-branch 110 | 111 | # repeat the procedure above 112 | $ ./x bench ... 113 | $ objdump ... > changes.asm 114 | 115 | # compare output 116 | $ kdiff3 baseline.asm changes.asm 117 | ``` 118 | 119 | This can also be applied to standalone benchmarks. 120 | -------------------------------------------------------------------------------- /ci/ghpages-deploy.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # This file was taken from https://github.com/X1011/git-directory-deploy/blob/e37ac94cda4bfc5773c0f01d89d8c875a21ab4f9/deploy.sh, 4 | # Copyright 2013-2021 Daniel Smith 5 | # All rights reserved. 6 | # It's licensed under the terms of the 3-clause BSD license. 7 | 8 | set -o errexit #abort if any command fails 9 | me=$(basename "$0") 10 | 11 | help_message="\ 12 | Usage: $me [-c FILE] [] 13 | Deploy generated files to a git branch. 14 | 15 | Options: 16 | 17 | -h, --help Show this help information. 18 | -v, --verbose Increase verbosity. Useful for debugging. 19 | -e, --allow-empty Allow deployment of an empty directory. 20 | -m, --message MESSAGE Specify the message used when committing on the 21 | deploy branch. 22 | -n, --no-hash Don't append the source commit's hash to the deploy 23 | commit's message. 24 | -c, --config-file PATH Override default & environment variables' values 25 | with those in set in the file at 'PATH'. Must be the 26 | first option specified. 27 | 28 | Variables: 29 | 30 | GIT_DEPLOY_DIR Folder path containing the files to deploy. 31 | GIT_DEPLOY_BRANCH Commit deployable files to this branch. 32 | GIT_DEPLOY_REPO Push the deploy branch to this repository. 33 | 34 | These variables have default values defined in the script. The defaults can be 35 | overridden by environment variables. Any environment variables are overridden 36 | by values set in a '.env' file (if it exists), and in turn by those set in a 37 | file specified by the '--config-file' option." 38 | 39 | parse_args() { 40 | # Set args from a local environment file. 41 | if [ -e ".env" ]; then 42 | source .env 43 | fi 44 | 45 | # Set args from file specified on the command-line. 46 | if [[ $1 = "-c" || $1 = "--config-file" ]]; then 47 | source "$2" 48 | shift 2 49 | fi 50 | 51 | # Parse arg flags 52 | # If something is exposed as an environment variable, set/overwrite it 53 | # here. Otherwise, set/overwrite the internal variable instead. 54 | while : ; do 55 | if [[ $1 = "-h" || $1 = "--help" ]]; then 56 | echo "$help_message" 57 | return 0 58 | elif [[ $1 = "-v" || $1 = "--verbose" ]]; then 59 | verbose=true 60 | shift 61 | elif [[ $1 = "-e" || $1 = "--allow-empty" ]]; then 62 | allow_empty=true 63 | shift 64 | elif [[ ( $1 = "-m" || $1 = "--message" ) && -n $2 ]]; then 65 | commit_message=$2 66 | shift 2 67 | elif [[ $1 = "-n" || $1 = "--no-hash" ]]; then 68 | GIT_DEPLOY_APPEND_HASH=false 69 | shift 70 | else 71 | break 72 | fi 73 | done 74 | 75 | # Set internal option vars from the environment and arg flags. All internal 76 | # vars should be declared here, with sane defaults if applicable. 77 | 78 | # Source directory & target branch. 79 | deploy_directory=${GIT_DEPLOY_DIR:-dist} 80 | deploy_branch=${GIT_DEPLOY_BRANCH:-gh-pages} 81 | 82 | #if no user identity is already set in the current git environment, use this: 83 | default_username=${GIT_DEPLOY_USERNAME:-deploy.sh} 84 | default_email=${GIT_DEPLOY_EMAIL:-} 85 | 86 | #repository to deploy to. must be readable and writable. 87 | repo=${GIT_DEPLOY_REPO:-origin} 88 | 89 | #append commit hash to the end of message by default 90 | append_hash=${GIT_DEPLOY_APPEND_HASH:-true} 91 | } 92 | 93 | main() { 94 | parse_args "$@" 95 | 96 | enable_expanded_output 97 | 98 | if ! git diff --exit-code --quiet --cached; then 99 | echo Aborting due to uncommitted changes in the index >&2 100 | return 1 101 | fi 102 | 103 | commit_title=`git log -n 1 --format="%s" HEAD` 104 | commit_hash=` git log -n 1 --format="%H" HEAD` 105 | 106 | #default commit message uses last title if a custom one is not supplied 107 | if [[ -z $commit_message ]]; then 108 | commit_message="publish: $commit_title" 109 | fi 110 | 111 | #append hash to commit message unless no hash flag was found 112 | if [ $append_hash = true ]; then 113 | commit_message="$commit_message"$'\n\n'"generated from commit $commit_hash" 114 | fi 115 | 116 | previous_branch=`git rev-parse --abbrev-ref HEAD` 117 | 118 | if [ ! -d "$deploy_directory" ]; then 119 | echo "Deploy directory '$deploy_directory' does not exist. Aborting." >&2 120 | return 1 121 | fi 122 | 123 | # must use short form of flag in ls for compatibility with OS X and BSD 124 | if [[ -z `ls -A "$deploy_directory" 2> /dev/null` && -z $allow_empty ]]; then 125 | echo "Deploy directory '$deploy_directory' is empty. Aborting. If you're sure you want to deploy an empty tree, use the --allow-empty / -e flag." >&2 126 | return 1 127 | fi 128 | 129 | if git ls-remote --exit-code $repo "refs/heads/$deploy_branch" ; then 130 | # deploy_branch exists in $repo; make sure we have the latest version 131 | 132 | disable_expanded_output 133 | git fetch --force $repo $deploy_branch:$deploy_branch 134 | enable_expanded_output 135 | fi 136 | 137 | # check if deploy_branch exists locally 138 | if git show-ref --verify --quiet "refs/heads/$deploy_branch" 139 | then incremental_deploy 140 | else initial_deploy 141 | fi 142 | 143 | restore_head 144 | } 145 | 146 | initial_deploy() { 147 | git --work-tree "$deploy_directory" checkout --orphan $deploy_branch 148 | git --work-tree "$deploy_directory" add --all 149 | commit+push 150 | } 151 | 152 | incremental_deploy() { 153 | #make deploy_branch the current branch 154 | git symbolic-ref HEAD refs/heads/$deploy_branch 155 | #put the previously committed contents of deploy_branch into the index 156 | git --work-tree "$deploy_directory" reset --mixed --quiet 157 | git --work-tree "$deploy_directory" add --all 158 | 159 | set +o errexit 160 | diff=$(git --work-tree "$deploy_directory" diff --exit-code --quiet HEAD --)$? 161 | set -o errexit 162 | case $diff in 163 | 0) echo No changes to files in $deploy_directory. Skipping commit.;; 164 | 1) commit+push;; 165 | *) 166 | echo git diff exited with code $diff. Aborting. Staying on branch $deploy_branch so you can debug. To switch back to master, use: git symbolic-ref HEAD refs/heads/master && git reset --mixed >&2 167 | return $diff 168 | ;; 169 | esac 170 | } 171 | 172 | commit+push() { 173 | set_user_id 174 | git --work-tree "$deploy_directory" commit -m "$commit_message" 175 | 176 | disable_expanded_output 177 | #--quiet is important here to avoid outputting the repo URL, which may contain a secret token 178 | git push --quiet $repo $deploy_branch 179 | enable_expanded_output 180 | } 181 | 182 | #echo expanded commands as they are executed (for debugging) 183 | enable_expanded_output() { 184 | if [ $verbose ]; then 185 | set -o xtrace 186 | set +o verbose 187 | fi 188 | } 189 | 190 | #this is used to avoid outputting the repo URL, which may contain a secret token 191 | disable_expanded_output() { 192 | if [ $verbose ]; then 193 | set +o xtrace 194 | set -o verbose 195 | fi 196 | } 197 | 198 | set_user_id() { 199 | if [[ -z `git config user.name` ]]; then 200 | git config user.name "$default_username" 201 | fi 202 | if [[ -z `git config user.email` ]]; then 203 | git config user.email "$default_email" 204 | fi 205 | } 206 | 207 | restore_head() { 208 | if [[ $previous_branch = "HEAD" ]]; then 209 | #we weren't on any branch before, so just set HEAD back to the commit it was on 210 | git update-ref --no-deref HEAD $commit_hash $deploy_branch 211 | else 212 | git symbolic-ref HEAD refs/heads/$previous_branch 213 | fi 214 | 215 | git reset --mixed 216 | } 217 | 218 | filter() { 219 | sed -e "s|$repo|\$repo|g" 220 | } 221 | 222 | sanitize() { 223 | "$@" 2> >(filter 1>&2) | filter 224 | } 225 | 226 | [[ $1 = --source-only ]] || main "$@" 227 | -------------------------------------------------------------------------------- /src/development/stabilization.md: -------------------------------------------------------------------------------- 1 | # Stabilizing features 2 | 3 | * **Status:** Current 4 | * **Last Updated:** 2022-05-27 5 | 6 | Feature stabilization involves adding `#[stable]` attributes. They may be introduced alongside new trait impls or replace existing `#[unstable]` attributes. 7 | 8 | Stabilization goes through the Libs FCP (Final Comment Period) process, which typically occurs on the tracking issue for the feature. 9 | 10 | ## When is an FCP appropriate? 11 | 12 | Once an unstable feature's API design space (e.g. alternative APIs) has been fully explored with no outstanding concerns, anyone may push for its stabilization. 13 | 14 | If you're unsure if a feature is ready for stabilization the first step should be to ask in the relevant tracking issue and get assistance from other participants in that discussion. In some cases the tracking issue may not have many other active participants, so if you're ever having trouble getting any feedback please ping one of the [libs team reviewers](https://github.com/rust-lang/rust/blob/master/triagebot.toml) directly to request assistance. 15 | 16 | ## Stabilization Report 17 | 18 | Once a feature is ready for stabilization the first step of the FCP process is writing a stabilization report. Stabilization reports are not mandatory but they are heavily encouraged, and may be mandated by library API team members if they feel it necessary. The purpose of stabilization reports is to help reviewers more quickly make decisions and to simplify the process of documenting stabilized APIs in release notes. Stabilization reports consist of three primary sections, an implementation history, an API summary, and an experience report. 19 | 20 | The **Implementation History** section should summarize the initial discussion during the implementation PR, every change that has been made to the feature since the initial implementation, all issues that were raised during the lifetime of the feature, and how they were resolved. 21 | 22 | The **API Summary** section should include a precise description of what APIs are being introduced to the standard libraries. This can often be a simple link back to the top level comment if it's up to date, but in some situations it may not be possible to edit the original tracking issue to fix outdated information, such as when the author of the stabilization report is not the author of the tracking issue itself. 23 | 24 | The libs team maintains a tool for this called [`cargo unstable-api`](https://github.com/rust-lang/libs-team/tree/main/tools/unstable-api) that can be used to generate these API summaries in some cases. *Note* the current implementation of this tool is fragile and does not work in all cases. We hope to have a more permanent version of this tool in the future that is built on top of either rustdoc or rustc's own APIs. 25 | 26 | The **Experience Report** section should include concrete usecases of users who have wanted to use the feature and who have tested that it works for their needs. The experience report should include a brief summary of the experience of using that feature. Ideally this would include links to commits or branches where the feature was integrated with their project, but this is not a requirement. Alternatively, users can provide usage examples of crates that export an identical API to the one being stabilized. 27 | 28 | You can see an example of a stabilization report in [#88581](https://github.com/rust-lang/rust/issues/88581#issuecomment-1054642118). 29 | 30 | ## Before writing a PR to stabilize a feature 31 | 32 | Check to see if a FCP has completed first. If not, either ping `@rust-lang/libs-api` if you're a member of the `rust-lang` organization, 33 | or leave a comment asking about the status of the feature. 34 | 35 | This will save you from opening a stabilization PR and having it need regular rebasing while the FCP process runs its course. 36 | 37 | ## Partial Stabilizations 38 | 39 | When you only wish to stabilize a subset of an existing feature you should skip creating a new tracking issue and instead create a partial stabilization PR for the subset of the feature being stabilized. 40 | 41 | If you're unsure if a feature is ready for partial stabilization the first step should be to ask in the relevant tracking issue and get assistance from other participants in that discussion. In some cases the tracking issue may not have many other active participants, so if you're ever having trouble getting any feedback please ping one of the [libs team reviewers](https://github.com/rust-lang/rust/blob/master/triagebot.toml) directly to request assistance. 42 | 43 | You can see an example of partially stabilizing a feature with tracking issue [#71146](https://github.com/rust-lang/rust/issues/71146) and partial stabilization PR [#94640](https://github.com/rust-lang/rust/pull/94640). 44 | 45 | ## When there's `const` involved 46 | 47 | Const functions can be stabilized in a PR that replaces `#[rustc_const_unstable]` attributes with `#[rustc_const_stable]` ones. The [Constant Evaluation WG](https://github.com/rust-lang/const-eval) should be pinged for input on whether or not the `const`-ness is something we want to commit to. If it is an intrinsic being exposed that is const-stabilized then `@rust-lang/lang` should also be included in the FCP. 48 | 49 | Check whether the function internally depends on other unstable `const` functions through `#[allow_internal_unstable]` attributes and consider how the function could be implemented if its internally unstable calls were removed. See the _Stability attributes_ page for more details on `#[allow_internal_unstable]`. 50 | 51 | Where `unsafe` and `const` is involved, e.g., for operations which are "unconst", that the const safety argument for the usage also be documented. That is, a `const fn` has additional determinism (e.g. run-time/compile-time results must correspond and the function's output only depends on its inputs...) restrictions that must be preserved, and those should be argued when `unsafe` is used. 52 | 53 | ## Stabilization PR for Library Features 54 | 55 | Once we have decided to stabilize a feature, we need to have a PR that actually makes that stabilization happen. These kinds of PRs are a great way to get involved in Rust, as they're typically small -- just updating attributes. 56 | 57 | Here is a general guide to how to stabilize a feature -- every feature is different, of course, so some features may require steps beyond what this guide talks about. 58 | 59 | ### Update the stability attributes on the items 60 | 61 | Library items are marked unstable via the `#[unstable]` attribute, like this: 62 | 63 | ```rust,ignore 64 | #[unstable(feature = "total_cmp", issue = "72599")] 65 | pub fn total_cmp(&self, other: &Self) -> crate::cmp::Ordering { ... } 66 | ``` 67 | 68 | You'll need to change that to a `#[stable]` attribute with the version set to the placeholder `CURRENT_RUSTC_VERSION`: 69 | 70 | ```rust,ignore 71 | #[stable(feature = "total_cmp", since = "CURRENT_RUSTC_VERSION")] 72 | ``` 73 | 74 | Note that other `#[stable]` attributes may contain spelled out version numbers, but you should not spell out any version number as it might get outdated by the time your pull request merges. 75 | 76 | ### Remove feature gates from doctests 77 | 78 | All the doctests on the items being stabilized will be enabling the unstable feature, so now that it's stable those attributes are no longer needed and should be removed. 79 | 80 | `````diff 81 | /// # Examples 82 | /// 83 | /// ``` 84 | -/// #![feature(total_cmp)] 85 | -/// 86 | /// assert_eq!(0.0_f32.total_cmp(&-0.0), std::cmp::Ordering::Greater); 87 | /// ``` 88 | ````` 89 | 90 | The most obvious place to find these is on the item itself, but it's worth searching the whole library. Often you'll find other unstable methods that were also using it in their tests. 91 | 92 | ### Remove feature gates from the compiler 93 | 94 | The compiler builds with nightly features allowed, so you may find uses of the feature there as well. These also need to be removed. 95 | 96 | ```diff 97 | #![feature(once_cell)] 98 | #![feature(never_type)] 99 | -#![feature(total_cmp)] 100 | #![feature(trusted_step)] 101 | #![feature(try_blocks)] 102 | ``` 103 | 104 | ## Stabilization PR Checklist 105 | 106 | To stabilize a feature, follow these steps: 107 | 108 | 0. Create a stabilization report in the tracking issue for the feature being stabilized. 109 | 0. (Optional) For partial stabilizations, create a new partial stabilization PR for the subset of the issue being stabilized. 110 | 0. Ask a **@rust-lang/libs-api** member to start an FCP on the tracking issue and wait for the FCP to complete (with `disposition-merge`). 111 | 0. Change `#[unstable(...)]` to `#[stable(since = "CURRENT_RUSTC_VERSION")]`. `CURRENT_RUSTC_VERSION` here is meant in a literal sense and not to be replaced with the spelled out version number. 112 | 0. Remove `#![feature(...)]` from any test or doc-test for this API. If the feature is used in the compiler or tools, remove it from there as well. 113 | 0. If applicable, change `#[rustc_const_unstable(...)]` to `#[rustc_const_stable(since = "CURRENT_RUSTC_VERSION")]`. 114 | 0. Open a PR against `rust-lang/rust`. 115 | - Add the appropriate labels: `@rustbot modify labels: +T-libs-api`. 116 | - Link to the tracking issue by adding "Closes #XXXXX". 117 | 118 | You can see an example of stabilizing a feature with [tracking issue #81656 with FCP](https://github.com/rust-lang/rust/issues/81656) and the associated [implementation PR #84642](https://github.com/rust-lang/rust/pull/84642). 119 | 120 | -------------------------------------------------------------------------------- /LICENSE-APACHE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | --------------------------------------------------------------------------------