├── 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 | [](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 |
--------------------------------------------------------------------------------