Merge branch 'master' into feature/incorporate-tracing

This commit is contained in:
pawanbisht62 2020-08-15 08:59:12 +05:30 committed by GitHub
commit bab15885c0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
781 changed files with 12125 additions and 6656 deletions

View File

@ -2454,9 +2454,9 @@ dependencies = [
[[package]]
name = "racer"
version = "2.1.36"
version = "2.1.37"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09ba6cca9fcd8ae086b842b1bd9e3f19f104a4c30e0e8927b2befc06d375e7e0"
checksum = "db975752fc2c2430b4159d262585f7e45eb9aa43d733bf02c5f2fde512b00bfb"
dependencies = [
"bitflags",
"clap",
@ -2804,9 +2804,9 @@ dependencies = [
[[package]]
name = "rustc-ap-rustc_arena"
version = "669.0.0"
version = "671.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c9cdd301e9dcb15ead384fc07196c850fd22829fae81d296b2ed6b4b10bf3278"
checksum = "4a3941333c39ffa778611a34692244052fc9ba0f6b02dcf019c8d24925707dd6"
dependencies = [
"rustc-ap-rustc_data_structures",
"smallvec 1.4.0",
@ -2814,9 +2814,9 @@ dependencies = [
[[package]]
name = "rustc-ap-rustc_ast"
version = "669.0.0"
version = "671.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f7c0d0537ca69dfe4a49212035295dfb37a235b5df01aa877d50b247f4775b8"
checksum = "27c579f7d89e6fc971b433e92bb2b8c65b716d7c797b21de8685945be9455610"
dependencies = [
"bitflags",
"log",
@ -2832,9 +2832,9 @@ dependencies = [
[[package]]
name = "rustc-ap-rustc_ast_passes"
version = "669.0.0"
version = "671.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d4cf4dca95f55f70eeb193fb08554026d79d0628de771fd726bb609e36887b82"
checksum = "f9914fadee461568d19ca2ebaec8699ff898f8ffec9928154659a57ee018e5fd"
dependencies = [
"itertools 0.8.0",
"log",
@ -2851,9 +2851,9 @@ dependencies = [
[[package]]
name = "rustc-ap-rustc_ast_pretty"
version = "669.0.0"
version = "671.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "202bd2886d0cfa48baa3711042c14843f1b4852555b7ee7e5376bf66b276cb8d"
checksum = "2a78c5cc50a2f294d3c4e9131a15676724c9f136d3ed54e9ba419850b6025cb3"
dependencies = [
"log",
"rustc-ap-rustc_ast",
@ -2863,9 +2863,9 @@ dependencies = [
[[package]]
name = "rustc-ap-rustc_attr"
version = "669.0.0"
version = "671.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b11ee1d92b3214e8a8c7829eff84cc1b03925da0ea5c6900cefe05b99edb4682"
checksum = "a78ce08227d146949755175c0cf710280a4b5bf6ee504c0e3f7ccc30d66fbfd9"
dependencies = [
"rustc-ap-rustc_ast",
"rustc-ap-rustc_ast_pretty",
@ -2881,9 +2881,9 @@ dependencies = [
[[package]]
name = "rustc-ap-rustc_data_structures"
version = "669.0.0"
version = "671.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a45d43b974d4cb9e32e5a15119c5eb7672c306ef09b064f2125b6a0399f6656"
checksum = "9d5ac3735c38d2d0e95991ebcd7eb1618b60e784194a738e0ce2e8d39c39b809"
dependencies = [
"bitflags",
"cfg-if",
@ -2911,9 +2911,9 @@ dependencies = [
[[package]]
name = "rustc-ap-rustc_errors"
version = "669.0.0"
version = "671.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8cd895d440820aaa04e6dc5486105494920a1e9779b9b051e8dba4ca5c182f94"
checksum = "5166a95afa6e3b78ccbece4c2f1e163634854297f1147c6fd90e2712ed3fede5"
dependencies = [
"annotate-snippets 0.8.0",
"atty",
@ -2929,9 +2929,9 @@ dependencies = [
[[package]]
name = "rustc-ap-rustc_expand"
version = "669.0.0"
version = "671.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "71a0cc7820860d6691bf0aa7a95cdbc60f6587b495c18e0fa15a888fdabbf171"
checksum = "1a0586e83bdfe70eda8393429a8a38ecb529525dd252d787e479af075d3cab08"
dependencies = [
"log",
"rustc-ap-rustc_ast",
@ -2951,9 +2951,9 @@ dependencies = [
[[package]]
name = "rustc-ap-rustc_feature"
version = "669.0.0"
version = "671.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5473d5106401aa46f881eb91772f0a41fd5f28ae6134cf4b450eb1370ea6af22"
checksum = "48fc3aa8de0737a8c5a4353e6948548f469150d2b5d3eac391843de32c6c6ca2"
dependencies = [
"lazy_static",
"rustc-ap-rustc_data_structures",
@ -2962,40 +2962,40 @@ dependencies = [
[[package]]
name = "rustc-ap-rustc_fs_util"
version = "669.0.0"
version = "671.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8da1d57ee7a7ef55f31a97d99c7f919f02fc9a60ab96faa8cf45a7ae3ab1ccbf"
checksum = "59fd3380f4029020b693bbfd5a14ec8c893ec33c5c0063ad2e68e46d3fbd6a1f"
[[package]]
name = "rustc-ap-rustc_graphviz"
version = "669.0.0"
version = "671.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3af62b20460908378cd1d354917acd9553376c5363bbb4e465f949bd82bdef9"
checksum = "b54bd98f70e04291bf611151d1fcd4d7770b35f7ec603d301c4aee0d1979cca4"
[[package]]
name = "rustc-ap-rustc_index"
version = "669.0.0"
version = "671.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3af7d4c456fe7647453d3fcd58335c9d512d1ff9a239a370b7ebdd353d69f66f"
checksum = "335bfb187a2489a59ee8c67fcf5d1760e9dcdbe0f02025c199a74caa05096b15"
dependencies = [
"arrayvec 0.5.1",
"rustc-ap-rustc_serialize",
"smallvec 1.4.0",
]
[[package]]
name = "rustc-ap-rustc_lexer"
version = "669.0.0"
version = "671.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "456af5f09c006cf6c22c1a433ee0232c4bb74bdc6c647a010166a47c94ed2a63"
checksum = "22e1221f3bfa2943c942cf8da319ab2346887f8757778c29c7f1822cd27b521f"
dependencies = [
"unicode-xid",
]
[[package]]
name = "rustc-ap-rustc_macros"
version = "669.0.0"
version = "671.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "64f6acd192f313047759a346b892998b626466b93fe04f415da5f38906bb3b4c"
checksum = "8b774df26c4ef513555b3a303cb209f44cf68a9e6a5481b41ac832301c6487cb"
dependencies = [
"proc-macro2",
"quote",
@ -3005,9 +3005,9 @@ dependencies = [
[[package]]
name = "rustc-ap-rustc_parse"
version = "669.0.0"
version = "671.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c006e8117c1c55e42bb56386c86ce6f7e4b47349e0bec7888c1d24784272e61b"
checksum = "065e632101bdd57a271f38ee7a4d72b5a3d0467ec845104346c284b2c6c69960"
dependencies = [
"bitflags",
"log",
@ -3024,9 +3024,9 @@ dependencies = [
[[package]]
name = "rustc-ap-rustc_serialize"
version = "669.0.0"
version = "671.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "306ced69beaeebe4de9552ee751eb54ea25b5f34a73fe80f5f9cbbe15ccebc48"
checksum = "0e8c0b704e3dedb97cbb1ac566bbc0ab397ec4a4743098326a8f2230463fd9f9"
dependencies = [
"indexmap",
"smallvec 1.4.0",
@ -3034,9 +3034,9 @@ dependencies = [
[[package]]
name = "rustc-ap-rustc_session"
version = "669.0.0"
version = "671.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dbff48435f5a476365e3ab5f49e07f98715cecb2d8c5bbcafeaf3aec638407be"
checksum = "dda99ede4e6e260712754f8548b0a175b615686ad393653a3bd11f6c5e41a04e"
dependencies = [
"bitflags",
"getopts",
@ -3054,9 +3054,9 @@ dependencies = [
[[package]]
name = "rustc-ap-rustc_span"
version = "669.0.0"
version = "671.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec4273af0abbe78fc4585316ab193445c848c555e9203ddc28af02330918bf30"
checksum = "53453791c2c0b501a921927ce8e305a801eef130920873f8da92d83dad595236"
dependencies = [
"cfg-if",
"log",
@ -3073,9 +3073,9 @@ dependencies = [
[[package]]
name = "rustc-ap-rustc_target"
version = "669.0.0"
version = "671.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6f9a2d6004ce6ad492a8eeacc2569b1c008169434b8828996d8dade4e5c6b6ee"
checksum = "ac82006fdb31ef44e24e1623f8b72ac2b404ef15ba20b7ebec0df35e5d20bbef"
dependencies = [
"bitflags",
"log",
@ -3257,6 +3257,7 @@ dependencies = [
"rustc_data_structures",
"rustc_errors",
"rustc_feature",
"rustc_lexer",
"rustc_macros",
"rustc_serialize",
"rustc_session",
@ -3333,6 +3334,7 @@ dependencies = [
"rustc_hir",
"rustc_incremental",
"rustc_index",
"rustc_macros",
"rustc_middle",
"rustc_serialize",
"rustc_session",
@ -3363,10 +3365,12 @@ dependencies = [
"rustc-rayon-core",
"rustc_graphviz",
"rustc_index",
"rustc_macros",
"rustc_serialize",
"smallvec 1.4.0",
"stable_deref_trait",
"stacker",
"tempfile",
"tracing",
"winapi 0.3.8",
]
@ -3414,6 +3418,7 @@ dependencies = [
"annotate-snippets 0.8.0",
"atty",
"rustc_data_structures",
"rustc_macros",
"rustc_serialize",
"rustc_span",
"termcolor",
@ -3435,6 +3440,7 @@ dependencies = [
"rustc_errors",
"rustc_feature",
"rustc_lexer",
"rustc_macros",
"rustc_parse",
"rustc_serialize",
"rustc_session",
@ -3497,6 +3503,7 @@ dependencies = [
"rustc_fs_util",
"rustc_graphviz",
"rustc_hir",
"rustc_macros",
"rustc_middle",
"rustc_serialize",
"rustc_session",
@ -3509,6 +3516,7 @@ name = "rustc_index"
version = "0.0.0"
dependencies = [
"arrayvec 0.5.1",
"rustc_macros",
"rustc_serialize",
]
@ -3638,6 +3646,7 @@ dependencies = [
"rustc_hir",
"rustc_hir_pretty",
"rustc_index",
"rustc_macros",
"rustc_middle",
"rustc_serialize",
"rustc_session",
@ -3813,6 +3822,7 @@ dependencies = [
"rustc_data_structures",
"rustc_errors",
"rustc_index",
"rustc_macros",
"rustc_serialize",
"rustc_span",
"smallvec 1.4.0",
@ -3867,6 +3877,7 @@ name = "rustc_serialize"
version = "0.0.0"
dependencies = [
"indexmap",
"rustc_macros",
"smallvec 1.4.0",
]
@ -3882,6 +3893,7 @@ dependencies = [
"rustc_errors",
"rustc_feature",
"rustc_fs_util",
"rustc_macros",
"rustc_serialize",
"rustc_span",
"rustc_target",
@ -4078,7 +4090,7 @@ dependencies = [
[[package]]
name = "rustfmt-nightly"
version = "1.4.19"
version = "1.4.20"
dependencies = [
"annotate-snippets 0.6.1",
"anyhow",
@ -4622,6 +4634,10 @@ dependencies = [
"walkdir",
]
[[package]]
name = "tier-check"
version = "0.1.0"
[[package]]
name = "time"
version = "0.1.42"

View File

@ -13,6 +13,7 @@ members = [
"src/tools/rustbook",
"src/tools/unstable-book-gen",
"src/tools/tidy",
"src/tools/tier-check",
"src/tools/build-manifest",
"src/tools/remote-test-client",
"src/tools/remote-test-server",

View File

@ -1,9 +1,9 @@
<a href = "https://www.rust-lang.org/">
<a href = "https://www.rust-lang.org/">
<img width = "90%" height = "auto" src = "https://img.shields.io/badge/Rust-Programming%20Language-black?style=flat&logo=rust" alt = "The Rust Programming Language">
</a>
This is the main source code repository for [Rust]. It contains the compiler,
standard library, and documentation.
standard library, and documentation.
[Rust]: https://www.rust-lang.org
@ -23,7 +23,7 @@ Read ["Installation"] from [The Book].
section.**
The Rust build system uses a Python script called `x.py` to build the compiler,
which manages the bootstrapping process. More information about it can be found
which manages the bootstrapping process. More information about it can be found
by running `./x.py --help` or reading the [rustc dev guide][rustcguidebuild].
[gettingstarted]: https://rustc-dev-guide.rust-lang.org/getting-started.html
@ -157,17 +157,6 @@ by manually calling the appropriate vcvars file before running the bootstrap.
> python x.py build
```
### Building rustc with older host toolchains
It is still possible to build Rust with the older toolchain versions listed below, but only if the
LLVM_TEMPORARILY_ALLOW_OLD_TOOLCHAIN option is set to true in the config.toml file.
* Clang 3.1
* Apple Clang 3.1
* GCC 4.8
* Visual Studio 2015 (Update 3)
Toolchain versions older than what is listed above cannot be used to build rustc.
#### Specifying an ABI
Each specific ABI can also be used from either environment (for example, using

View File

@ -1,3 +1,104 @@
Version 1.46.0 (2020-08-27)
==========================
Language
--------
- [`if`, `match`, and `loop` expressions can now be used in const functions.][72437]
- [Additionally you are now also able to coerce and cast to slices (`&[T]`) in
const functions.][73862]
- [The `#[track_caller]` attribute can now be added to functions to use the
function's caller's location information for panic messages.][72445]
- [Recursively indexing into tuples no longer needs parentheses.][71322] E.g.
`x.0.0` over `(x.0).0`.
- [`mem::transmute` can now be used in static and constants.][72920] **Note**
You currently can't use `mem::transmute` in constant functions.
Compiler
--------
- [You can now use the `cdylib` target on Apple iOS and tvOS platforms.][73516]
- [Enabled static "Position Independent Executables" by default
for `x86_64-unknown-linux-musl`.][70740]
Libraries
---------
- [`mem::forget` is now a `const fn`.][73887]
- [`String` now implements `From<char>`.][73466]
- [The `leading_ones`, and `trailing_ones` methods have been stabilised for all
integer types.][73032]
- [`vec::IntoIter<T>` now implements `AsRef<[T]>`.][72583]
- [All non-zero integer types (`NonZeroU8`) now implement `TryFrom` for their
zero-able equivalent (e.g. `TryFrom<u8>`).][72717]
- [`&[T]` and `&mut [T]` now implement `PartialEq<Vec<T>>`.][71660]
- [`(String, u16)` now implements `ToSocketAddrs`.][73007]
- [`vec::Drain<'_, T>` now implements `AsRef<[T]>`.][72584]
Stabilized APIs
---------------
- [`Option::zip`]
- [`vec::Drain::as_slice`]
Cargo
-----
Added a number of new environment variables that are now available when
compiling your crate.
- [`CARGO_BIN_NAME` and `CARGO_CRATE_NAME`][cargo/8270] Providing the name of
the specific binary being compiled and the name of the crate.
- [`CARGO_PKG_LICENSE`][cargo/8325] The license from the manifest of the package.
- [`CARGO_PKG_LICENSE_FILE`][cargo/8387] The path to the license file.
Compatibility Notes
-------------------
- [The target configuration option `abi_blacklist` has been renamed
to `unsupported_abis`.][74150] The old name will still continue to work.
- [Rustc will now warn if you have a C-like enum that implements `Drop`.][72331]
This was previously accepted but will become a hard error in a future release.
- [Rustc will fail to compile if you have a struct with
`#[repr(i128)]` or `#[repr(u128)]`.][74109] This representation is currently only
allowed on `enum`s.
- [Tokens passed to `macro_rules!` are now always captured.][73293] This helps
ensure that spans have the correct information, and may cause breakage if you
were relying on receiving spans with dummy information.
- [The InnoSetup installer for Windows is no longer available.][72569] This was
a legacy installer that was replaced by a MSI installer a few years ago but
was still being built.
- [`{f32, f64}::asinh` now returns the correct values for negative numbers.][72486]
- [Rustc will no longer accept overlapping trait implementations that only
differ in how the lifetime was bound.][72493]
- [Rustc now correctly relates the lifetime of an existential associated
type.][71896] This fixes some edge cases where `rustc` would erroneously allow
you to pass a shorter lifetime than expected.
[74109]: https://github.com/rust-lang/rust/pull/74109/
[74150]: https://github.com/rust-lang/rust/pull/74150/
[73862]: https://github.com/rust-lang/rust/pull/73862/
[73887]: https://github.com/rust-lang/rust/pull/73887/
[73466]: https://github.com/rust-lang/rust/pull/73466/
[73516]: https://github.com/rust-lang/rust/pull/73516/
[73293]: https://github.com/rust-lang/rust/pull/73293/
[73007]: https://github.com/rust-lang/rust/pull/73007/
[73032]: https://github.com/rust-lang/rust/pull/73032/
[72920]: https://github.com/rust-lang/rust/pull/72920/
[72569]: https://github.com/rust-lang/rust/pull/72569/
[72583]: https://github.com/rust-lang/rust/pull/72583/
[72584]: https://github.com/rust-lang/rust/pull/72584/
[72717]: https://github.com/rust-lang/rust/pull/72717/
[72437]: https://github.com/rust-lang/rust/pull/72437/
[72445]: https://github.com/rust-lang/rust/pull/72445/
[72486]: https://github.com/rust-lang/rust/pull/72486/
[72493]: https://github.com/rust-lang/rust/pull/72493/
[72331]: https://github.com/rust-lang/rust/pull/72331/
[71896]: https://github.com/rust-lang/rust/pull/71896/
[71660]: https://github.com/rust-lang/rust/pull/71660/
[71322]: https://github.com/rust-lang/rust/pull/71322/
[70740]: https://github.com/rust-lang/rust/pull/70740/
[cargo/8270]: https://github.com/rust-lang/cargo/pull/8270/
[cargo/8325]: https://github.com/rust-lang/cargo/pull/8325/
[cargo/8387]: https://github.com/rust-lang/cargo/pull/8387/
[`Option::zip`]: https://doc.rust-lang.org/stable/std/option/enum.Option.html#method.zip
[`vec::Drain::as_slice`]: https://doc.rust-lang.org/stable/std/vec/struct.Drain.html#method.as_slice
Version 1.45.2 (2020-08-03)
==========================
@ -7,6 +108,7 @@ Version 1.45.2 (2020-08-03)
[74954]: https://github.com/rust-lang/rust/issues/74954
[74784]: https://github.com/rust-lang/rust/issues/74784
Version 1.45.1 (2020-07-30)
==========================
@ -20,6 +122,7 @@ Version 1.45.1 (2020-07-30)
[74509]: https://github.com/rust-lang/rust/pull/74509
[74457]: https://github.com/rust-lang/rust/pull/74457
Version 1.45.0 (2020-07-16)
==========================

View File

@ -2,14 +2,14 @@
use core::borrow::Borrow;
use core::cmp::Ordering;
use core::fmt::Debug;
use core::fmt::{self, Debug};
use core::hash::{Hash, Hasher};
use core::iter::{FromIterator, FusedIterator, Peekable};
use core::marker::PhantomData;
use core::mem::{self, ManuallyDrop};
use core::ops::Bound::{Excluded, Included, Unbounded};
use core::ops::{Index, RangeBounds};
use core::{fmt, ptr};
use core::ptr;
use super::node::{self, marker, ForceResult::*, Handle, InsertResult::*, NodeRef};
use super::search::{self, SearchResult::*};
@ -154,7 +154,7 @@ impl<K: Clone, V: Clone> Clone for BTreeMap<K, V> {
{
let root = out_tree.root.as_mut().unwrap(); // unwrap succeeds because we just wrapped
let mut out_node = match root.as_mut().force() {
let mut out_node = match root.node_as_mut().force() {
Leaf(leaf) => leaf,
Internal(_) => unreachable!(),
};
@ -210,7 +210,7 @@ impl<K: Clone, V: Clone> Clone for BTreeMap<K, V> {
// Ord` constraint, which this method lacks.
BTreeMap { root: None, length: 0 }
} else {
clone_subtree(self.root.as_ref().unwrap().as_ref()) // unwrap succeeds because not empty
clone_subtree(self.root.as_ref().unwrap().node_as_ref()) // unwrap succeeds because not empty
}
}
}
@ -223,14 +223,16 @@ where
type Key = K;
fn get(&self, key: &Q) -> Option<&K> {
match search::search_tree(self.root.as_ref()?.as_ref(), key) {
let root_node = self.root.as_ref()?.node_as_ref();
match search::search_tree(root_node, key) {
Found(handle) => Some(handle.into_kv().0),
GoDown(_) => None,
}
}
fn take(&mut self, key: &Q) -> Option<K> {
match search::search_tree(self.root.as_mut()?.as_mut(), key) {
let root_node = self.root.as_mut()?.node_as_mut();
match search::search_tree(root_node, key) {
Found(handle) => Some(
OccupiedEntry { handle, length: &mut self.length, _marker: PhantomData }
.remove_kv()
@ -242,8 +244,8 @@ where
fn replace(&mut self, key: K) -> Option<K> {
let root = Self::ensure_is_owned(&mut self.root);
match search::search_tree::<marker::Mut<'_>, K, (), K>(root.as_mut(), &key) {
Found(handle) => Some(mem::replace(handle.into_kv_mut().0, key)),
match search::search_tree::<marker::Mut<'_>, K, (), K>(root.node_as_mut(), &key) {
Found(handle) => Some(mem::replace(handle.into_key_mut(), key)),
GoDown(handle) => {
VacantEntry { key, handle, length: &mut self.length, _marker: PhantomData }
.insert(());
@ -565,7 +567,8 @@ impl<K: Ord, V> BTreeMap<K, V> {
K: Borrow<Q>,
Q: Ord,
{
match search::search_tree(self.root.as_ref()?.as_ref(), key) {
let root_node = self.root.as_ref()?.node_as_ref();
match search::search_tree(root_node, key) {
Found(handle) => Some(handle.into_kv().1),
GoDown(_) => None,
}
@ -592,7 +595,8 @@ impl<K: Ord, V> BTreeMap<K, V> {
K: Borrow<Q>,
Q: Ord,
{
match search::search_tree(self.root.as_ref()?.as_ref(), k) {
let root_node = self.root.as_ref()?.node_as_ref();
match search::search_tree(root_node, k) {
Found(handle) => Some(handle.into_kv()),
GoDown(_) => None,
}
@ -617,8 +621,8 @@ impl<K: Ord, V> BTreeMap<K, V> {
/// ```
#[unstable(feature = "map_first_last", issue = "62924")]
pub fn first_key_value(&self) -> Option<(&K, &V)> {
let front = self.root.as_ref()?.as_ref().first_leaf_edge();
front.right_kv().ok().map(Handle::into_kv)
let root_node = self.root.as_ref()?.node_as_ref();
root_node.first_leaf_edge().right_kv().ok().map(Handle::into_kv)
}
/// Returns the first entry in the map for in-place manipulation.
@ -643,8 +647,8 @@ impl<K: Ord, V> BTreeMap<K, V> {
/// ```
#[unstable(feature = "map_first_last", issue = "62924")]
pub fn first_entry(&mut self) -> Option<OccupiedEntry<'_, K, V>> {
let front = self.root.as_mut()?.as_mut().first_leaf_edge();
let kv = front.right_kv().ok()?;
let root_node = self.root.as_mut()?.node_as_mut();
let kv = root_node.first_leaf_edge().right_kv().ok()?;
Some(OccupiedEntry {
handle: kv.forget_node_type(),
length: &mut self.length,
@ -694,8 +698,8 @@ impl<K: Ord, V> BTreeMap<K, V> {
/// ```
#[unstable(feature = "map_first_last", issue = "62924")]
pub fn last_key_value(&self) -> Option<(&K, &V)> {
let back = self.root.as_ref()?.as_ref().last_leaf_edge();
back.left_kv().ok().map(Handle::into_kv)
let root_node = self.root.as_ref()?.node_as_ref();
root_node.last_leaf_edge().left_kv().ok().map(Handle::into_kv)
}
/// Returns the last entry in the map for in-place manipulation.
@ -720,8 +724,8 @@ impl<K: Ord, V> BTreeMap<K, V> {
/// ```
#[unstable(feature = "map_first_last", issue = "62924")]
pub fn last_entry(&mut self) -> Option<OccupiedEntry<'_, K, V>> {
let back = self.root.as_mut()?.as_mut().last_leaf_edge();
let kv = back.left_kv().ok()?;
let root_node = self.root.as_mut()?.node_as_mut();
let kv = root_node.last_leaf_edge().left_kv().ok()?;
Some(OccupiedEntry {
handle: kv.forget_node_type(),
length: &mut self.length,
@ -805,8 +809,9 @@ impl<K: Ord, V> BTreeMap<K, V> {
K: Borrow<Q>,
Q: Ord,
{
match search::search_tree(self.root.as_mut()?.as_mut(), key) {
Found(handle) => Some(handle.into_kv_mut().1),
let root_node = self.root.as_mut()?.node_as_mut();
match search::search_tree(root_node, key) {
Found(handle) => Some(handle.into_val_mut()),
GoDown(_) => None,
}
}
@ -899,7 +904,8 @@ impl<K: Ord, V> BTreeMap<K, V> {
K: Borrow<Q>,
Q: Ord,
{
match search::search_tree(self.root.as_mut()?.as_mut(), key) {
let root_node = self.root.as_mut()?.node_as_mut();
match search::search_tree(root_node, key) {
Found(handle) => Some(
OccupiedEntry { handle, length: &mut self.length, _marker: PhantomData }
.remove_entry(),
@ -995,7 +1001,7 @@ impl<K: Ord, V> BTreeMap<K, V> {
R: RangeBounds<T>,
{
if let Some(root) = &self.root {
let (f, b) = range_search(root.as_ref(), range);
let (f, b) = range_search(root.node_as_ref(), range);
Range { front: Some(f), back: Some(b) }
} else {
@ -1041,7 +1047,7 @@ impl<K: Ord, V> BTreeMap<K, V> {
R: RangeBounds<T>,
{
if let Some(root) = &mut self.root {
let (f, b) = range_search(root.as_mut(), range);
let (f, b) = range_search(root.node_as_mut(), range);
RangeMut { front: Some(f), back: Some(b), _marker: PhantomData }
} else {
@ -1071,7 +1077,7 @@ impl<K: Ord, V> BTreeMap<K, V> {
pub fn entry(&mut self, key: K) -> Entry<'_, K, V> {
// FIXME(@porglezomp) Avoid allocating if we don't insert
let root = Self::ensure_is_owned(&mut self.root);
match search::search_tree(root.as_mut(), &key) {
match search::search_tree(root.node_as_mut(), &key) {
Found(handle) => {
Occupied(OccupiedEntry { handle, length: &mut self.length, _marker: PhantomData })
}
@ -1083,7 +1089,7 @@ impl<K: Ord, V> BTreeMap<K, V> {
fn from_sorted_iter<I: Iterator<Item = (K, V)>>(&mut self, iter: I) {
let root = Self::ensure_is_owned(&mut self.root);
let mut cur_node = root.as_mut().last_leaf_edge().into_node();
let mut cur_node = root.node_as_mut().last_leaf_edge().into_node();
// Iterate through all key-value pairs, pushing them into nodes at the right level.
for (key, value) in iter {
// Try to push key-value pair into the current leaf node.
@ -1133,7 +1139,7 @@ impl<K: Ord, V> BTreeMap<K, V> {
fn fix_right_edge(root: &mut node::Root<K, V>) {
// Handle underfull nodes, start from the top.
let mut cur_node = root.as_mut();
let mut cur_node = root.node_as_mut();
while let Internal(internal) = cur_node.force() {
// Check if right-most child is underfull.
let mut last_edge = internal.last_edge();
@ -1201,8 +1207,8 @@ impl<K: Ord, V> BTreeMap<K, V> {
}
{
let mut left_node = left_root.as_mut();
let mut right_node = right_root.as_mut();
let mut left_node = left_root.node_as_mut();
let mut right_node = right_root.node_as_mut();
loop {
let mut split_edge = match search::search_node(left_node, key) {
@ -1280,7 +1286,8 @@ impl<K: Ord, V> BTreeMap<K, V> {
DrainFilter { pred, inner: self.drain_filter_inner() }
}
pub(super) fn drain_filter_inner(&mut self) -> DrainFilterInner<'_, K, V> {
let front = self.root.as_mut().map(|r| r.as_mut().first_leaf_edge());
let root_node = self.root.as_mut().map(|r| r.node_as_mut());
let front = root_node.map(|rn| rn.first_leaf_edge());
DrainFilterInner {
length: &mut self.length,
cur_leaf_edge: front,
@ -1315,7 +1322,7 @@ impl<K: Ord, V> BTreeMap<K, V> {
res
}
self.length = dfs(self.root.as_ref().unwrap().as_ref());
self.length = dfs(self.root.as_ref().unwrap().node_as_ref());
}
/// Creates a consuming iterator visiting all the keys, in sorted order.
@ -2251,7 +2258,7 @@ impl<K, V> BTreeMap<K, V> {
#[stable(feature = "rust1", since = "1.0.0")]
pub fn iter(&self) -> Iter<'_, K, V> {
if let Some(root) = &self.root {
let (f, b) = full_range_search(root.as_ref());
let (f, b) = full_range_search(root.node_as_ref());
Iter { range: Range { front: Some(f), back: Some(b) }, length: self.length }
} else {
@ -2283,7 +2290,7 @@ impl<K, V> BTreeMap<K, V> {
#[stable(feature = "rust1", since = "1.0.0")]
pub fn iter_mut(&mut self) -> IterMut<'_, K, V> {
if let Some(root) = &mut self.root {
let (f, b) = full_range_search(root.as_mut());
let (f, b) = full_range_search(root.node_as_mut());
IterMut {
range: RangeMut { front: Some(f), back: Some(b), _marker: PhantomData },
@ -2741,7 +2748,7 @@ impl<'a, K: Ord, V> OccupiedEntry<'a, K, V> {
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn into_mut(self) -> &'a mut V {
self.handle.into_kv_mut().1
self.handle.into_val_mut()
}
/// Sets the value of the entry with the `OccupiedEntry`'s key,
@ -2895,7 +2902,7 @@ impl<'a, K: 'a, V: 'a> Handle<NodeRef<marker::Mut<'a>, K, V, marker::LeafOrInter
impl<K, V> node::Root<K, V> {
/// Removes empty levels on the top, but keep an empty leaf if the entire tree is empty.
fn fix_top(&mut self) {
while self.height() > 0 && self.as_ref().len() == 0 {
while self.height() > 0 && self.node_as_ref().len() == 0 {
self.pop_internal_level();
}
}
@ -2904,7 +2911,7 @@ impl<K, V> node::Root<K, V> {
self.fix_top();
{
let mut cur_node = self.as_mut();
let mut cur_node = self.node_as_mut();
while let Internal(node) = cur_node.force() {
let mut last_kv = node.last_kv();
@ -2930,7 +2937,7 @@ impl<K, V> node::Root<K, V> {
self.fix_top();
{
let mut cur_node = self.as_mut();
let mut cur_node = self.node_as_mut();
while let Internal(node) = cur_node.force() {
let mut first_kv = node.first_kv();
@ -3017,3 +3024,6 @@ impl<K: Ord, V, I: Iterator<Item = (K, V)>> Iterator for MergeIter<K, V, I> {
}
}
}
#[cfg(test)]
mod tests;

View File

@ -1,16 +1,20 @@
use std::collections::btree_map::Entry::{Occupied, Vacant};
use std::collections::BTreeMap;
use crate::boxed::Box;
use crate::collections::btree_map::Entry::{Occupied, Vacant};
use crate::collections::BTreeMap;
use crate::fmt::Debug;
use crate::rc::Rc;
use crate::string::String;
use crate::string::ToString;
use crate::vec::Vec;
use std::convert::TryFrom;
use std::fmt::Debug;
use std::iter::FromIterator;
use std::mem;
use std::ops::Bound::{self, Excluded, Included, Unbounded};
use std::ops::RangeBounds;
use std::panic::{catch_unwind, AssertUnwindSafe};
use std::rc::Rc;
use std::sync::atomic::{AtomicUsize, Ordering};
use super::DeterministicRng;
use super::super::DeterministicRng;
// Value of node::CAPACITY, thus capacity of a tree with a single level,
// i.e. a tree who's root is a leaf node at height 0.

View File

@ -25,3 +25,30 @@ pub unsafe fn unwrap_unchecked<T>(val: Option<T>) -> T {
}
})
}
#[cfg(test)]
/// XorShiftRng
struct DeterministicRng {
x: u32,
y: u32,
z: u32,
w: u32,
}
#[cfg(test)]
impl DeterministicRng {
fn new() -> Self {
DeterministicRng { x: 0x193a6754, y: 0xa8a7d469, z: 0x97830e05, w: 0x113ba7bb }
}
fn next(&mut self) -> u32 {
let x = self.x;
let t = x ^ (x << 11);
self.x = self.y;
self.y = self.z;
self.z = self.w;
let w_ = self.w;
self.w = w_ ^ (w_ >> 19) ^ (t ^ (t >> 8));
self.w
}
}

View File

@ -43,6 +43,9 @@ use crate::boxed::Box;
const B: usize = 6;
pub const MIN_LEN: usize = B - 1;
pub const CAPACITY: usize = 2 * B - 1;
const KV_IDX_CENTER: usize = B - 1;
const EDGE_IDX_LEFT_OF_CENTER: usize = B - 1;
const EDGE_IDX_RIGHT_OF_CENTER: usize = B;
/// The underlying representation of leaf nodes.
#[repr(C)]
@ -163,7 +166,8 @@ impl<K, V> Root<K, V> {
Root { node: BoxedNode::from_leaf(Box::new(unsafe { LeafNode::new() })), height: 0 }
}
pub fn as_ref(&self) -> NodeRef<marker::Immut<'_>, K, V, marker::LeafOrInternal> {
/// Borrows and returns an immutable reference to the node owned by the root.
pub fn node_as_ref(&self) -> NodeRef<marker::Immut<'_>, K, V, marker::LeafOrInternal> {
NodeRef {
height: self.height,
node: self.node.as_ptr(),
@ -172,7 +176,8 @@ impl<K, V> Root<K, V> {
}
}
pub fn as_mut(&mut self) -> NodeRef<marker::Mut<'_>, K, V, marker::LeafOrInternal> {
/// Borrows and returns a mutable reference to the node owned by the root.
pub fn node_as_mut(&mut self) -> NodeRef<marker::Mut<'_>, K, V, marker::LeafOrInternal> {
NodeRef {
height: self.height,
node: self.node.as_ptr(),
@ -226,12 +231,12 @@ impl<K, V> Root<K, V> {
self.node = unsafe {
BoxedNode::from_ptr(
self.as_mut().cast_unchecked::<marker::Internal>().first_edge().descend().node,
self.node_as_mut().cast_unchecked::<marker::Internal>().first_edge().descend().node,
)
};
self.height -= 1;
unsafe {
(*self.as_mut().as_leaf_mut()).parent = ptr::null();
(*self.node_as_mut().as_leaf_mut()).parent = ptr::null();
}
unsafe {
@ -411,7 +416,7 @@ impl<K, V> NodeRef<marker::Owned, K, V, marker::LeafOrInternal> {
impl<'a, K, V, Type> NodeRef<marker::Mut<'a>, K, V, Type> {
/// Unsafely asserts to the compiler some static information about whether this
/// node is a `Leaf` or an `Internal`.
unsafe fn cast_unchecked<NewType>(&mut self) -> NodeRef<marker::Mut<'_>, K, V, NewType> {
unsafe fn cast_unchecked<NewType>(self) -> NodeRef<marker::Mut<'a>, K, V, NewType> {
NodeRef { height: self.height, node: self.node, root: self.root, _marker: PhantomData }
}
@ -616,7 +621,7 @@ impl<'a, K, V> NodeRef<marker::Mut<'a>, K, V, marker::LeafOrInternal> {
let edge =
ptr::read(internal.as_internal().edges.get_unchecked(idx + 1).as_ptr());
let mut new_root = Root { node: edge, height: internal.height - 1 };
(*new_root.as_mut().as_leaf_mut()).parent = ptr::null();
(*new_root.node_as_mut().as_leaf_mut()).parent = ptr::null();
Some(new_root)
}
};
@ -648,7 +653,7 @@ impl<'a, K, V> NodeRef<marker::Mut<'a>, K, V, marker::LeafOrInternal> {
);
let mut new_root = Root { node: edge, height: internal.height - 1 };
(*new_root.as_mut().as_leaf_mut()).parent = ptr::null();
(*new_root.node_as_mut().as_leaf_mut()).parent = ptr::null();
for i in 0..old_len {
Handle::new_edge(internal.reborrow_mut(), i).correct_parent_link();
@ -719,7 +724,7 @@ impl<Node: Copy, Type> Clone for Handle<Node, Type> {
}
impl<Node, Type> Handle<Node, Type> {
/// Retrieves the node that contains the edge of key/value pair this handle points to.
/// Retrieves the node that contains the edge or key/value pair this handle points to.
pub fn into_node(self) -> Node {
self.node
}
@ -819,6 +824,27 @@ impl<BorrowType, K, V, NodeType> Handle<NodeRef<BorrowType, K, V, NodeType>, mar
}
}
enum InsertionPlace {
Left(usize),
Right(usize),
}
/// Given an edge index where we want to insert into a node filled to capacity,
/// computes a sensible KV index of a split point and where to perform the insertion.
/// The goal of the split point is for its key and value to end up in a parent node;
/// the keys, values and edges to the left of the split point become the left child;
/// the keys, values and edges to the right of the split point become the right child.
fn splitpoint(edge_idx: usize) -> (usize, InsertionPlace) {
debug_assert!(edge_idx <= CAPACITY);
// Rust issue #74834 tries to explain these symmetric rules.
match edge_idx {
0..EDGE_IDX_LEFT_OF_CENTER => (KV_IDX_CENTER - 1, InsertionPlace::Left(edge_idx)),
EDGE_IDX_LEFT_OF_CENTER => (KV_IDX_CENTER, InsertionPlace::Left(edge_idx)),
EDGE_IDX_RIGHT_OF_CENTER => (KV_IDX_CENTER, InsertionPlace::Right(0)),
_ => (KV_IDX_CENTER + 1, InsertionPlace::Right(edge_idx - (KV_IDX_CENTER + 1 + 1))),
}
}
impl<'a, K, V, NodeType> Handle<NodeRef<marker::Mut<'a>, K, V, NodeType>, marker::Edge> {
/// Helps implementations of `insert_fit` for a particular `NodeType`,
/// by taking care of leaf data.
@ -861,18 +887,20 @@ impl<'a, K, V> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, marker::Edge
let kv = unsafe { Handle::new_kv(self.node, self.idx) };
(InsertResult::Fit(kv), ptr)
} else {
let middle = unsafe { Handle::new_kv(self.node, B) };
let (middle_kv_idx, insertion) = splitpoint(self.idx);
let middle = unsafe { Handle::new_kv(self.node, middle_kv_idx) };
let (mut left, k, v, mut right) = middle.split();
let ptr = if self.idx <= B {
unsafe { Handle::new_edge(left.reborrow_mut(), self.idx).insert_fit(key, val) }
} else {
unsafe {
let ptr = match insertion {
InsertionPlace::Left(insert_idx) => unsafe {
Handle::new_edge(left.reborrow_mut(), insert_idx).insert_fit(key, val)
},
InsertionPlace::Right(insert_idx) => unsafe {
Handle::new_edge(
right.as_mut().cast_unchecked::<marker::Leaf>(),
self.idx - (B + 1),
right.node_as_mut().cast_unchecked::<marker::Leaf>(),
insert_idx,
)
.insert_fit(key, val)
}
},
};
(InsertResult::Split(SplitResult { left: left.forget_type(), k, v, right }), ptr)
}
@ -934,20 +962,20 @@ impl<'a, K, V> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Internal>, marker::
let kv = unsafe { Handle::new_kv(self.node, self.idx) };
InsertResult::Fit(kv)
} else {
let middle = unsafe { Handle::new_kv(self.node, B) };
let (middle_kv_idx, insertion) = splitpoint(self.idx);
let middle = unsafe { Handle::new_kv(self.node, middle_kv_idx) };
let (mut left, k, v, mut right) = middle.split();
if self.idx <= B {
unsafe {
Handle::new_edge(left.reborrow_mut(), self.idx).insert_fit(key, val, edge);
}
} else {
unsafe {
match insertion {
InsertionPlace::Left(insert_idx) => unsafe {
Handle::new_edge(left.reborrow_mut(), insert_idx).insert_fit(key, val, edge);
},
InsertionPlace::Right(insert_idx) => unsafe {
Handle::new_edge(
right.as_mut().cast_unchecked::<marker::Internal>(),
self.idx - (B + 1),
right.node_as_mut().cast_unchecked::<marker::Internal>(),
insert_idx,
)
.insert_fit(key, val, edge);
}
},
}
InsertResult::Split(SplitResult { left: left.forget_type(), k, v, right })
}
@ -1016,6 +1044,16 @@ impl<'a, K: 'a, V: 'a, NodeType> Handle<NodeRef<marker::Immut<'a>, K, V, NodeTyp
}
impl<'a, K: 'a, V: 'a, NodeType> Handle<NodeRef<marker::Mut<'a>, K, V, NodeType>, marker::KV> {
pub fn into_key_mut(self) -> &'a mut K {
let keys = self.node.into_key_slice_mut();
unsafe { keys.get_unchecked_mut(self.idx) }
}
pub fn into_val_mut(self) -> &'a mut V {
let vals = self.node.into_val_slice_mut();
unsafe { vals.get_unchecked_mut(self.idx) }
}
pub fn into_kv_mut(self) -> (&'a mut K, &'a mut V) {
unsafe {
let (keys, vals) = self.node.into_slices_mut();
@ -1080,7 +1118,7 @@ impl<'a, K, V> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, marker::KV>
}
/// Removes the key/value pair pointed to by this handle and returns it, along with the edge
/// between the now adjacent key/value pairs (if any) to the left and right of this handle.
/// that the key/value pair collapsed into.
pub fn remove(
mut self,
) -> ((K, V), Handle<NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, marker::Edge>) {
@ -1117,7 +1155,7 @@ impl<'a, K, V> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Internal>, marker::
let mut new_root = Root { node: BoxedNode::from_internal(new_node), height };
for i in 0..(new_len + 1) {
Handle::new_edge(new_root.as_mut().cast_unchecked(), i).correct_parent_link();
Handle::new_edge(new_root.node_as_mut().cast_unchecked(), i).correct_parent_link();
}
(self.node, k, v, new_root)
@ -1138,7 +1176,7 @@ impl<'a, K, V> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Internal>, marker::
/// to by this handle, and the node immediately to the right of this handle into one new
/// child of the underlying node, returning an edge referencing that new child.
///
/// Assumes that this edge `.can_merge()`.
/// Panics unless this edge `.can_merge()`.
pub fn merge(
mut self,
) -> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Internal>, marker::Edge> {
@ -1146,10 +1184,9 @@ impl<'a, K, V> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Internal>, marker::
let self2 = unsafe { ptr::read(&self) };
let mut left_node = self1.left_edge().descend();
let left_len = left_node.len();
let mut right_node = self2.right_edge().descend();
let right_node = self2.right_edge().descend();
let right_len = right_node.len();
// necessary for correctness, but in a private module
assert!(left_len + right_len < CAPACITY);
unsafe {
@ -1180,28 +1217,25 @@ impl<'a, K, V> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Internal>, marker::
(*left_node.as_leaf_mut()).len += right_len as u16 + 1;
let layout = if self.node.height > 1 {
if self.node.height > 1 {
// SAFETY: the height of the nodes being merged is one below the height
// of the node of this edge, thus above zero, so they are internal.
let mut left_node = left_node.cast_unchecked();
let right_node = right_node.cast_unchecked();
ptr::copy_nonoverlapping(
right_node.cast_unchecked().as_internal().edges.as_ptr(),
left_node
.cast_unchecked()
.as_internal_mut()
.edges
.as_mut_ptr()
.add(left_len + 1),
right_node.reborrow().as_internal().edges.as_ptr(),
left_node.reborrow_mut().as_internal_mut().edges.as_mut_ptr().add(left_len + 1),
right_len + 1,
);
for i in left_len + 1..left_len + right_len + 2 {
Handle::new_edge(left_node.cast_unchecked().reborrow_mut(), i)
.correct_parent_link();
Handle::new_edge(left_node.reborrow_mut(), i).correct_parent_link();
}
Layout::new::<InternalNode<K, V>>()
Global.dealloc(right_node.node.cast(), Layout::new::<InternalNode<K, V>>());
} else {
Layout::new::<LeafNode<K, V>>()
};
Global.dealloc(right_node.node.cast(), layout);
Global.dealloc(right_node.node.cast(), Layout::new::<LeafNode<K, V>>());
}
Handle::new_edge(self.node, self.idx)
}
@ -1214,8 +1248,8 @@ impl<'a, K, V> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Internal>, marker::
unsafe {
let (k, v, edge) = self.reborrow_mut().left_edge().descend().pop();
let k = mem::replace(self.reborrow_mut().into_kv_mut().0, k);
let v = mem::replace(self.reborrow_mut().into_kv_mut().1, v);
let k = mem::replace(self.kv_mut().0, k);
let v = mem::replace(self.kv_mut().1, v);
match self.reborrow_mut().right_edge().descend().force() {
ForceResult::Leaf(mut leaf) => leaf.push_front(k, v),
@ -1231,8 +1265,8 @@ impl<'a, K, V> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Internal>, marker::
unsafe {
let (k, v, edge) = self.reborrow_mut().right_edge().descend().pop_front();
let k = mem::replace(self.reborrow_mut().into_kv_mut().0, k);
let v = mem::replace(self.reborrow_mut().into_kv_mut().1, v);
let k = mem::replace(self.kv_mut().0, k);
let v = mem::replace(self.kv_mut().1, v);
match self.reborrow_mut().left_edge().descend().force() {
ForceResult::Leaf(mut leaf) => leaf.push(k, v),
@ -1260,7 +1294,7 @@ impl<'a, K, V> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Internal>, marker::
let left_kv = left_node.reborrow_mut().into_kv_pointers_mut();
let right_kv = right_node.reborrow_mut().into_kv_pointers_mut();
let parent_kv = {
let kv = self.reborrow_mut().into_kv_mut();
let kv = self.kv_mut();
(kv.0 as *mut K, kv.1 as *mut V)
};
@ -1317,7 +1351,7 @@ impl<'a, K, V> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Internal>, marker::
let left_kv = left_node.reborrow_mut().into_kv_pointers_mut();
let right_kv = right_node.reborrow_mut().into_kv_pointers_mut();
let parent_kv = {
let kv = self.reborrow_mut().into_kv_mut();
let kv = self.kv_mut();
(kv.0 as *mut K, kv.1 as *mut V)
};
@ -1543,3 +1577,6 @@ unsafe fn slice_remove<T>(slice: &mut [T], idx: usize) -> T {
ret
}
}
#[cfg(test)]
mod tests;

View File

@ -0,0 +1,25 @@
use super::*;
#[test]
fn test_splitpoint() {
for idx in 0..=CAPACITY {
let (middle_kv_idx, insertion) = splitpoint(idx);
// Simulate performing the split:
let mut left_len = middle_kv_idx;
let mut right_len = CAPACITY - middle_kv_idx - 1;
match insertion {
InsertionPlace::Left(edge_idx) => {
assert!(edge_idx <= left_len);
left_len += 1;
}
InsertionPlace::Right(edge_idx) => {
assert!(edge_idx <= right_len);
right_len += 1;
}
}
assert!(left_len >= MIN_LEN);
assert!(right_len >= MIN_LEN);
assert!(left_len + right_len == CAPACITY);
}
}

View File

@ -1572,3 +1572,6 @@ impl<'a, T: Ord> Iterator for Union<'a, T> {
#[stable(feature = "fused", since = "1.26.0")]
impl<T: Ord> FusedIterator for Union<'_, T> {}
#[cfg(test)]
mod tests;

View File

@ -1,9 +1,10 @@
use std::collections::BTreeSet;
use crate::collections::BTreeSet;
use crate::vec::Vec;
use std::iter::FromIterator;
use std::panic::{catch_unwind, AssertUnwindSafe};
use std::sync::atomic::{AtomicU32, Ordering};
use super::DeterministicRng;
use super::super::DeterministicRng;
#[test]
fn test_clone_eq() {
@ -15,24 +16,6 @@ fn test_clone_eq() {
assert_eq!(m.clone(), m);
}
#[test]
fn test_hash() {
use crate::hash;
let mut x = BTreeSet::new();
let mut y = BTreeSet::new();
x.insert(1);
x.insert(2);
x.insert(3);
y.insert(3);
y.insert(2);
y.insert(1);
assert_eq!(hash(&x), hash(&y));
}
#[test]
fn test_iter_min_max() {
let mut a = BTreeSet::new();

View File

@ -239,7 +239,7 @@
//! println!("{}, `{name:>8.*}` has 3 right-aligned characters", "Hello", 3, name="1234.56");
//! ```
//!
//! print two significantly different things:
//! print three significantly different things:
//!
//! ```text
//! Hello, `1234.560` has 3 fractional digits

View File

@ -80,6 +80,7 @@
#![feature(arbitrary_self_types)]
#![feature(box_patterns)]
#![feature(box_syntax)]
#![feature(btree_drain_filter)]
#![feature(cfg_sanitize)]
#![feature(cfg_target_has_atomic)]
#![feature(coerce_unsized)]
@ -93,6 +94,7 @@
#![feature(container_error_extra)]
#![feature(dropck_eyepatch)]
#![feature(exact_size_is_empty)]
#![feature(exclusive_range_pattern)]
#![feature(extend_one)]
#![feature(fmt_internals)]
#![feature(fn_traits)]
@ -101,6 +103,8 @@
#![feature(lang_items)]
#![feature(layout_for_ptr)]
#![feature(libc)]
#![feature(map_first_last)]
#![feature(map_into_keys_values)]
#![feature(negative_impls)]
#![feature(new_uninit)]
#![feature(nll)]

View File

@ -2269,7 +2269,7 @@ impl<T> Vec<T> {
/// with the given `replace_with` iterator and yields the removed items.
/// `replace_with` does not need to be the same length as `range`.
///
/// The element range is removed even if the iterator is not consumed until the end.
/// `range` is removed even if the iterator is not consumed until the end.
///
/// It is unspecified how many elements are removed from the vector
/// if the `Splice` value is leaked.
@ -2620,9 +2620,6 @@ where
///
/// This `struct` is created by the `into_iter` method on [`Vec`] (provided
/// by the [`IntoIterator`] trait).
///
/// [`Vec`]: struct.Vec.html
/// [`IntoIterator`]: ../../std/iter/trait.IntoIterator.html
#[stable(feature = "rust1", since = "1.0.0")]
pub struct IntoIter<T> {
buf: NonNull<T>,
@ -2802,10 +2799,7 @@ unsafe impl<#[may_dangle] T> Drop for IntoIter<T> {
/// A draining iterator for `Vec<T>`.
///
/// This `struct` is created by the [`drain`] method on [`Vec`].
///
/// [`drain`]: struct.Vec.html#method.drain
/// [`Vec`]: struct.Vec.html
/// This `struct` is created by [`Vec::drain`].
#[stable(feature = "drain", since = "1.6.0")]
pub struct Drain<'a, T: 'a> {
/// Index of tail to preserve
@ -2933,11 +2927,8 @@ impl<T> FusedIterator for Drain<'_, T> {}
/// A splicing iterator for `Vec`.
///
/// This struct is created by the [`splice()`] method on [`Vec`]. See its
/// documentation for more.
///
/// [`splice()`]: struct.Vec.html#method.splice
/// [`Vec`]: struct.Vec.html
/// This struct is created by [`Vec::splice()`].
/// See its documentation for more.
#[derive(Debug)]
#[stable(feature = "vec_splice", since = "1.21.0")]
pub struct Splice<'a, I: Iterator + 'a> {

View File

@ -1,27 +0,0 @@
mod map;
mod set;
/// XorShiftRng
struct DeterministicRng {
x: u32,
y: u32,
z: u32,
w: u32,
}
impl DeterministicRng {
fn new() -> Self {
DeterministicRng { x: 0x193a6754, y: 0xa8a7d469, z: 0x97830e05, w: 0x113ba7bb }
}
fn next(&mut self) -> u32 {
let x = self.x;
let t = x ^ (x << 11);
self.x = self.y;
self.y = self.z;
self.z = self.w;
let w_ = self.w;
self.w = w_ ^ (w_ >> 19) ^ (t ^ (t >> 8));
self.w
}
}

View File

@ -0,0 +1,19 @@
use std::collections::BTreeSet;
#[test]
fn test_hash() {
use crate::hash;
let mut x = BTreeSet::new();
let mut y = BTreeSet::new();
x.insert(1);
x.insert(2);
x.insert(3);
y.insert(3);
y.insert(2);
y.insert(1);
assert_eq!(hash(&x), hash(&y));
}

View File

@ -1,10 +1,7 @@
#![feature(allocator_api)]
#![feature(box_syntax)]
#![feature(btree_drain_filter)]
#![feature(drain_filter)]
#![feature(exact_size_is_empty)]
#![feature(map_first_last)]
#![feature(map_into_keys_values)]
#![feature(new_uninit)]
#![feature(pattern)]
#![feature(str_split_once)]
@ -25,7 +22,7 @@ mod arc;
mod binary_heap;
mod borrow;
mod boxed;
mod btree;
mod btree_set_hash;
mod cow_str;
mod fmt;
mod heap;

View File

@ -1522,7 +1522,7 @@ fn test_copy_from_slice() {
}
#[test]
#[should_panic(expected = "destination and source slices have different lengths")]
#[should_panic(expected = "source slice length (4) does not match destination slice length (5)")]
fn test_copy_from_slice_dst_longer() {
let src = [0, 1, 2, 3];
let mut dst = [0; 5];
@ -1530,7 +1530,7 @@ fn test_copy_from_slice_dst_longer() {
}
#[test]
#[should_panic(expected = "destination and source slices have different lengths")]
#[should_panic(expected = "source slice length (4) does not match destination slice length (3)")]
fn test_copy_from_slice_dst_shorter() {
let src = [0, 1, 2, 3];
let mut dst = [0; 3];

View File

@ -364,3 +364,66 @@ macro_rules! array_impl_default {
}
array_impl_default! {32, T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T T}
#[cfg(not(bootstrap))]
#[lang = "array"]
impl<T, const N: usize> [T; N] {
/// Returns an array of the same size as `self`, with function `f` applied to each element
/// in order.
///
/// # Examples
///
/// ```
/// #![feature(array_map)]
/// let x = [1, 2, 3];
/// let y = x.map(|v| v + 1);
/// assert_eq!(y, [2, 3, 4]);
///
/// let x = [1, 2, 3];
/// let mut temp = 0;
/// let y = x.map(|v| { temp += 1; v * temp });
/// assert_eq!(y, [1, 4, 9]);
///
/// let x = ["Ferris", "Bueller's", "Day", "Off"];
/// let y = x.map(|v| v.len());
/// assert_eq!(y, [6, 9, 3, 3]);
/// ```
#[unstable(feature = "array_map", issue = "75243")]
pub fn map<F, U>(self, mut f: F) -> [U; N]
where
F: FnMut(T) -> U,
{
use crate::mem::MaybeUninit;
struct Guard<T, const N: usize> {
dst: *mut T,
initialized: usize,
}
impl<T, const N: usize> Drop for Guard<T, N> {
fn drop(&mut self) {
debug_assert!(self.initialized <= N);
let initialized_part =
crate::ptr::slice_from_raw_parts_mut(self.dst, self.initialized);
// SAFETY: this raw slice will contain only initialized objects
// that's why, it is allowed to drop it.
unsafe {
crate::ptr::drop_in_place(initialized_part);
}
}
}
let mut dst = MaybeUninit::uninit_array::<N>();
let mut guard: Guard<U, N> =
Guard { dst: MaybeUninit::first_ptr_mut(&mut dst), initialized: 0 };
for (src, dst) in IntoIter::new(self).zip(&mut dst) {
dst.write(f(src));
guard.initialized += 1;
}
// FIXME: Convert to crate::mem::transmute once it works with generics.
// unsafe { crate::mem::transmute::<[MaybeUninit<U>; N], [U; N]>(dst) }
crate::mem::forget(guard);
// SAFETY: At this point we've properly initialized the whole array
// and we just need to cast it to the correct type.
unsafe { crate::mem::transmute_copy::<_, [U; N]>(&dst) }
}
}

View File

@ -40,14 +40,12 @@
/// provide a reference to related type `T`, it is often better to use
/// [`AsRef<T>`] as more types can safely implement it.
///
/// [`AsRef<T>`]: ../../std/convert/trait.AsRef.html
/// [`BorrowMut<T>`]: trait.BorrowMut.html
/// [`BorrowMut<T>`]: BorrowMut
/// [`Box<T>`]: ../../std/boxed/struct.Box.html
/// [`Mutex<T>`]: ../../std/sync/struct.Mutex.html
/// [`Rc<T>`]: ../../std/rc/struct.Rc.html
/// [`str`]: ../../std/primitive.str.html
/// [`String`]: ../../std/string/struct.String.html
/// [`borrow`]: #tymethod.borrow
/// [`borrow`]: Borrow::borrow
///
/// # Examples
///
@ -152,10 +150,9 @@
/// If it wants to allow others access to the underlying `str`, it can do
/// that via `AsRef<str>` which doesnt carry any extra requirements.
///
/// [`Hash`]: ../../std/hash/trait.Hash.html
/// [`Hash`]: crate::hash::Hash
/// [`HashMap<K, V>`]: ../../std/collections/struct.HashMap.html
/// [`String`]: ../../std/string/struct.String.html
/// [`str`]: ../../std/primitive.str.html
#[stable(feature = "rust1", since = "1.0.0")]
pub trait Borrow<Borrowed: ?Sized> {
/// Immutably borrows from an owned value.
@ -187,7 +184,7 @@ pub trait Borrow<Borrowed: ?Sized> {
/// an underlying type by providing a mutable reference. See [`Borrow<T>`]
/// for more information on borrowing as another type.
///
/// [`Borrow<T>`]: trait.Borrow.html
/// [`Borrow<T>`]: Borrow
#[stable(feature = "rust1", since = "1.0.0")]
pub trait BorrowMut<Borrowed: ?Sized>: Borrow<Borrowed> {
/// Mutably borrows from an owned value.

View File

@ -17,14 +17,8 @@
//!
//! For more details, see the respective documentation of each item in the list.
//!
//! [`Eq`]: trait.Eq.html
//! [`PartialEq`]: trait.PartialEq.html
//! [`Ord`]: trait.Ord.html
//! [`PartialOrd`]: trait.PartialOrd.html
//! [`Ordering`]: enum.Ordering.html
//! [`Reverse`]: struct.Reverse.html
//! [`max`]: fn.max.html
//! [`min`]: fn.min.html
//! [`max`]: Ord::max
//! [`min`]: Ord::min
#![stable(feature = "rust1", since = "1.0.0")]

View File

@ -145,6 +145,7 @@
#![feature(abi_unadjusted)]
#![feature(adx_target_feature)]
#![feature(maybe_uninit_slice)]
#![feature(maybe_uninit_extra)]
#![feature(external_doc)]
#![feature(associated_type_bounds)]
#![feature(const_caller_location)]

View File

@ -56,9 +56,9 @@ use crate::ptr;
/// working with [pinned] data, where reusing the memory without calling the destructor could lead
/// to Undefined Behaviour.
///
/// [`mem::zeroed`]: fn.zeroed.html
/// [`MaybeUninit<T>`]: union.MaybeUninit.html
/// [pinned]: ../pin/index.html
/// [`mem::zeroed`]: crate::mem::zeroed
/// [`MaybeUninit<T>`]: crate::mem::MaybeUninit
/// [pinned]: crate::pin
#[stable(feature = "manually_drop", since = "1.20.0")]
#[lang = "manually_drop"]
#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
@ -116,8 +116,6 @@ impl<T> ManuallyDrop<T> {
/// leaving the state of this container unchanged.
/// It is your responsibility to ensure that this `ManuallyDrop` is not used again.
///
/// [`ManuallyDrop::drop`]: #method.drop
/// [`ManuallyDrop::into_inner`]: #method.into_inner
#[must_use = "if you don't need the value, you can use `ManuallyDrop::drop` instead"]
#[stable(feature = "manually_drop_take", since = "1.42.0")]
#[inline]
@ -148,9 +146,7 @@ impl<T: ?Sized> ManuallyDrop<T> {
/// This is normally prevented by the type system, but users of `ManuallyDrop` must
/// uphold those guarantees without assistance from the compiler.
///
/// [`ManuallyDrop::into_inner`]: #method.into_inner
/// [`ptr::drop_in_place`]: ../ptr/fn.drop_in_place.html
/// [pinned]: ../pin/index.html
/// [pinned]: crate::pin
#[stable(feature = "manually_drop", since = "1.20.0")]
#[inline]
pub unsafe fn drop(slot: &mut ManuallyDrop<T>) {

View File

@ -247,7 +247,7 @@ impl<T> MaybeUninit<T> {
/// Note that dropping a `MaybeUninit<T>` will never call `T`'s drop code.
/// It is your responsibility to make sure `T` gets dropped if it got initialized.
///
/// [`assume_init`]: #method.assume_init
/// [`assume_init`]: MaybeUninit::assume_init
#[stable(feature = "maybe_uninit", since = "1.36.0")]
#[rustc_const_stable(feature = "const_maybe_uninit", since = "1.36.0")]
#[inline(always)]
@ -525,7 +525,7 @@ impl<T> MaybeUninit<T> {
/// to ensure that that data may indeed be duplicated.
///
/// [inv]: #initialization-invariant
/// [`assume_init`]: #method.assume_init
/// [`assume_init`]: MaybeUninit::assume_init
///
/// # Examples
///

View File

@ -662,6 +662,11 @@ impl<T: ?Sized> *const T {
/// will only affect the pointer part, whereas for (thin) pointers to
/// sized types, this has the same effect as a simple assignment.
///
/// The resulting pointer will have provenance of `val`, i.e., for a fat
/// pointer, this operation is semantically the same as creating a new
/// fat pointer with the data pointer value of `val` but the metadata of
/// `self`.
///
/// # Examples
///
/// This function is primarily useful for allowing byte-wise pointer
@ -673,13 +678,17 @@ impl<T: ?Sized> *const T {
/// let arr: [i32; 3] = [1, 2, 3];
/// let mut ptr = &arr[0] as *const dyn Debug;
/// let thin = ptr as *const u8;
/// ptr = ptr.set_ptr_value(unsafe { thin.add(8).cast() });
/// assert_eq!(unsafe { *(ptr as *const i32) }, 3);
/// unsafe {
/// ptr = ptr.set_ptr_value(thin.add(8));
/// # assert_eq!(*(ptr as *const i32), 3);
/// println!("{:?}", &*ptr); // will print "3"
/// }
/// ```
#[unstable(feature = "set_ptr_value", issue = "75091")]
#[must_use = "returns a new pointer rather than modifying its argument"]
#[inline]
pub fn set_ptr_value(mut self, val: *const ()) -> Self {
let thin = &mut self as *mut *const T as *mut *const ();
pub fn set_ptr_value(mut self, val: *const u8) -> Self {
let thin = &mut self as *mut *const T as *mut *const u8;
// SAFETY: In case of a thin pointer, this operations is identical
// to a simple assignment. In case of a fat pointer, with the current
// fat pointer layout implementation, the first field of such a

View File

@ -718,6 +718,11 @@ impl<T: ?Sized> *mut T {
/// will only affect the pointer part, whereas for (thin) pointers to
/// sized types, this has the same effect as a simple assignment.
///
/// The resulting pointer will have provenance of `val`, i.e., for a fat
/// pointer, this operation is semantically the same as creating a new
/// fat pointer with the data pointer value of `val` but the metadata of
/// `self`.
///
/// # Examples
///
/// This function is primarily useful for allowing byte-wise pointer
@ -729,13 +734,17 @@ impl<T: ?Sized> *mut T {
/// let mut arr: [i32; 3] = [1, 2, 3];
/// let mut ptr = &mut arr[0] as *mut dyn Debug;
/// let thin = ptr as *mut u8;
/// ptr = ptr.set_ptr_value(unsafe { thin.add(8).cast() });
/// assert_eq!(unsafe { *(ptr as *mut i32) }, 3);
/// unsafe {
/// ptr = ptr.set_ptr_value(thin.add(8));
/// # assert_eq!(*(ptr as *mut i32), 3);
/// println!("{:?}", &*ptr); // will print "3"
/// }
/// ```
#[unstable(feature = "set_ptr_value", issue = "75091")]
#[must_use = "returns a new pointer rather than modifying its argument"]
#[inline]
pub fn set_ptr_value(mut self, val: *mut ()) -> Self {
let thin = &mut self as *mut *mut T as *mut *mut ();
pub fn set_ptr_value(mut self, val: *mut u8) -> Self {
let thin = &mut self as *mut *mut T as *mut *mut u8;
// SAFETY: In case of a thin pointer, this operations is identical
// to a simple assignment. In case of a fat pointer, with the current
// fat pointer layout implementation, the first field of such a

View File

@ -1,5 +1,4 @@
// ignore-tidy-filelength
// ignore-tidy-undocumented-unsafe
//! Slice management and manipulation.
//!
@ -70,6 +69,8 @@ impl<T> [T] {
#[allow(unused_attributes)]
#[allow_internal_unstable(const_fn_union)]
pub const fn len(&self) -> usize {
// SAFETY: this is safe because `&[T]` and `FatPtr<T>` have the same layout.
// Only `std` can make this guarantee.
unsafe { crate::ptr::Repr { rust: self }.raw.len }
}
@ -443,7 +444,8 @@ impl<T> [T] {
#[unstable(feature = "slice_ptr_range", issue = "65807")]
#[inline]
pub fn as_ptr_range(&self) -> Range<*const T> {
// The `add` here is safe, because:
let start = self.as_ptr();
// SAFETY: The `add` here is safe, because:
//
// - Both pointers are part of the same object, as pointing directly
// past the object also counts.
@ -460,7 +462,6 @@ impl<T> [T] {
// the end of the address space.
//
// See the documentation of pointer::add.
let start = self.as_ptr();
let end = unsafe { start.add(self.len()) };
start..end
}
@ -484,8 +485,8 @@ impl<T> [T] {
#[unstable(feature = "slice_ptr_range", issue = "65807")]
#[inline]
pub fn as_mut_ptr_range(&mut self) -> Range<*mut T> {
// See as_ptr_range() above for why `add` here is safe.
let start = self.as_mut_ptr();
// SAFETY: See as_ptr_range() above for why `add` here is safe.
let end = unsafe { start.add(self.len()) };
start..end
}
@ -511,11 +512,15 @@ impl<T> [T] {
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn swap(&mut self, a: usize, b: usize) {
// Can't take two mutable loans from one vector, so instead just cast
// them to their raw pointers to do the swap.
let pa: *mut T = &mut self[a];
let pb: *mut T = &mut self[b];
// SAFETY: `pa` and `pb` have been created from safe mutable references and refer
// to elements in the slice and therefore are guaranteed to be valid and aligned.
// Note that accessing the elements behind `a` and `b` is checked and will
// panic when out of bounds.
unsafe {
// Can't take two mutable loans from one vector, so instead just cast
// them to their raw pointers to do the swap
let pa: *mut T = &mut self[a];
let pb: *mut T = &mut self[b];
ptr::swap(pa, pb);
}
}
@ -554,6 +559,24 @@ impl<T> [T] {
// Use the llvm.bswap intrinsic to reverse u8s in a usize
let chunk = mem::size_of::<usize>();
while i + chunk - 1 < ln / 2 {
// SAFETY: There are several things to check here:
//
// - Note that `chunk` is either 4 or 8 due to the cfg check
// above. So `chunk - 1` is positive.
// - Indexing with index `i` is fine as the loop check guarantees
// `i + chunk - 1 < ln / 2`
// <=> `i < ln / 2 - (chunk - 1) < ln / 2 < ln`.
// - Indexing with index `ln - i - chunk = ln - (i + chunk)` is fine:
// - `i + chunk > 0` is trivially true.
// - The loop check guarantees:
// `i + chunk - 1 < ln / 2`
// <=> `i + chunk ≤ ln / 2 ≤ ln`, thus subtraction does not underflow.
// - The `read_unaligned` and `write_unaligned` calls are fine:
// - `pa` points to index `i` where `i < ln / 2 - (chunk - 1)`
// (see above) and `pb` points to index `ln - i - chunk`, so
// both are at least `chunk`
// many bytes away from the end of `self`.
// - Any initialized memory is valid `usize`.
unsafe {
let pa: *mut T = self.get_unchecked_mut(i);
let pb: *mut T = self.get_unchecked_mut(ln - i - chunk);
@ -570,6 +593,20 @@ impl<T> [T] {
// Use rotate-by-16 to reverse u16s in a u32
let chunk = mem::size_of::<u32>() / 2;
while i + chunk - 1 < ln / 2 {
// SAFETY: An unaligned u32 can be read from `i` if `i + 1 < ln`
// (and obviously `i < ln`), because each element is 2 bytes and
// we're reading 4.
//
// `i + chunk - 1 < ln / 2` # while condition
// `i + 2 - 1 < ln / 2`
// `i + 1 < ln / 2`
//
// Since it's less than the length divided by 2, then it must be
// in bounds.
//
// This also means that the condition `0 < i + chunk <= ln` is
// always respected, ensuring the `pb` pointer can be used
// safely.
unsafe {
let pa: *mut T = self.get_unchecked_mut(i);
let pb: *mut T = self.get_unchecked_mut(ln - i - chunk);
@ -583,8 +620,13 @@ impl<T> [T] {
}
while i < ln / 2 {
// Unsafe swap to avoid the bounds check in safe swap.
// SAFETY: `i` is inferior to half the length of the slice so
// accessing `i` and `ln - i - 1` is safe (`i` starts at 0 and
// will not go further than `ln / 2 - 1`).
// The resulting pointers `pa` and `pb` are therefore valid and
// aligned, and can be read from and written to.
unsafe {
// Unsafe swap to avoid the bounds check in safe swap.
let pa: *mut T = self.get_unchecked_mut(i);
let pb: *mut T = self.get_unchecked_mut(ln - i - 1);
ptr::swap(pa, pb);
@ -609,8 +651,24 @@ impl<T> [T] {
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn iter(&self) -> Iter<'_, T> {
let ptr = self.as_ptr();
// SAFETY: There are several things here:
//
// `ptr` has been obtained by `self.as_ptr()` where `self` is a valid
// reference thus it is non-NUL and safe to use and pass to
// `NonNull::new_unchecked` .
//
// Adding `self.len()` to the starting pointer gives a pointer
// at the end of `self`. `end` will never be dereferenced, only checked
// for direct pointer equality with `ptr` to check if the iterator is
// done.
//
// In the case of a ZST, the end pointer is just the start pointer plus
// the length, to also allows for the fast `ptr == end` check.
//
// See the `next_unchecked!` and `is_empty!` macros as well as the
// `post_inc_start` method for more informations.
unsafe {
let ptr = self.as_ptr();
assume(!ptr.is_null());
let end = if mem::size_of::<T>() == 0 {
@ -637,8 +695,24 @@ impl<T> [T] {
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn iter_mut(&mut self) -> IterMut<'_, T> {
let ptr = self.as_mut_ptr();
// SAFETY: There are several things here:
//
// `ptr` has been obtained by `self.as_ptr()` where `self` is a valid
// reference thus it is non-NUL and safe to use and pass to
// `NonNull::new_unchecked` .
//
// Adding `self.len()` to the starting pointer gives a pointer
// at the end of `self`. `end` will never be dereferenced, only checked
// for direct pointer equality with `ptr` to check if the iterator is
// done.
//
// In the case of a ZST, the end pointer is just the start pointer plus
// the length, to also allows for the fast `ptr == end` check.
//
// See the `next_unchecked!` and `is_empty!` macros as well as the
// `post_inc_start` method for more informations.
unsafe {
let ptr = self.as_mut_ptr();
assume(!ptr.is_null());
let end = if mem::size_of::<T>() == 0 {
@ -1107,6 +1181,8 @@ impl<T> [T] {
let len = self.len();
let ptr = self.as_mut_ptr();
// SAFETY: `[ptr; mid]` and `[mid; len]` are inside `self`, which
// fulfills the requirements of `from_raw_parts_mut`.
unsafe {
assert!(mid <= len);
@ -1655,14 +1731,14 @@ impl<T> [T] {
while size > 1 {
let half = size / 2;
let mid = base + half;
// mid is always in [0, size), that means mid is >= 0 and < size.
// mid >= 0: by definition
// mid < size: mid = size / 2 + size / 4 + size / 8 ...
// SAFETY: the call is made safe by the following inconstants:
// - `mid >= 0`: by definition
// - `mid < size`: `mid = size / 2 + size / 4 + size / 8 ...`
let cmp = f(unsafe { s.get_unchecked(mid) });
base = if cmp == Greater { base } else { mid };
size -= half;
}
// base is always in [0, size) because base <= mid.
// SAFETY: base is always in [0, size) because base <= mid.
let cmp = f(unsafe { s.get_unchecked(base) });
if cmp == Equal { Ok(base) } else { Err(base + (cmp == Less) as usize) }
}
@ -2120,6 +2196,21 @@ impl<T> [T] {
let mut next_read: usize = 1;
let mut next_write: usize = 1;
// SAFETY: the `while` condition guarantees `next_read` and `next_write`
// are less than `len`, thus are inside `self`. `prev_ptr_write` points to
// one element before `ptr_write`, but `next_write` starts at 1, so
// `prev_ptr_write` is never less than 0 and is inside the slice.
// This fulfils the requirements for dereferencing `ptr_read`, `prev_ptr_write`
// and `ptr_write`, and for using `ptr.add(next_read)`, `ptr.add(next_write - 1)`
// and `prev_ptr_write.offset(1)`.
//
// `next_write` is also incremented at most once per loop at most meaning
// no element is skipped when it may need to be swapped.
//
// `ptr_read` and `prev_ptr_write` never point to the same element. This
// is required for `&mut *ptr_read`, `&mut *prev_ptr_write` to be safe.
// The explanation is simply that `next_read >= next_write` is always true,
// thus `next_read > next_write - 1` is too.
unsafe {
// Avoid bounds checks by using raw pointers.
while next_read < len {
@ -2203,9 +2294,11 @@ impl<T> [T] {
pub fn rotate_left(&mut self, mid: usize) {
assert!(mid <= self.len());
let k = self.len() - mid;
let p = self.as_mut_ptr();
// SAFETY: The range `[p.add(mid) - mid, p.add(mid) + k)` is trivially
// valid for reading and writing, as required by `ptr_rotate`.
unsafe {
let p = self.as_mut_ptr();
rotate::ptr_rotate(mid, p.add(mid), k);
}
}
@ -2244,9 +2337,11 @@ impl<T> [T] {
pub fn rotate_right(&mut self, k: usize) {
assert!(k <= self.len());
let mid = self.len() - k;
let p = self.as_mut_ptr();
// SAFETY: The range `[p.add(mid) - mid, p.add(mid) + k)` is trivially
// valid for reading and writing, as required by `ptr_rotate`.
unsafe {
let p = self.as_mut_ptr();
rotate::ptr_rotate(mid, p.add(mid), k);
}
}
@ -2406,7 +2501,25 @@ impl<T> [T] {
where
T: Copy,
{
assert_eq!(self.len(), src.len(), "destination and source slices have different lengths");
// The panic code path was put into a cold function to not bloat the
// call site.
#[inline(never)]
#[cold]
#[track_caller]
fn len_mismatch_fail(dst_len: usize, src_len: usize) -> ! {
panic!(
"source slice length ({}) does not match destination slice length ({})",
src_len, dst_len,
);
}
if self.len() != src.len() {
len_mismatch_fail(self.len(), src.len());
}
// SAFETY: `self` is valid for `self.len()` elements by definition, and `src` was
// checked to have the same length. The slices cannot overlap because
// mutable references are exclusive.
unsafe {
ptr::copy_nonoverlapping(src.as_ptr(), self.as_mut_ptr(), self.len());
}
@ -2460,6 +2573,8 @@ impl<T> [T] {
assert!(src_end <= self.len(), "src is out of bounds");
let count = src_end - src_start;
assert!(dest <= self.len() - count, "dest is out of bounds");
// SAFETY: the conditions for `ptr::copy` have all been checked above,
// as have those for `ptr::add`.
unsafe {
ptr::copy(self.as_ptr().add(src_start), self.as_mut_ptr().add(dest), count);
}
@ -2515,6 +2630,9 @@ impl<T> [T] {
#[stable(feature = "swap_with_slice", since = "1.27.0")]
pub fn swap_with_slice(&mut self, other: &mut [T]) {
assert!(self.len() == other.len(), "destination and source slices have different lengths");
// SAFETY: `self` is valid for `self.len()` elements by definition, and `src` was
// checked to have the same length. The slices cannot overlap because
// mutable references are exclusive.
unsafe {
ptr::swap_nonoverlapping(self.as_mut_ptr(), other.as_mut_ptr(), self.len());
}
@ -2546,6 +2664,8 @@ impl<T> [T] {
// iterative steins algorithm
// We should still make this `const fn` (and revert to recursive algorithm if we do)
// because relying on llvm to consteval all this is… well, it makes me uncomfortable.
// SAFETY: `a` and `b` are checked to be non-zero values.
let (ctz_a, mut ctz_b) = unsafe {
if a == 0 {
return b;
@ -2565,6 +2685,7 @@ impl<T> [T] {
mem::swap(&mut a, &mut b);
}
b = b - a;
// SAFETY: `b` is checked to be non-zero.
unsafe {
if b == 0 {
break;
@ -2626,6 +2747,7 @@ impl<T> [T] {
// First, find at what point do we split between the first and 2nd slice. Easy with
// ptr.align_offset.
let ptr = self.as_ptr();
// SAFETY: See the `align_to_mut` method for the detailed safety comment.
let offset = unsafe { crate::ptr::align_offset(ptr, mem::align_of::<U>()) };
if offset > self.len() {
(self, &[], &[])
@ -2685,6 +2807,13 @@ impl<T> [T] {
// First, find at what point do we split between the first and 2nd slice. Easy with
// ptr.align_offset.
let ptr = self.as_ptr();
// SAFETY: Here we are ensuring we will use aligned pointers for U for the
// rest of the method. This is done by passing a pointer to &[T] with an
// alignment targeted for U.
// `crate::ptr::align_offset` is called with a correctly aligned and
// valid pointer `ptr` (it comes from a reference to `self`) and with
// a size that is a power of two (since it comes from the alignement for U),
// satisfying its safety constraints.
let offset = unsafe { crate::ptr::align_offset(ptr, mem::align_of::<U>()) };
if offset > self.len() {
(self, &mut [], &mut [])
@ -2810,15 +2939,13 @@ impl<T> [T] {
while left != right {
let mid = left + (right - left) / 2;
// SAFETY:
// When left < right, left <= mid < right.
// Therefore left always increases and right always decreases,
// and eigher of them is selected.
// In both cases left <= right is satisfied.
// Therefore if left < right in a step,
// left <= right is satisfied in the next step.
// Therefore as long as left != right, 0 <= left < right <= len is satisfied
// and if this case 0 <= mid < len is satisfied too.
// SAFETY: When `left < right`, `left <= mid < right`.
// Therefore `left` always increases and `right` always decreases,
// and either of them is selected. In both cases `left <= right` is
// satisfied. Therefore if `left < right` in a step, `left <= right`
// is satisfied in the next step. Therefore as long as `left != right`,
// `0 <= left < right <= len` is satisfied and if this case
// `0 <= mid < len` is satisfied too.
let value = unsafe { self.get_unchecked(mid) };
if pred(value) {
left = mid + 1;
@ -2938,7 +3065,8 @@ fn is_ascii(s: &[u8]) -> bool {
// above.
debug_assert!(offset_to_aligned <= len);
// word_ptr is the (properly aligned) usize ptr we use to read the middle chunk of the slice.
// SAFETY: word_ptr is the (properly aligned) usize ptr we use to read the
// middle chunk of the slice.
let mut word_ptr = unsafe { start.add(offset_to_aligned) as *const usize };
// `byte_pos` is the byte index of `word_ptr`, used for loop end checks.
@ -3126,11 +3254,13 @@ unsafe impl<T> SliceIndex<[T]> for usize {
#[inline]
fn get(self, slice: &[T]) -> Option<&T> {
// SAFETY: `self` is checked to be in bounds.
if self < slice.len() { unsafe { Some(&*self.get_unchecked(slice)) } } else { None }
}
#[inline]
fn get_mut(self, slice: &mut [T]) -> Option<&mut T> {
// SAFETY: `self` is checked to be in bounds.
if self < slice.len() { unsafe { Some(&mut *self.get_unchecked_mut(slice)) } } else { None }
}
@ -3171,6 +3301,7 @@ unsafe impl<T> SliceIndex<[T]> for ops::Range<usize> {
if self.start > self.end || self.end > slice.len() {
None
} else {
// SAFETY: `self` is checked to be valid and in bounds above.
unsafe { Some(&*self.get_unchecked(slice)) }
}
}
@ -3180,6 +3311,7 @@ unsafe impl<T> SliceIndex<[T]> for ops::Range<usize> {
if self.start > self.end || self.end > slice.len() {
None
} else {
// SAFETY: `self` is checked to be valid and in bounds above.
unsafe { Some(&mut *self.get_unchecked_mut(slice)) }
}
}
@ -3208,6 +3340,7 @@ unsafe impl<T> SliceIndex<[T]> for ops::Range<usize> {
} else if self.end > slice.len() {
slice_end_index_len_fail(self.end, slice.len());
}
// SAFETY: `self` is checked to be valid and in bounds above.
unsafe { &*self.get_unchecked(slice) }
}
@ -3218,6 +3351,7 @@ unsafe impl<T> SliceIndex<[T]> for ops::Range<usize> {
} else if self.end > slice.len() {
slice_end_index_len_fail(self.end, slice.len());
}
// SAFETY: `self` is checked to be valid and in bounds above.
unsafe { &mut *self.get_unchecked_mut(slice) }
}
}
@ -3290,6 +3424,7 @@ unsafe impl<T> SliceIndex<[T]> for ops::RangeFrom<usize> {
if self.start > slice.len() {
slice_start_index_len_fail(self.start, slice.len());
}
// SAFETY: `self` is checked to be valid and in bounds above.
unsafe { &*self.get_unchecked(slice) }
}
@ -3298,6 +3433,7 @@ unsafe impl<T> SliceIndex<[T]> for ops::RangeFrom<usize> {
if self.start > slice.len() {
slice_start_index_len_fail(self.start, slice.len());
}
// SAFETY: `self` is checked to be valid and in bounds above.
unsafe { &mut *self.get_unchecked_mut(slice) }
}
}
@ -3543,6 +3679,9 @@ macro_rules! iterator {
// Helper function for creating a slice from the iterator.
#[inline(always)]
fn make_slice(&self) -> &'a [T] {
// SAFETY: the iterator was created from a slice with pointer
// `self.ptr` and length `len!(self)`. This guarantees that all
// the prerequisites for `from_raw_parts` are fulfilled.
unsafe { from_raw_parts(self.ptr.as_ptr(), len!(self)) }
}
@ -3601,6 +3740,11 @@ macro_rules! iterator {
#[inline]
fn next(&mut self) -> Option<$elem> {
// could be implemented with slices, but this avoids bounds checks
// SAFETY: `assume` calls are safe since a slice's start pointer
// must be non-null, and slices over non-ZSTs must also have a
// non-null end pointer. The call to `next_unchecked!` is safe
// since we check if the iterator is empty first.
unsafe {
assume(!self.ptr.as_ptr().is_null());
if mem::size_of::<T>() != 0 {
@ -3634,14 +3778,14 @@ macro_rules! iterator {
// could be (due to wrapping).
self.end = self.ptr.as_ptr();
} else {
// SAFETY: end can't be 0 if T isn't ZST because ptr isn't 0 and end >= ptr
unsafe {
// End can't be 0 if T isn't ZST because ptr isn't 0 and end >= ptr
self.ptr = NonNull::new_unchecked(self.end as *mut T);
}
}
return None;
}
// We are in bounds. `post_inc_start` does the right thing even for ZSTs.
// SAFETY: We are in bounds. `post_inc_start` does the right thing even for ZSTs.
unsafe {
self.post_inc_start(n as isize);
Some(next_unchecked!(self))
@ -3748,6 +3892,8 @@ macro_rules! iterator {
let mut i = 0;
while let Some(x) = self.next() {
if predicate(x) {
// SAFETY: we are guaranteed to be in bounds by the loop invariant:
// when `i >= n`, `self.next()` returns `None` and the loop breaks.
unsafe { assume(i < n) };
return Some(i);
}
@ -3769,6 +3915,8 @@ macro_rules! iterator {
while let Some(x) = self.next_back() {
i -= 1;
if predicate(x) {
// SAFETY: `i` must be lower than `n` since it starts at `n`
// and is only decreasing.
unsafe { assume(i < n) };
return Some(i);
}
@ -3784,6 +3932,11 @@ macro_rules! iterator {
#[inline]
fn next_back(&mut self) -> Option<$elem> {
// could be implemented with slices, but this avoids bounds checks
// SAFETY: `assume` calls are safe since a slice's start pointer must be non-null,
// and slices over non-ZSTs must also have a non-null end pointer.
// The call to `next_back_unchecked!` is safe since we check if the iterator is
// empty first.
unsafe {
assume(!self.ptr.as_ptr().is_null());
if mem::size_of::<T>() != 0 {
@ -3804,7 +3957,7 @@ macro_rules! iterator {
self.end = self.ptr.as_ptr();
return None;
}
// We are in bounds. `pre_dec_end` does the right thing even for ZSTs.
// SAFETY: We are in bounds. `pre_dec_end` does the right thing even for ZSTs.
unsafe {
self.pre_dec_end(n as isize);
Some(next_back_unchecked!(self))
@ -3999,6 +4152,9 @@ impl<'a, T> IterMut<'a, T> {
/// ```
#[stable(feature = "iter_to_slice", since = "1.4.0")]
pub fn into_slice(self) -> &'a mut [T] {
// SAFETY: the iterator was created from a mutable slice with pointer
// `self.ptr` and length `len!(self)`. This guarantees that all the prerequisites
// for `from_raw_parts_mut` are fulfilled.
unsafe { from_raw_parts_mut(self.ptr.as_ptr(), len!(self)) }
}
@ -5568,6 +5724,8 @@ impl<T, const N: usize> FusedIterator for ArrayChunks<'_, T, N> {}
#[unstable(feature = "array_chunks", issue = "74985")]
unsafe impl<'a, T, const N: usize> TrustedRandomAccess for ArrayChunks<'a, T, N> {
unsafe fn get_unchecked(&mut self, i: usize) -> &'a [T; N] {
// SAFETY: The safety guarantees of `get_unchecked` are transferred to
// the caller.
unsafe { self.iter.get_unchecked(i) }
}
fn may_have_side_effect() -> bool {
@ -6288,12 +6446,20 @@ pub unsafe fn from_raw_parts_mut<'a, T>(data: *mut T, len: usize) -> &'a mut [T]
/// Converts a reference to T into a slice of length 1 (without copying).
#[stable(feature = "from_ref", since = "1.28.0")]
pub fn from_ref<T>(s: &T) -> &[T] {
// SAFETY: a reference is guaranteed to be valid for reads. The returned
// reference cannot be mutated as it is an immutable reference.
// `mem::size_of::<T>()` cannot be larger than `isize::MAX`.
// Thus the call to `from_raw_parts` is safe.
unsafe { from_raw_parts(s, 1) }
}
/// Converts a reference to T into a slice of length 1 (without copying).
#[stable(feature = "from_ref", since = "1.28.0")]
pub fn from_mut<T>(s: &mut T) -> &mut [T] {
// SAFETY: a mutable reference is guaranteed to be valid for writes.
// The reference cannot be accessed by another pointer as it is an mutable reference.
// `mem::size_of::<T>()` cannot be larger than `isize::MAX`.
// Thus the call to `from_raw_parts_mut` is safe.
unsafe { from_raw_parts_mut(s, 1) }
}
@ -6414,6 +6580,8 @@ where
if self.as_ptr().guaranteed_eq(other.as_ptr()) {
return true;
}
// SAFETY: `self` and `other` are references and are thus guaranteed to be valid.
// The two slices have been checked to have the same size above.
unsafe {
let size = mem::size_of_val(self);
memcmp(self.as_ptr() as *const u8, other.as_ptr() as *const u8, size) == 0
@ -6516,6 +6684,9 @@ impl SliceOrd for u8 {
#[inline]
fn compare(left: &[Self], right: &[Self]) -> Ordering {
let order =
// SAFETY: `left` and `right` are references and are thus guaranteed to be valid.
// We use the minimum of both lengths which guarantees that both regions are
// valid for reads in that interval.
unsafe { memcmp(left.as_ptr(), right.as_ptr(), cmp::min(left.len(), right.len())) };
if order == 0 {
left.len().cmp(&right.len())
@ -6590,6 +6761,10 @@ impl SliceContains for u8 {
impl SliceContains for i8 {
fn slice_contains(&self, x: &[Self]) -> bool {
let byte = *self as u8;
// SAFETY: `i8` and `u8` have the same memory layout, thus casting `x.as_ptr()`
// as `*const u8` is safe. The `x.as_ptr()` comes from a reference and is thus guaranteed
// to be valid for reads for the length of the slice `x.len()`, which cannot be larger
// than `isize::MAX`. The returned slice is never mutated.
let bytes: &[u8] = unsafe { from_raw_parts(x.as_ptr() as *const u8, x.len()) };
memchr::memchr(byte, bytes).is_some()
}

View File

@ -414,12 +414,13 @@ pub fn from_utf8_mut(v: &mut [u8]) -> Result<&mut str, Utf8Error> {
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub unsafe fn from_utf8_unchecked(v: &[u8]) -> &str {
// SAFETY: the caller must guarantee that the bytes `v`
// are valid UTF-8, thus the cast to `*const str` is safe.
// Also, the pointer dereference is safe because that pointer
// comes from a reference which is guaranteed to be valid for reads.
unsafe { &*(v as *const [u8] as *const str) }
#[rustc_const_unstable(feature = "const_str_from_utf8_unchecked", issue = "75196")]
#[allow(unused_attributes)]
#[allow_internal_unstable(const_fn_transmute)]
pub const unsafe fn from_utf8_unchecked(v: &[u8]) -> &str {
// SAFETY: the caller must guarantee that the bytes `v` are valid UTF-8.
// Also relies on `&str` and `&[u8]` having the same layout.
unsafe { mem::transmute(v) }
}
/// Converts a slice of bytes to a string slice without checking
@ -2357,15 +2358,10 @@ impl str {
#[rustc_const_stable(feature = "str_as_bytes", since = "1.32.0")]
#[inline(always)]
#[allow(unused_attributes)]
#[allow_internal_unstable(const_fn_union)]
#[allow_internal_unstable(const_fn_transmute)]
pub const fn as_bytes(&self) -> &[u8] {
#[repr(C)]
union Slices<'a> {
str: &'a str,
slice: &'a [u8],
}
// SAFETY: const sound because we transmute two types with the same layout
unsafe { Slices { str: self }.slice }
unsafe { mem::transmute(self) }
}
/// Converts a mutable string slice to a mutable byte slice.

View File

@ -290,3 +290,43 @@ fn empty_array_is_always_default() {
let _arr = <[DoesNotImplDefault; 0]>::default();
}
#[test]
fn array_map() {
let a = [1, 2, 3];
let b = a.map(|v| v + 1);
assert_eq!(b, [2, 3, 4]);
let a = [1u8, 2, 3];
let b = a.map(|v| v as u64);
assert_eq!(b, [1, 2, 3]);
}
// See note on above test for why `should_panic` is used.
#[test]
#[should_panic(expected = "test succeeded")]
fn array_map_drop_safety() {
use core::sync::atomic::AtomicUsize;
use core::sync::atomic::Ordering;
static DROPPED: AtomicUsize = AtomicUsize::new(0);
struct DropCounter;
impl Drop for DropCounter {
fn drop(&mut self) {
DROPPED.fetch_add(1, Ordering::SeqCst);
}
}
let num_to_create = 5;
let success = std::panic::catch_unwind(|| {
let items = [0; 10];
let mut nth = 0;
items.map(|_| {
assert!(nth < num_to_create);
nth += 1;
DropCounter
});
});
assert!(success.is_err());
assert_eq!(DROPPED.load(Ordering::SeqCst), num_to_create);
panic!("test succeeded")
}

View File

@ -1,5 +1,6 @@
#![feature(alloc_layout_extra)]
#![feature(array_chunks)]
#![feature(array_map)]
#![feature(bool_to_option)]
#![feature(bound_cloned)]
#![feature(box_syntax)]

View File

@ -16,7 +16,7 @@ cfg-if = { version = "0.1.8", features = ['rustc-dep-of-std'] }
panic_unwind = { path = "../panic_unwind", optional = true }
panic_abort = { path = "../panic_abort" }
core = { path = "../core" }
libc = { version = "0.2.51", default-features = false, features = ['rustc-dep-of-std'] }
libc = { version = "0.2.74", default-features = false, features = ['rustc-dep-of-std'] }
compiler_builtins = { version = "0.1.32" }
profiler_builtins = { path = "../profiler_builtins", optional = true }
unwind = { path = "../unwind" }

View File

@ -1,3 +1,4 @@
#![deny(unsafe_op_in_unsafe_fn)]
use crate::ascii;
use crate::borrow::{Borrow, Cow};
use crate::cmp::Ordering;
@ -35,23 +36,23 @@ use crate::sys;
/// example, you can build a `CString` straight out of a [`String`] or
/// a [`&str`], since both implement that trait).
///
/// The [`new`] method will actually check that the provided `&[u8]`
/// The [`CString::new`] method will actually check that the provided `&[u8]`
/// does not have 0 bytes in the middle, and return an error if it
/// finds one.
///
/// # Extracting a raw pointer to the whole C string
///
/// `CString` implements a [`as_ptr`] method through the [`Deref`]
/// `CString` implements a [`as_ptr`][`CStr::as_ptr`] method through the [`Deref`]
/// trait. This method will give you a `*const c_char` which you can
/// feed directly to extern functions that expect a nul-terminated
/// string, like C's `strdup()`. Notice that [`as_ptr`] returns a
/// string, like C's `strdup()`. Notice that [`as_ptr`][`CStr::as_ptr`] returns a
/// read-only pointer; if the C code writes to it, that causes
/// undefined behavior.
///
/// # Extracting a slice of the whole C string
///
/// Alternatively, you can obtain a `&[`[`u8`]`]` slice from a
/// `CString` with the [`as_bytes`] method. Slices produced in this
/// `CString` with the [`CString::as_bytes`] method. Slices produced in this
/// way do *not* contain the trailing nul terminator. This is useful
/// when you will be calling an extern function that takes a `*const
/// u8` argument which is not necessarily nul-terminated, plus another
@ -60,7 +61,7 @@ use crate::sys;
/// [`len`][slice.len] method.
///
/// If you need a `&[`[`u8`]`]` slice *with* the nul terminator, you
/// can use [`as_bytes_with_nul`] instead.
/// can use [`CString::as_bytes_with_nul`] instead.
///
/// Once you have the kind of slice you need (with or without a nul
/// terminator), you can call the slice's own
@ -68,20 +69,11 @@ use crate::sys;
/// extern functions. See the documentation for that function for a
/// discussion on ensuring the lifetime of the raw pointer.
///
/// [`Into`]: ../convert/trait.Into.html
/// [`Vec`]: ../vec/struct.Vec.html
/// [`String`]: ../string/struct.String.html
/// [`&str`]: ../primitive.str.html
/// [`u8`]: ../primitive.u8.html
/// [`new`]: #method.new
/// [`as_bytes`]: #method.as_bytes
/// [`as_bytes_with_nul`]: #method.as_bytes_with_nul
/// [`as_ptr`]: #method.as_ptr
/// [`&str`]: str
/// [slice.as_ptr]: ../primitive.slice.html#method.as_ptr
/// [slice.len]: ../primitive.slice.html#method.len
/// [`Deref`]: ../ops/trait.Deref.html
/// [`CStr`]: struct.CStr.html
/// [`&CStr`]: struct.CStr.html
/// [`Deref`]: ops::Deref
/// [`&CStr`]: CStr
///
/// # Examples
///
@ -113,7 +105,6 @@ use crate::sys;
/// documentation of `CString` before use, as improper ownership management
/// of `CString` instances can lead to invalid memory accesses, memory leaks,
/// and other memory errors.
#[derive(PartialEq, PartialOrd, Eq, Ord, Hash, Clone)]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct CString {
@ -137,8 +128,8 @@ pub struct CString {
///
/// Note that this structure is **not** `repr(C)` and is not recommended to be
/// placed in the signatures of FFI functions. Instead, safe wrappers of FFI
/// functions may leverage the unsafe [`from_ptr`] constructor to provide a safe
/// interface to other consumers.
/// functions may leverage the unsafe [`CStr::from_ptr`] constructor to provide
/// a safe interface to other consumers.
///
/// # Examples
///
@ -189,11 +180,7 @@ pub struct CString {
/// println!("string: {}", my_string_safe());
/// ```
///
/// [`u8`]: ../primitive.u8.html
/// [`&str`]: ../primitive.str.html
/// [`String`]: ../string/struct.String.html
/// [`CString`]: struct.CString.html
/// [`from_ptr`]: #method.from_ptr
/// [`&str`]: str
#[derive(Hash)]
#[stable(feature = "rust1", since = "1.0.0")]
// FIXME:
@ -218,9 +205,6 @@ pub struct CStr {
/// This error is created by the [`new`][`CString::new`] method on
/// [`CString`]. See its documentation for more.
///
/// [`CString`]: struct.CString.html
/// [`CString::new`]: struct.CString.html#method.new
///
/// # Examples
///
/// ```
@ -237,12 +221,9 @@ pub struct NulError(usize, Vec<u8>);
/// The slice used to create a [`CStr`] must have one and only one nul byte,
/// positioned at the end.
///
/// This error is created by the [`from_bytes_with_nul`] method on [`CStr`].
/// This error is created by the [`CStr::from_bytes_with_nul`] method.
/// See its documentation for more.
///
/// [`CStr`]: struct.CStr.html
/// [`from_bytes_with_nul`]: struct.CStr.html#method.from_bytes_with_nul
///
/// # Examples
///
/// ```
@ -261,12 +242,9 @@ pub struct FromBytesWithNulError {
/// The vector used to create a [`CString`] must have one and only one nul byte,
/// positioned at the end.
///
/// This error is created by the [`from_vec_with_nul`] method on [`CString`].
/// This error is created by the [`CString::from_vec_with_nul`] method.
/// See its documentation for more.
///
/// [`CString`]: struct.CString.html
/// [`from_vec_with_nul`]: struct.CString.html#method.from_vec_with_nul
///
/// # Examples
///
/// ```
@ -316,8 +294,6 @@ impl FromVecWithNulError {
///
/// assert_eq!(&bytes[..], value.unwrap_err().as_bytes());
/// ```
///
/// [`CString`]: struct.CString.html
pub fn as_bytes(&self) -> &[u8] {
&self.bytes[..]
}
@ -343,8 +319,6 @@ impl FromVecWithNulError {
///
/// assert_eq!(bytes, value.unwrap_err().into_bytes());
/// ```
///
/// [`CString`]: struct.CString.html
pub fn into_bytes(self) -> Vec<u8> {
self.bytes
}
@ -352,17 +326,12 @@ impl FromVecWithNulError {
/// An error indicating invalid UTF-8 when converting a [`CString`] into a [`String`].
///
/// `CString` is just a wrapper over a buffer of bytes with a nul
/// terminator; [`into_string`][`CString::into_string`] performs UTF-8
/// validation on those bytes and may return this error.
/// `CString` is just a wrapper over a buffer of bytes with a nul terminator;
/// [`CString::into_string`] performs UTF-8 validation on those bytes and may
/// return this error.
///
/// This `struct` is created by the
/// [`into_string`][`CString::into_string`] method on [`CString`]. See
/// This `struct` is created by [`CString::into_string()`]. See
/// its documentation for more.
///
/// [`String`]: ../string/struct.String.html
/// [`CString`]: struct.CString.html
/// [`CString::into_string`]: struct.CString.html#method.into_string
#[derive(Clone, PartialEq, Eq, Debug)]
#[stable(feature = "cstring_into", since = "1.7.0")]
pub struct IntoStringError {
@ -398,8 +367,6 @@ impl CString {
/// This function will return an error if the supplied bytes contain an
/// internal 0 byte. The [`NulError`] returned will contain the bytes as well as
/// the position of the nul byte.
///
/// [`NulError`]: struct.NulError.html
#[stable(feature = "rust1", since = "1.0.0")]
pub fn new<T: Into<Vec<u8>>>(t: T) -> Result<CString, NulError> {
trait SpecIntoVec {
@ -439,11 +406,9 @@ impl CString {
/// Creates a C-compatible string by consuming a byte vector,
/// without checking for interior 0 bytes.
///
/// This method is equivalent to [`new`] except that no runtime assertion
/// is made that `v` contains no 0 bytes, and it requires an actual
/// byte vector, not anything that can be converted to one with Into.
///
/// [`new`]: #method.new
/// This method is equivalent to [`CString::new`] except that no runtime
/// assertion is made that `v` contains no 0 bytes, and it requires an
/// actual byte vector, not anything that can be converted to one with Into.
///
/// # Examples
///
@ -462,21 +427,22 @@ impl CString {
CString { inner: v.into_boxed_slice() }
}
/// Retakes ownership of a `CString` that was transferred to C via [`into_raw`].
/// Retakes ownership of a `CString` that was transferred to C via
/// [`CString::into_raw`].
///
/// Additionally, the length of the string will be recalculated from the pointer.
///
/// # Safety
///
/// This should only ever be called with a pointer that was earlier
/// obtained by calling [`into_raw`] on a `CString`. Other usage (e.g., trying to take
/// obtained by calling [`CString::into_raw`]. Other usage (e.g., trying to take
/// ownership of a string that was allocated by foreign code) is likely to lead
/// to undefined behavior or allocator corruption.
///
/// It should be noted that the length isn't just "recomputed," but that
/// the recomputed length must match the original length from the
/// [`into_raw`] call. This means the [`into_raw`]/`from_raw` methods
/// should not be used when passing the string to C functions that can
/// [`CString::into_raw`] call. This means the [`CString::into_raw`]/`from_raw`
/// methods should not be used when passing the string to C functions that can
/// modify the string's length.
///
/// > **Note:** If you need to borrow a string that was allocated by
@ -485,9 +451,6 @@ impl CString {
/// > make your own provisions for freeing it appropriately, likely
/// > with the foreign code's API to do that.
///
/// [`into_raw`]: #method.into_raw
/// [`CStr`]: struct.CStr.html
///
/// # Examples
///
/// Creates a `CString`, pass ownership to an `extern` function (via raw pointer), then retake
@ -510,26 +473,31 @@ impl CString {
/// ```
#[stable(feature = "cstr_memory", since = "1.4.0")]
pub unsafe fn from_raw(ptr: *mut c_char) -> CString {
let len = sys::strlen(ptr) + 1; // Including the NUL byte
let slice = slice::from_raw_parts_mut(ptr, len as usize);
CString { inner: Box::from_raw(slice as *mut [c_char] as *mut [u8]) }
// SAFETY: This is called with a pointer that was obtained from a call
// to `CString::into_raw` and the length has not been modified. As such,
// we know there is a NUL byte (and only one) at the end and that the
// information about the size of the allocation is correct on Rust's
// side.
unsafe {
let len = sys::strlen(ptr) + 1; // Including the NUL byte
let slice = slice::from_raw_parts_mut(ptr, len as usize);
CString { inner: Box::from_raw(slice as *mut [c_char] as *mut [u8]) }
}
}
/// Consumes the `CString` and transfers ownership of the string to a C caller.
///
/// The pointer which this function returns must be returned to Rust and reconstituted using
/// [`from_raw`] to be properly deallocated. Specifically, one
/// [`CString::from_raw`] to be properly deallocated. Specifically, one
/// should *not* use the standard C `free()` function to deallocate
/// this string.
///
/// Failure to call [`from_raw`] will lead to a memory leak.
/// Failure to call [`CString::from_raw`] will lead to a memory leak.
///
/// The C side must **not** modify the length of the string (by writing a
/// `NULL` somewhere inside the string or removing the final one) before
/// it makes it back into Rust using [`from_raw`]. See the safety section
/// in [`from_raw`].
///
/// [`from_raw`]: #method.from_raw
/// it makes it back into Rust using [`CString::from_raw`]. See the safety section
/// in [`CString::from_raw`].
///
/// # Examples
///
@ -560,8 +528,6 @@ impl CString {
///
/// On failure, ownership of the original `CString` is returned.
///
/// [`String`]: ../string/struct.String.html
///
/// # Examples
///
/// ```
@ -608,10 +574,8 @@ impl CString {
vec
}
/// Equivalent to the [`into_bytes`] function except that the returned vector
/// includes the trailing nul terminator.
///
/// [`into_bytes`]: #method.into_bytes
/// Equivalent to [`CString::into_bytes()`] except that the
/// returned vector includes the trailing nul terminator.
///
/// # Examples
///
@ -632,9 +596,7 @@ impl CString {
/// The returned slice does **not** contain the trailing nul
/// terminator, and it is guaranteed to not have any interior nul
/// bytes. If you need the nul terminator, use
/// [`as_bytes_with_nul`] instead.
///
/// [`as_bytes_with_nul`]: #method.as_bytes_with_nul
/// [`CString::as_bytes_with_nul`] instead.
///
/// # Examples
///
@ -651,10 +613,8 @@ impl CString {
&self.inner[..self.inner.len() - 1]
}
/// Equivalent to the [`as_bytes`] function except that the returned slice
/// includes the trailing nul terminator.
///
/// [`as_bytes`]: #method.as_bytes
/// Equivalent to [`CString::as_bytes()`] except that the
/// returned slice includes the trailing nul terminator.
///
/// # Examples
///
@ -673,8 +633,6 @@ impl CString {
/// Extracts a [`CStr`] slice containing the entire string.
///
/// [`CStr`]: struct.CStr.html
///
/// # Examples
///
/// ```
@ -693,8 +651,6 @@ impl CString {
/// Converts this `CString` into a boxed [`CStr`].
///
/// [`CStr`]: struct.CStr.html
///
/// # Examples
///
/// ```
@ -711,8 +667,6 @@ impl CString {
}
/// Bypass "move out of struct which implements [`Drop`] trait" restriction.
///
/// [`Drop`]: ../ops/trait.Drop.html
fn into_inner(self) -> Box<[u8]> {
// Rationale: `mem::forget(self)` invalidates the previous call to `ptr::read(&self.inner)`
// so we use `ManuallyDrop` to ensure `self` is not dropped.
@ -722,12 +676,12 @@ impl CString {
unsafe { ptr::read(&this.inner) }
}
/// Converts a `Vec` of `u8` to a `CString` without checking the invariants
/// on the given `Vec`.
/// Converts a [`Vec`]`<u8>` to a [`CString`] without checking the
/// invariants on the given [`Vec`].
///
/// # Safety
///
/// The given `Vec` **must** have one nul byte as its last element.
/// The given [`Vec`] **must** have one nul byte as its last element.
/// This means it cannot be empty nor have any other nul byte anywhere else.
///
/// # Example
@ -745,10 +699,10 @@ impl CString {
Self { inner: v.into_boxed_slice() }
}
/// Attempts to converts a `Vec` of `u8` to a `CString`.
/// Attempts to converts a [`Vec`]`<u8>` to a [`CString`].
///
/// Runtime checks are present to ensure there is only one nul byte in the
/// `Vec`, its last element.
/// [`Vec`], its last element.
///
/// # Errors
///
@ -757,8 +711,8 @@ impl CString {
///
/// # Examples
///
/// A successful conversion will produce the same result as [`new`] when
/// called without the ending nul byte.
/// A successful conversion will produce the same result as [`CString::new`]
/// when called without the ending nul byte.
///
/// ```
/// #![feature(cstring_from_vec_with_nul)]
@ -770,7 +724,7 @@ impl CString {
/// );
/// ```
///
/// A incorrectly formatted vector will produce an error.
/// A incorrectly formatted [`Vec`] will produce an error.
///
/// ```
/// #![feature(cstring_from_vec_with_nul)]
@ -780,8 +734,6 @@ impl CString {
/// // No nul byte
/// let _: FromVecWithNulError = CString::from_vec_with_nul(b"abc".to_vec()).unwrap_err();
/// ```
///
/// [`new`]: #method.new
#[unstable(feature = "cstring_from_vec_with_nul", issue = "73179")]
pub fn from_vec_with_nul(v: Vec<u8>) -> Result<Self, FromVecWithNulError> {
let nul_pos = memchr::memchr(0, &v);
@ -838,9 +790,6 @@ impl From<CString> for Vec<u8> {
/// Converts a [`CString`] into a [`Vec`]`<u8>`.
///
/// The conversion consumes the [`CString`], and removes the terminating NUL byte.
///
/// [`Vec`]: ../vec/struct.Vec.html
/// [`CString`]: ../ffi/struct.CString.html
#[inline]
fn from(s: CString) -> Vec<u8> {
s.into_bytes()
@ -913,9 +862,6 @@ impl From<Cow<'_, CStr>> for Box<CStr> {
#[stable(feature = "c_string_from_box", since = "1.18.0")]
impl From<Box<CStr>> for CString {
/// Converts a [`Box`]`<CStr>` into a [`CString`] without copying or allocating.
///
/// [`Box`]: ../boxed/struct.Box.html
/// [`CString`]: ../ffi/struct.CString.html
#[inline]
fn from(s: Box<CStr>) -> CString {
s.into_c_string()
@ -926,10 +872,6 @@ impl From<Box<CStr>> for CString {
impl From<Vec<NonZeroU8>> for CString {
/// Converts a [`Vec`]`<`[`NonZeroU8`]`>` into a [`CString`] without
/// copying nor checking for inner null bytes.
///
/// [`CString`]: ../ffi/struct.CString.html
/// [`NonZeroU8`]: ../num/struct.NonZeroU8.html
/// [`Vec`]: ../vec/struct.Vec.html
#[inline]
fn from(v: Vec<NonZeroU8>) -> CString {
unsafe {
@ -959,9 +901,6 @@ impl Clone for Box<CStr> {
#[stable(feature = "box_from_c_string", since = "1.20.0")]
impl From<CString> for Box<CStr> {
/// Converts a [`CString`] into a [`Box`]`<CStr>` without copying or allocating.
///
/// [`CString`]: ../ffi/struct.CString.html
/// [`Box`]: ../boxed/struct.Box.html
#[inline]
fn from(s: CString) -> Box<CStr> {
s.into_boxed_c_str()
@ -995,9 +934,6 @@ impl<'a> From<&'a CString> for Cow<'a, CStr> {
#[stable(feature = "shared_from_slice2", since = "1.24.0")]
impl From<CString> for Arc<CStr> {
/// Converts a [`CString`] into a [`Arc`]`<CStr>` without copying or allocating.
///
/// [`CString`]: ../ffi/struct.CString.html
/// [`Arc`]: ../sync/struct.Arc.html
#[inline]
fn from(s: CString) -> Arc<CStr> {
let arc: Arc<[u8]> = Arc::from(s.into_inner());
@ -1017,9 +953,6 @@ impl From<&CStr> for Arc<CStr> {
#[stable(feature = "shared_from_slice2", since = "1.24.0")]
impl From<CString> for Rc<CStr> {
/// Converts a [`CString`] into a [`Rc`]`<CStr>` without copying or allocating.
///
/// [`CString`]: ../ffi/struct.CString.html
/// [`Rc`]: ../rc/struct.Rc.html
#[inline]
fn from(s: CString) -> Rc<CStr> {
let rc: Rc<[u8]> = Rc::from(s.into_inner());
@ -1048,8 +981,6 @@ impl NulError {
/// Returns the position of the nul byte in the slice that caused
/// [`CString::new`] to fail.
///
/// [`CString::new`]: struct.CString.html#method.new
///
/// # Examples
///
/// ```
@ -1101,9 +1032,6 @@ impl fmt::Display for NulError {
#[stable(feature = "rust1", since = "1.0.0")]
impl From<NulError> for io::Error {
/// Converts a [`NulError`] into a [`io::Error`].
///
/// [`NulError`]: ../ffi/struct.NulError.html
/// [`io::Error`]: ../io/struct.Error.html
fn from(_: NulError) -> io::Error {
io::Error::new(io::ErrorKind::InvalidInput, "data provided contains a nul byte")
}
@ -1154,8 +1082,6 @@ impl fmt::Display for FromVecWithNulError {
impl IntoStringError {
/// Consumes this error, returning original [`CString`] which generated the
/// error.
///
/// [`CString`]: struct.CString.html
#[stable(feature = "cstring_into", since = "1.7.0")]
pub fn into_cstring(self) -> CString {
self.inner
@ -1228,9 +1154,21 @@ impl CStr {
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub unsafe fn from_ptr<'a>(ptr: *const c_char) -> &'a CStr {
let len = sys::strlen(ptr);
let ptr = ptr as *const u8;
CStr::from_bytes_with_nul_unchecked(slice::from_raw_parts(ptr, len as usize + 1))
// SAFETY: The caller has provided a pointer that points to a valid C
// string with a NUL terminator of size less than `isize::MAX`, whose
// content remain valid and doesn't change for the lifetime of the
// returned `CStr`.
//
// Thus computing the length is fine (a NUL byte exists), the call to
// from_raw_parts is safe because we know the length is at most `isize::MAX`, meaning
// the call to `from_bytes_with_nul_unchecked` is correct.
//
// The cast from c_char to u8 is ok because a c_char is always one byte.
unsafe {
let len = sys::strlen(ptr);
let ptr = ptr as *const u8;
CStr::from_bytes_with_nul_unchecked(slice::from_raw_parts(ptr, len as usize + 1))
}
}
/// Creates a C string wrapper from a byte slice.
@ -1299,7 +1237,12 @@ impl CStr {
#[stable(feature = "cstr_from_bytes", since = "1.10.0")]
#[rustc_const_unstable(feature = "const_cstr_unchecked", issue = "none")]
pub const unsafe fn from_bytes_with_nul_unchecked(bytes: &[u8]) -> &CStr {
&*(bytes as *const [u8] as *const CStr)
// SAFETY: Casting to CStr is safe because its internal representation
// is a [u8] too (safe only inside std).
// Dereferencing the obtained pointer is safe because it comes from a
// reference. Making a reference is then safe because its lifetime
// is bound by the lifetime of the given `bytes`.
unsafe { &*(bytes as *const [u8] as *const CStr) }
}
/// Returns the inner pointer to this C string.
@ -1330,7 +1273,8 @@ impl CStr {
///
/// This happens because the pointer returned by `as_ptr` does not carry any
/// lifetime information and the [`CString`] is deallocated immediately after
/// the `CString::new("Hello").expect("CString::new failed").as_ptr()` expression is evaluated.
/// the `CString::new("Hello").expect("CString::new failed").as_ptr()`
/// expression is evaluated.
/// To fix the problem, bind the `CString` to a local variable:
///
/// ```no_run
@ -1345,10 +1289,8 @@ impl CStr {
/// }
/// ```
///
/// This way, the lifetime of the `CString` in `hello` encompasses
/// This way, the lifetime of the [`CString`] in `hello` encompasses
/// the lifetime of `ptr` and the `unsafe` block.
///
/// [`CString`]: struct.CString.html
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_stable(feature = "const_str_as_ptr", since = "1.32.0")]
@ -1382,15 +1324,13 @@ impl CStr {
/// Converts this C string to a byte slice containing the trailing 0 byte.
///
/// This function is the equivalent of [`to_bytes`] except that it will retain
/// the trailing nul terminator instead of chopping it off.
/// This function is the equivalent of [`CStr::to_bytes`] except that it
/// will retain the trailing nul terminator instead of chopping it off.
///
/// > **Note**: This method is currently implemented as a 0-cost cast, but
/// > it is planned to alter its definition in the future to perform the
/// > length calculation whenever this method is called.
///
/// [`to_bytes`]: #method.to_bytes
///
/// # Examples
///
/// ```
@ -1411,7 +1351,7 @@ impl CStr {
/// function will return the corresponding [`&str`] slice. Otherwise,
/// it will return an error with details of where UTF-8 validation failed.
///
/// [`&str`]: ../primitive.str.html
/// [`&str`]: str
///
/// # Examples
///
@ -1439,12 +1379,9 @@ impl CStr {
/// [`U+FFFD REPLACEMENT CHARACTER`][U+FFFD] and return a
/// [`Cow`]`::`[`Owned`]`(`[`String`]`)` with the result.
///
/// [`Cow`]: ../borrow/enum.Cow.html
/// [`Borrowed`]: ../borrow/enum.Cow.html#variant.Borrowed
/// [`Owned`]: ../borrow/enum.Cow.html#variant.Owned
/// [`str`]: ../primitive.str.html
/// [`String`]: ../string/struct.String.html
/// [U+FFFD]: ../char/constant.REPLACEMENT_CHARACTER.html
/// [`Borrowed`]: Cow::Borrowed
/// [`Owned`]: Cow::Owned
/// [U+FFFD]: crate::char::REPLACEMENT_CHARACTER
///
/// # Examples
///
@ -1479,9 +1416,6 @@ impl CStr {
/// Converts a [`Box`]`<CStr>` into a [`CString`] without copying or allocating.
///
/// [`Box`]: ../boxed/struct.Box.html
/// [`CString`]: struct.CString.html
///
/// # Examples
///
/// ```

View File

@ -88,7 +88,7 @@
//! [`env::var_os()`] is used to query environment variables; it
//! returns an [`Option`]`<`[`OsString`]`>`. If the environment variable
//! exists you will get a [`Some`]`(os_string)`, which you can *then* try to
//! convert to a Rust string. This yields a [`Result<>`], so that
//! convert to a Rust string. This yields a [`Result`], so that
//! your code can detect errors in case the environment variable did
//! not in fact contain valid Unicode data.
//!
@ -124,34 +124,22 @@
//! method is an [`OsString`] which can be round-tripped to a Windows
//! string losslessly.
//!
//! [`String`]: ../string/struct.String.html
//! [`str`]: ../primitive.str.html
//! [`char`]: ../primitive.char.html
//! [`u8`]: ../primitive.u8.html
//! [`u16`]: ../primitive.u16.html
//! [Unicode scalar value]: http://www.unicode.org/glossary/#unicode_scalar_value
//! [Unicode code point]: http://www.unicode.org/glossary/#code_point
//! [`CString`]: struct.CString.html
//! [`CStr`]: struct.CStr.html
//! [`OsString`]: struct.OsString.html
//! [`OsStr`]: struct.OsStr.html
//! [`env::set_var()`]: ../env/fn.set_var.html
//! [`env::var_os()`]: ../env/fn.var_os.html
//! [`Result<>`]: ../result/enum.Result.html
//! [unix.OsStringExt]: ../os/unix/ffi/trait.OsStringExt.html
//! [`from_vec`]: ../os/unix/ffi/trait.OsStringExt.html#tymethod.from_vec
//! [`into_vec`]: ../os/unix/ffi/trait.OsStringExt.html#tymethod.into_vec
//! [unix.OsStrExt]: ../os/unix/ffi/trait.OsStrExt.html
//! [`from_bytes`]: ../os/unix/ffi/trait.OsStrExt.html#tymethod.from_bytes
//! [`as_bytes`]: ../os/unix/ffi/trait.OsStrExt.html#tymethod.as_bytes
//! [`OsStrExt`]: ../os/unix/ffi/trait.OsStrExt.html
//! [windows.OsStrExt]: ../os/windows/ffi/trait.OsStrExt.html
//! [`encode_wide`]: ../os/windows/ffi/trait.OsStrExt.html#tymethod.encode_wide
//! [`collect`]: ../iter/trait.Iterator.html#method.collect
//! [windows.OsStringExt]: ../os/windows/ffi/trait.OsStringExt.html
//! [`from_wide`]: ../os/windows/ffi/trait.OsStringExt.html#tymethod.from_wide
//! [`Option`]: ../option/enum.Option.html
//! [`Some`]: ../option/enum.Option.html#variant.Some
//! [`env::set_var()`]: crate::env::set_var
//! [`env::var_os()`]: crate::env::var_os
//! [unix.OsStringExt]: crate::os::unix::ffi::OsStringExt
//! [`from_vec`]: crate::os::unix::ffi::OsStringExt::from_vec
//! [`into_vec`]: crate::os::unix::ffi::OsStringExt::into_vec
//! [unix.OsStrExt]: crate::os::unix::ffi::OsStrExt
//! [`from_bytes`]: crate::os::unix::ffi::OsStrExt::from_bytes
//! [`as_bytes`]: crate::os::unix::ffi::OsStrExt::as_bytes
//! [`OsStrExt`]: crate::os::unix::ffi::OsStrExt
//! [windows.OsStrExt]: crate::os::windows::ffi::OsStrExt
//! [`encode_wide`]: crate::os::windows::ffi::OsStrExt::encode_wide
//! [`collect`]: crate::iter::Iterator::collect
//! [windows.OsStringExt]: crate::os::windows::ffi::OsStringExt
//! [`from_wide`]: crate::os::windows::ffi::OsStringExt::from_wide
#![stable(feature = "rust1", since = "1.0.0")]

View File

@ -47,14 +47,14 @@ use crate::sys_common::{AsInner, FromInner, IntoInner};
/// create an `OsString` from a normal Rust string.
///
/// **From slices:** Just like you can start with an empty Rust
/// [`String`] and then [`push_str`][String.push_str] `&str`
/// [`String`] and then [`String::push_str`] `&str`
/// sub-string slices into it, you can create an empty `OsString` with
/// the [`new`] method and then push string slices into it with the
/// [`push`] method.
/// the [`OsString::new`] method and then push string slices into it with the
/// [`OsString::push`] method.
///
/// # Extracting a borrowed reference to the whole OS string
///
/// You can use the [`as_os_str`] method to get an `&`[`OsStr`] from
/// You can use the [`OsString::as_os_str`] method to get an `&`[`OsStr`] from
/// an `OsString`; this is effectively a borrowed reference to the
/// whole string.
///
@ -63,18 +63,9 @@ use crate::sys_common::{AsInner, FromInner, IntoInner};
/// See the [module's toplevel documentation about conversions][conversions] for a discussion on
/// the traits which `OsString` implements for [conversions] from/to native representations.
///
/// [`OsStr`]: struct.OsStr.html
/// [`&OsStr`]: struct.OsStr.html
/// [`CStr`]: struct.CStr.html
/// [`From`]: ../convert/trait.From.html
/// [`String`]: ../string/struct.String.html
/// [`&str`]: ../primitive.str.html
/// [`u8`]: ../primitive.u8.html
/// [`u16`]: ../primitive.u16.html
/// [String.push_str]: ../string/struct.String.html#method.push_str
/// [`new`]: #method.new
/// [`push`]: #method.push
/// [`as_os_str`]: #method.as_os_str
/// [`&OsStr`]: OsStr
/// [`&str`]: str
/// [`CStr`]: crate::ffi::CStr
/// [conversions]: index.html#conversions
#[derive(Clone)]
#[stable(feature = "rust1", since = "1.0.0")]
@ -93,9 +84,7 @@ pub struct OsString {
/// See the [module's toplevel documentation about conversions][conversions] for a discussion on
/// the traits which `OsStr` implements for [conversions] from/to native representations.
///
/// [`OsString`]: struct.OsString.html
/// [`&str`]: ../primitive.str.html
/// [`String`]: ../string/struct.String.html
/// [`&str`]: str
/// [conversions]: index.html#conversions
#[stable(feature = "rust1", since = "1.0.0")]
// FIXME:
@ -125,8 +114,6 @@ impl OsString {
/// Converts to an [`OsStr`] slice.
///
/// [`OsStr`]: struct.OsStr.html
///
/// # Examples
///
/// ```
@ -145,8 +132,6 @@ impl OsString {
///
/// On failure, ownership of the original `OsString` is returned.
///
/// [`String`]: ../../std/string/struct.String.html
///
/// # Examples
///
/// ```
@ -163,7 +148,7 @@ impl OsString {
/// Extends the string with the given [`&OsStr`] slice.
///
/// [`&OsStr`]: struct.OsStr.html
/// [`&OsStr`]: OsStr
///
/// # Examples
///
@ -333,8 +318,6 @@ impl OsString {
/// Converts this `OsString` into a boxed [`OsStr`].
///
/// [`OsStr`]: struct.OsStr.html
///
/// # Examples
///
/// ```
@ -356,8 +339,6 @@ impl From<String> for OsString {
/// Converts a [`String`] into a [`OsString`].
///
/// The conversion copies the data, and includes an allocation on the heap.
///
/// [`OsString`]: ../../std/ffi/struct.OsString.html
fn from(s: String) -> OsString {
OsString { inner: Buf::from_string(s) }
}
@ -544,7 +525,7 @@ impl OsStr {
///
/// This conversion may entail doing a check for UTF-8 validity.
///
/// [`&str`]: ../../std/primitive.str.html
/// [`&str`]: str
///
/// # Examples
///
@ -564,9 +545,7 @@ impl OsStr {
/// Any non-Unicode sequences are replaced with
/// [`U+FFFD REPLACEMENT CHARACTER`][U+FFFD].
///
/// [`Cow`]: ../../std/borrow/enum.Cow.html
/// [`str`]: ../../std/primitive.str.html
/// [U+FFFD]: ../../std/char/constant.REPLACEMENT_CHARACTER.html
/// [U+FFFD]: crate::char::REPLACEMENT_CHARACTER
///
/// # Examples
///
@ -613,8 +592,6 @@ impl OsStr {
/// Copies the slice into an owned [`OsString`].
///
/// [`OsString`]: struct.OsString.html
///
/// # Examples
///
/// ```
@ -662,9 +639,6 @@ impl OsStr {
/// This number is simply useful for passing to other methods, like
/// [`OsString::with_capacity`] to avoid reallocations.
///
/// [`OsString`]: struct.OsString.html
/// [`OsString::with_capacity`]: struct.OsString.html#method.with_capacity
///
/// # Examples
///
/// ```
@ -682,9 +656,6 @@ impl OsStr {
}
/// Converts a [`Box`]`<OsStr>` into an [`OsString`] without copying or allocating.
///
/// [`Box`]: ../boxed/struct.Box.html
/// [`OsString`]: struct.OsString.html
#[stable(feature = "into_boxed_os_str", since = "1.20.0")]
pub fn into_os_string(self: Box<OsStr>) -> OsString {
let boxed = unsafe { Box::from_raw(Box::into_raw(self) as *mut Slice) };
@ -706,9 +677,7 @@ impl OsStr {
/// but non-ASCII letters are unchanged.
///
/// To return a new lowercased value without modifying the existing one, use
/// [`to_ascii_lowercase`].
///
/// [`to_ascii_lowercase`]: #method.to_ascii_lowercase
/// [`OsStr::to_ascii_lowercase`].
///
/// # Examples
///
@ -733,9 +702,7 @@ impl OsStr {
/// but non-ASCII letters are unchanged.
///
/// To return a new uppercased value without modifying the existing one, use
/// [`to_ascii_uppercase`].
///
/// [`to_ascii_uppercase`]: #method.to_ascii_uppercase
/// [`OsStr::to_ascii_uppercase`].
///
/// # Examples
///
@ -760,9 +727,7 @@ impl OsStr {
/// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z',
/// but non-ASCII letters are unchanged.
///
/// To lowercase the value in-place, use [`make_ascii_lowercase`].
///
/// [`make_ascii_lowercase`]: #method.make_ascii_lowercase
/// To lowercase the value in-place, use [`OsStr::make_ascii_lowercase`].
///
/// # Examples
///
@ -784,9 +749,7 @@ impl OsStr {
/// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z',
/// but non-ASCII letters are unchanged.
///
/// To uppercase the value in-place, use [`make_ascii_uppercase`].
///
/// [`make_ascii_uppercase`]: #method.make_ascii_uppercase
/// To uppercase the value in-place, use [`OsStr::make_ascii_uppercase`].
///
/// # Examples
///
@ -865,9 +828,6 @@ impl From<Cow<'_, OsStr>> for Box<OsStr> {
impl From<Box<OsStr>> for OsString {
/// Converts a [`Box`]`<`[`OsStr`]`>` into a `OsString` without copying or
/// allocating.
///
/// [`Box`]: ../boxed/struct.Box.html
/// [`OsStr`]: ../ffi/struct.OsStr.html
fn from(boxed: Box<OsStr>) -> OsString {
boxed.into_os_string()
}
@ -876,9 +836,6 @@ impl From<Box<OsStr>> for OsString {
#[stable(feature = "box_from_os_string", since = "1.20.0")]
impl From<OsString> for Box<OsStr> {
/// Converts a [`OsString`] into a [`Box`]`<OsStr>` without copying or allocating.
///
/// [`Box`]: ../boxed/struct.Box.html
/// [`OsString`]: ../ffi/struct.OsString.html
fn from(s: OsString) -> Box<OsStr> {
s.into_boxed_os_str()
}
@ -895,9 +852,6 @@ impl Clone for Box<OsStr> {
#[stable(feature = "shared_from_slice2", since = "1.24.0")]
impl From<OsString> for Arc<OsStr> {
/// Converts a [`OsString`] into a [`Arc`]`<OsStr>` without copying or allocating.
///
/// [`Arc`]: ../sync/struct.Arc.html
/// [`OsString`]: ../ffi/struct.OsString.html
#[inline]
fn from(s: OsString) -> Arc<OsStr> {
let arc = s.inner.into_arc();
@ -917,9 +871,6 @@ impl From<&OsStr> for Arc<OsStr> {
#[stable(feature = "shared_from_slice2", since = "1.24.0")]
impl From<OsString> for Rc<OsStr> {
/// Converts a [`OsString`] into a [`Rc`]`<OsStr>` without copying or allocating.
///
/// [`Rc`]: ../rc/struct.Rc.html
/// [`OsString`]: ../ffi/struct.OsString.html
#[inline]
fn from(s: OsString) -> Rc<OsStr> {
let rc = s.inner.into_rc();

View File

@ -1212,7 +1212,7 @@ impl Initializer {
///
/// [`write`]: Self::write
/// [`flush`]: Self::flush
/// [`std::io`]: index.html
/// [`std::io`]: self
///
/// # Examples
///
@ -1590,8 +1590,6 @@ pub trait Seek {
/// # Errors
///
/// Seeking to a negative offset is considered an error.
///
/// [`SeekFrom::Start`]: enum.SeekFrom.html#variant.Start
#[stable(feature = "rust1", since = "1.0.0")]
fn seek(&mut self, pos: SeekFrom) -> Result<u64>;
@ -1678,8 +1676,6 @@ pub trait Seek {
/// Enumeration of possible methods to seek within an I/O object.
///
/// It is used by the [`Seek`] trait.
///
/// [`Seek`]: trait.Seek.html
#[derive(Copy, PartialEq, Eq, Clone, Debug)]
#[stable(feature = "rust1", since = "1.0.0")]
pub enum SeekFrom {
@ -1759,11 +1755,9 @@ fn read_until<R: BufRead + ?Sized>(r: &mut R, delim: u8, buf: &mut Vec<u8>) -> R
/// For example, [`File`] implements [`Read`], but not `BufRead`.
/// [`BufReader`] to the rescue!
///
/// [`BufReader`]: struct.BufReader.html
/// [`File`]: crate::fs::File
/// [`read_line`]: Self::read_line
/// [`lines`]: Self::lines
/// [`Read`]: trait.Read.html
///
/// ```no_run
/// use std::io::{self, BufReader};
@ -1869,7 +1863,6 @@ pub trait BufRead: Read {
/// present in `buf` and its length will have been adjusted appropriately.
///
/// [`fill_buf`]: Self::fill_buf
/// [`ErrorKind::Interrupted`]: enum.ErrorKind.html#variant.Interrupted
///
/// # Examples
///
@ -1877,8 +1870,6 @@ pub trait BufRead: Read {
/// this example, we use [`Cursor`] to read all the bytes in a byte slice
/// in hyphen delimited segments:
///
/// [`Cursor`]: struct.Cursor.html
///
/// ```
/// use std::io::{self, BufRead};
///
@ -1940,8 +1931,6 @@ pub trait BufRead: Read {
/// [`std::io::Cursor`][`Cursor`] is a type that implements `BufRead`. In
/// this example, we use [`Cursor`] to read all the lines in a byte slice:
///
/// [`Cursor`]: struct.Cursor.html
///
/// ```
/// use std::io::{self, BufRead};
///
@ -1996,8 +1985,6 @@ pub trait BufRead: Read {
/// this example, we use [`Cursor`] to iterate over all hyphen delimited
/// segments in a byte slice
///
/// [`Cursor`]: struct.Cursor.html
///
/// ```
/// use std::io::{self, BufRead};
///
@ -2046,8 +2033,6 @@ pub trait BufRead: Read {
/// # Errors
///
/// Each line of the iterator has the same error semantics as [`BufRead::read_line`].
///
/// [`BufRead::read_line`]: trait.BufRead.html#method.read_line
#[stable(feature = "rust1", since = "1.0.0")]
fn lines(self) -> Lines<Self>
where
@ -2062,7 +2047,7 @@ pub trait BufRead: Read {
/// This struct is generally created by calling [`chain`] on a reader.
/// Please see the documentation of [`chain`] for more details.
///
/// [`chain`]: trait.Read.html#method.chain
/// [`chain`]: Read::chain
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Chain<T, U> {
first: T,
@ -2204,7 +2189,7 @@ impl<T: BufRead, U: BufRead> BufRead for Chain<T, U> {
/// This struct is generally created by calling [`take`] on a reader.
/// Please see the documentation of [`take`] for more details.
///
/// [`take`]: trait.Read.html#method.take
/// [`take`]: Read::take
#[stable(feature = "rust1", since = "1.0.0")]
#[derive(Debug)]
pub struct Take<T> {
@ -2403,7 +2388,7 @@ impl<T: BufRead> BufRead for Take<T> {
/// This struct is generally created by calling [`bytes`] on a reader.
/// Please see the documentation of [`bytes`] for more details.
///
/// [`bytes`]: trait.Read.html#method.bytes
/// [`bytes`]: Read::bytes
#[stable(feature = "rust1", since = "1.0.0")]
#[derive(Debug)]
pub struct Bytes<R> {
@ -2433,7 +2418,7 @@ impl<R: Read> Iterator for Bytes<R> {
/// This struct is generally created by calling [`split`] on a `BufRead`.
/// Please see the documentation of [`split`] for more details.
///
/// [`split`]: trait.BufRead.html#method.split
/// [`split`]: BufRead::split
#[stable(feature = "rust1", since = "1.0.0")]
#[derive(Debug)]
pub struct Split<B> {
@ -2465,7 +2450,7 @@ impl<B: BufRead> Iterator for Split<B> {
/// This struct is generally created by calling [`lines`] on a `BufRead`.
/// Please see the documentation of [`lines`] for more details.
///
/// [`lines`]: trait.BufRead.html#method.lines
/// [`lines`]: BufRead::lines
#[stable(feature = "rust1", since = "1.0.0")]
#[derive(Debug)]
pub struct Lines<B> {

View File

@ -1813,12 +1813,190 @@ mod type_keyword {}
#[doc(keyword = "unsafe")]
//
/// Code or interfaces whose [memory safety] cannot be verified by the type system.
/// Code or interfaces whose [memory safety] cannot be verified by the type
/// system.
///
/// The documentation for this keyword is [not yet complete]. Pull requests welcome!
/// The `unsafe` keyword has two uses: to declare the existence of contracts the
/// compiler can't check (`unsafe fn` and `unsafe trait`), and to declare that a
/// programmer has checked that these contracts have been upheld (`unsafe {}`
/// and `unsafe impl`, but also `unsafe fn` -- see below). They are not mutually
/// exclusive, as can be seen in `unsafe fn`.
///
/// # Unsafe abilities
///
/// **No matter what, Safe Rust can't cause Undefined Behavior**. This is
/// referred to as [soundness]: a well-typed program actually has the desired
/// properties. The [Nomicon][nomicon-soundness] has a more detailed explanation
/// on the subject.
///
/// To ensure soundness, Safe Rust is restricted enough that it can be
/// automatically checked. Sometimes, however, it is necessary to write code
/// that is correct for reasons which are too clever for the compiler to
/// understand. In those cases, you need to use Unsafe Rust.
///
/// Here are the abilities Unsafe Rust has in addition to Safe Rust:
///
/// - Dereference [raw pointers]
/// - Implement `unsafe` [`trait`]s
/// - Call `unsafe` functions
/// - Mutate [`static`]s (including [`extern`]al ones)
/// - Access fields of [`union`]s
///
/// However, this extra power comes with extra responsibilities: it is now up to
/// you to ensure soundness. The `unsafe` keyword helps by clearly marking the
/// pieces of code that need to worry about this.
///
/// ## The different meanings of `unsafe`
///
/// Not all uses of `unsafe` are equivalent: some are here to mark the existence
/// of a contract the programmer must check, others are to say "I have checked
/// the contract, go ahead and do this". The following
/// [discussion on Rust Internals] has more in-depth explanations about this but
/// here is a summary of the main points:
///
/// - `unsafe fn`: calling this function means abiding by a contract the
/// compiler cannot enforce.
/// - `unsafe trait`: implementing the [`trait`] means abiding by a
/// contract the compiler cannot enforce.
/// - `unsafe {}`: the contract necessary to call the operations inside the
/// block has been checked by the programmer and is guaranteed to be respected.
/// - `unsafe impl`: the contract necessary to implement the trait has been
/// checked by the programmer and is guaranteed to be respected.
///
/// `unsafe fn` also acts like an `unsafe {}` block
/// around the code inside the function. This means it is not just a signal to
/// the caller, but also promises that the preconditions for the operations
/// inside the function are upheld. Mixing these two meanings can be confusing
/// and [proposal]s exist to use `unsafe {}` blocks inside such functions when
/// making `unsafe` operations.
///
/// See the [Rustnomicon] and the [Reference] for more informations.
///
/// # Examples
///
/// ## Marking elements as `unsafe`
///
/// `unsafe` can be used on functions. Note that functions and statics declared
/// in [`extern`] blocks are implicitly marked as `unsafe` (but not functions
/// declared as `extern "something" fn ...`). Mutable statics are always unsafe,
/// wherever they are declared. Methods can also be declared as `unsafe`:
///
/// ```rust
/// # #![allow(dead_code)]
/// static mut FOO: &str = "hello";
///
/// unsafe fn unsafe_fn() {}
///
/// extern "C" {
/// fn unsafe_extern_fn();
/// static BAR: *mut u32;
/// }
///
/// trait SafeTraitWithUnsafeMethod {
/// unsafe fn unsafe_method(&self);
/// }
///
/// struct S;
///
/// impl S {
/// unsafe fn unsafe_method_on_struct() {}
/// }
/// ```
///
/// Traits can also be declared as `unsafe`:
///
/// ```rust
/// unsafe trait UnsafeTrait {}
/// ```
///
/// Since `unsafe fn` and `unsafe trait` indicate that there is a safety
/// contract that the compiler cannot enforce, documenting it is important. The
/// standard library has many examples of this, like the following which is an
/// extract from [`Vec::set_len`]. The `# Safety` section explains the contract
/// that must be fulfilled to safely call the function.
///
/// ```rust,ignore (stub-to-show-doc-example)
/// /// Forces the length of the vector to `new_len`.
/// ///
/// /// This is a low-level operation that maintains none of the normal
/// /// invariants of the type. Normally changing the length of a vector
/// /// is done using one of the safe operations instead, such as
/// /// `truncate`, `resize`, `extend`, or `clear`.
/// ///
/// /// # Safety
/// ///
/// /// - `new_len` must be less than or equal to `capacity()`.
/// /// - The elements at `old_len..new_len` must be initialized.
/// pub unsafe fn set_len(&mut self, new_len: usize)
/// ```
///
/// ## Using `unsafe {}` blocks and `impl`s
///
/// Performing `unsafe` operations requires an `unsafe {}` block:
///
/// ```rust
/// # #![allow(dead_code)]
/// /// Dereference the given pointer.
/// ///
/// /// # Safety
/// ///
/// /// `ptr` must be aligned and must not be dangling.
/// unsafe fn deref_unchecked(ptr: *const i32) -> i32 {
/// *ptr
/// }
///
/// let a = 3;
/// let b = &a as *const _;
/// // SAFETY: `a` has not been dropped and references are always aligned,
/// // so `b` is a valid address.
/// unsafe { assert_eq!(*b, deref_unchecked(b)); };
/// ```
///
/// Traits marked as `unsafe` must be [`impl`]emented using `unsafe impl`. This
/// makes a guarantee to other `unsafe` code that the implementation satisfies
/// the trait's safety contract. The [Send] and [Sync] traits are examples of
/// this behaviour in the standard library.
///
/// ```rust
/// /// Implementors of this trait must guarantee an element is always
/// /// accessible with index 3.
/// unsafe trait ThreeIndexable<T> {
/// /// Returns a reference to the element with index 3 in `&self`.
/// fn three(&self) -> &T;
/// }
///
/// // The implementation of `ThreeIndexable` for `[T; 4]` is `unsafe`
/// // because the implementor must abide by a contract the compiler cannot
/// // check but as a programmer we know there will always be a valid element
/// // at index 3 to access.
/// unsafe impl<T> ThreeIndexable<T> for [T; 4] {
/// fn three(&self) -> &T {
/// // SAFETY: implementing the trait means there always is an element
/// // with index 3 accessible.
/// unsafe { self.get_unchecked(3) }
/// }
/// }
///
/// let a = [1, 2, 4, 8];
/// assert_eq!(a.three(), &8);
/// ```
///
/// [`extern`]: keyword.extern.html
/// [`trait`]: keyword.trait.html
/// [`static`]: keyword.static.html
/// [`union`]: keyword.union.html
/// [`impl`]: keyword.impl.html
/// [Send]: marker/trait.Send.html
/// [Sync]: marker/trait.Sync.html
/// [`Vec::set_len`]: vec/struct.Vec.html#method.set_len
/// [raw pointers]: ../reference/types/pointer.html
/// [memory safety]: ../book/ch19-01-unsafe-rust.html
/// [not yet complete]: https://github.com/rust-lang/rust/issues/34601
/// [Rustnomicon]: ../nomicon/index.html
/// [nomicon-soundness]: ../nomicon/safe-unsafe-meaning.html
/// [soundness]: https://rust-lang.github.io/unsafe-code-guidelines/glossary.html#soundness-of-code--of-a-library
/// [Reference]: ../reference/unsafety.html
/// [proposal]: https://github.com/rust-lang/rfcs/pull/2585
/// [discussion on Rust Internals]: https://internals.rust-lang.org/t/what-does-unsafe-mean/6696
mod unsafe_keyword {}
#[doc(keyword = "use")]

View File

@ -22,7 +22,7 @@
//! * [`std::*` modules](#modules)
//! * [Primitive types](#primitives)
//! * [Standard macros](#macros)
//! * [The Rust Prelude](prelude/index.html)
//! * [The Rust Prelude]
//!
//! If this is your first time, the documentation for the standard library is
//! written to be casually perused. Clicking on interesting things should
@ -63,8 +63,8 @@
//! So for example there is a [page for the primitive type
//! `i32`](primitive.i32.html) that lists all the methods that can be called on
//! 32-bit integers (very useful), and there is a [page for the module
//! `std::i32`](i32/index.html) that documents the constant values [`MIN`] and
//! [`MAX`](i32/constant.MAX.html) (rarely useful).
//! `std::i32`] that documents the constant values [`MIN`] and [`MAX`] (rarely
//! useful).
//!
//! Note the documentation for the primitives [`str`] and [`[T]`][slice] (also
//! called 'slice'). Many method calls on [`String`] and [`Vec<T>`] are actually
@ -152,48 +152,35 @@
//! contains further primitive shared memory types, including [`atomic`] and
//! [`mpsc`], which contains the channel types for message passing.
//!
//! [I/O]: io/index.html
//! [`MIN`]: i32/constant.MIN.html
//! [TCP]: net/struct.TcpStream.html
//! [The Rust Prelude]: prelude/index.html
//! [UDP]: net/struct.UdpSocket.html
//! [`Arc`]: sync/struct.Arc.html
//! [owned slice]: boxed/index.html
//! [`Cell`]: cell/struct.Cell.html
//! [`FromStr`]: str/trait.FromStr.html
//! [`HashMap<K, V>`]: collections/struct.HashMap.html
//! [`Iterator`]: iter/trait.Iterator.html
//! [`Mutex`]: sync/struct.Mutex.html
//! [`Option<T>`]: option/enum.Option.html
//! [`Rc`]: rc/struct.Rc.html
//! [`RefCell`]: cell/struct.RefCell.html
//! [`Result<T, E>`]: result/enum.Result.html
//! [`String`]: string/struct.String.html
//! [`Vec<T>`]: vec/struct.Vec.html
//! [array]: primitive.array.html
//! [slice]: primitive.slice.html
//! [`atomic`]: sync/atomic/index.html
//! [`collections`]: collections/index.html
//! [I/O]: io
//! [`MIN`]: i32::MIN
//! [`MAX`]: i32::MAX
//! [page for the module `std::i32`]: crate::i32
//! [TCP]: net::TcpStream
//! [The Rust Prelude]: prelude
//! [UDP]: net::UdpSocket
//! [`Arc`]: sync::Arc
//! [owned slice]: boxed
//! [`Cell`]: cell::Cell
//! [`FromStr`]: str::FromStr
//! [`HashMap<K, V>`]: collections::HashMap
//! [`Mutex`]: sync::Mutex
//! [`Option<T>`]: option::Option
//! [`Rc`]: rc::Rc
//! [`RefCell`]: cell::RefCell
//! [`Result<T, E>`]: result::Result
//! [`Vec<T>`]: vec::Vec
//! [`atomic`]: sync::atomic
//! [`for`]: ../book/ch03-05-control-flow.html#looping-through-a-collection-with-for
//! [`format!`]: macro.format.html
//! [`fs`]: fs/index.html
//! [`io`]: io/index.html
//! [`iter`]: iter/index.html
//! [`mpsc`]: sync/mpsc/index.html
//! [`net`]: net/index.html
//! [`option`]: option/index.html
//! [`result`]: result/index.html
//! [`std::cmp`]: cmp/index.html
//! [`std::slice`]: slice/index.html
//! [`str`]: primitive.str.html
//! [`sync`]: sync/index.html
//! [`thread`]: thread/index.html
//! [`mpsc`]: sync::mpsc
//! [`std::cmp`]: cmp
//! [`std::slice`]: slice
//! [`use std::env`]: env/index.html
//! [`use`]: ../book/ch07-02-defining-modules-to-control-scope-and-privacy.html
//! [crates.io]: https://crates.io
//! [deref-coercions]: ../book/ch15-02-deref.html#implicit-deref-coercions-with-functions-and-methods
//! [files]: fs/struct.File.html
//! [multithreading]: thread/index.html
//! [files]: fs::File
//! [multithreading]: thread
//! [other]: #what-is-in-the-standard-library-documentation
//! [primitive types]: ../book/ch03-02-data-types.html
//! [rust-discord]: https://discord.gg/rust-lang
@ -249,6 +236,7 @@
#![feature(clamp)]
#![feature(concat_idents)]
#![feature(const_cstr_unchecked)]
#![feature(const_fn_transmute)]
#![feature(const_raw_ptr_deref)]
#![feature(container_error_extra)]
#![feature(core_intrinsics)]

View File

@ -37,7 +37,7 @@ use crate::vec;
/// assert_eq!(socket.port(), 8080);
/// assert_eq!(socket.is_ipv4(), true);
/// ```
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, PartialOrd, Ord)]
#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
#[stable(feature = "rust1", since = "1.0.0")]
pub enum SocketAddr {
/// An IPv4 socket address.
@ -597,6 +597,13 @@ impl fmt::Display for SocketAddr {
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl fmt::Debug for SocketAddr {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(self, fmt)
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl fmt::Display for SocketAddrV4 {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {

View File

@ -10,6 +10,7 @@ use crate::cmp::Ordering;
use crate::fmt::{self, Write as FmtWrite};
use crate::hash;
use crate::io::Write as IoWrite;
use crate::mem::transmute;
use crate::sys::net::netc as c;
use crate::sys_common::{AsInner, FromInner};
@ -39,7 +40,7 @@ use crate::sys_common::{AsInner, FromInner};
/// assert_eq!(localhost_v4.is_ipv4(), true);
/// ```
#[stable(feature = "ip_addr", since = "1.7.0")]
#[derive(Copy, Clone, Eq, PartialEq, Debug, Hash, PartialOrd, Ord)]
#[derive(Copy, Clone, Eq, PartialEq, Hash, PartialOrd, Ord)]
pub enum IpAddr {
/// An IPv4 address.
#[stable(feature = "ip_addr", since = "1.7.0")]
@ -766,10 +767,8 @@ impl Ipv4Addr {
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn to_ipv6_compatible(&self) -> Ipv6Addr {
let octets = self.octets();
Ipv6Addr::from([
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, octets[0], octets[1], octets[2], octets[3],
])
let [a, b, c, d] = self.octets();
Ipv6Addr::from([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, a, b, c, d])
}
/// Converts this address to an IPv4-mapped [IPv6 address].
@ -788,10 +787,8 @@ impl Ipv4Addr {
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn to_ipv6_mapped(&self) -> Ipv6Addr {
let octets = self.octets();
Ipv6Addr::from([
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, octets[0], octets[1], octets[2], octets[3],
])
let [a, b, c, d] = self.octets();
Ipv6Addr::from([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, a, b, c, d])
}
}
@ -805,6 +802,13 @@ impl fmt::Display for IpAddr {
}
}
#[stable(feature = "ip_addr", since = "1.7.0")]
impl fmt::Debug for IpAddr {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(self, fmt)
}
}
#[stable(feature = "ip_from_ip", since = "1.16.0")]
impl From<Ipv4Addr> for IpAddr {
/// Copies this address to a new `IpAddr::V4`.
@ -1045,27 +1049,23 @@ impl Ipv6Addr {
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_stable(feature = "const_ipv6", since = "1.32.0")]
#[allow_internal_unstable(const_fn_transmute)]
pub const fn new(a: u16, b: u16, c: u16, d: u16, e: u16, f: u16, g: u16, h: u16) -> Ipv6Addr {
let addr16 = [
a.to_be(),
b.to_be(),
c.to_be(),
d.to_be(),
e.to_be(),
f.to_be(),
g.to_be(),
h.to_be(),
];
Ipv6Addr {
inner: c::in6_addr {
s6_addr: [
(a >> 8) as u8,
a as u8,
(b >> 8) as u8,
b as u8,
(c >> 8) as u8,
c as u8,
(d >> 8) as u8,
d as u8,
(e >> 8) as u8,
e as u8,
(f >> 8) as u8,
f as u8,
(g >> 8) as u8,
g as u8,
(h >> 8) as u8,
h as u8,
],
// All elements in `addr16` are big endian.
// SAFETY: `[u16; 8]` is always safe to transmute to `[u8; 16]`.
s6_addr: unsafe { transmute::<_, [u8; 16]>(addr16) },
},
}
}
@ -1108,16 +1108,19 @@ impl Ipv6Addr {
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn segments(&self) -> [u16; 8] {
let arr = &self.inner.s6_addr;
// All elements in `s6_addr` must be big endian.
// SAFETY: `[u8; 16]` is always safe to transmute to `[u16; 8]`.
let [a, b, c, d, e, f, g, h] = unsafe { transmute::<_, [u16; 8]>(self.inner.s6_addr) };
// We want native endian u16
[
u16::from_be_bytes([arr[0], arr[1]]),
u16::from_be_bytes([arr[2], arr[3]]),
u16::from_be_bytes([arr[4], arr[5]]),
u16::from_be_bytes([arr[6], arr[7]]),
u16::from_be_bytes([arr[8], arr[9]]),
u16::from_be_bytes([arr[10], arr[11]]),
u16::from_be_bytes([arr[12], arr[13]]),
u16::from_be_bytes([arr[14], arr[15]]),
u16::from_be(a),
u16::from_be(b),
u16::from_be(c),
u16::from_be(d),
u16::from_be(e),
u16::from_be(f),
u16::from_be(g),
u16::from_be(h),
]
}
@ -1477,6 +1480,37 @@ impl Ipv6Addr {
(self.segments()[0] & 0xff00) == 0xff00
}
/// Converts this address to an [IPv4 address] if it's an "IPv4-mapped IPv6 address"
/// defined in [IETF RFC 4291 section 2.5.5.2], otherwise returns [`None`].
///
/// `::ffff:a.b.c.d` becomes `a.b.c.d`.
/// All addresses *not* starting with `::ffff` will return `None`.
///
/// [IPv4 address]: ../../std/net/struct.Ipv4Addr.html
/// [`None`]: ../../std/option/enum.Option.html#variant.None
/// [IETF RFC 4291 section 2.5.5.2]: https://tools.ietf.org/html/rfc4291#section-2.5.5.2
///
/// # Examples
///
/// ```
/// #![feature(ip)]
///
/// use std::net::{Ipv4Addr, Ipv6Addr};
///
/// assert_eq!(Ipv6Addr::new(0xff00, 0, 0, 0, 0, 0, 0, 0).to_ipv4_mapped(), None);
/// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).to_ipv4_mapped(),
/// Some(Ipv4Addr::new(192, 10, 2, 255)));
/// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1).to_ipv4_mapped(), None);
/// ```
pub fn to_ipv4_mapped(&self) -> Option<Ipv4Addr> {
match self.octets() {
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, a, b, c, d] => {
Some(Ipv4Addr::new(a, b, c, d))
}
_ => None,
}
}
/// Converts this address to an [IPv4 address]. Returns [`None`] if this address is
/// neither IPv4-compatible or IPv4-mapped.
///
@ -1498,11 +1532,12 @@ impl Ipv6Addr {
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn to_ipv4(&self) -> Option<Ipv4Addr> {
match self.segments() {
[0, 0, 0, 0, 0, f, g, h] if f == 0 || f == 0xffff => {
Some(Ipv4Addr::new((g >> 8) as u8, g as u8, (h >> 8) as u8, h as u8))
}
_ => None,
if let [0, 0, 0, 0, 0, 0 | 0xffff, ab, cd] = self.segments() {
let [a, b] = ab.to_be_bytes();
let [c, d] = cd.to_be_bytes();
Some(Ipv4Addr::new(a, b, c, d))
} else {
None
}
}
@ -2073,6 +2108,15 @@ mod tests {
);
}
#[test]
fn ipv6_to_ipv4_mapped() {
assert_eq!(
Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0x1234, 0x5678).to_ipv4_mapped(),
Some(Ipv4Addr::new(0x12, 0x34, 0x56, 0x78))
);
assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0x1234, 0x5678).to_ipv4_mapped(), None);
}
#[test]
fn ipv6_to_ipv4() {
assert_eq!(

View File

@ -8,7 +8,7 @@ use crate::os::android::raw;
/// OS-specific extensions to [`fs::Metadata`].
///
/// [`fs::Metadata`]: ../../../../std/fs/struct.Metadata.html
/// [`fs::Metadata`]: crate::fs::Metadata
#[stable(feature = "metadata_ext", since = "1.1.0")]
pub trait MetadataExt {
/// Gain a reference to the underlying `stat` structure which contains

View File

@ -8,7 +8,7 @@ use crate::os::dragonfly::raw;
/// OS-specific extensions to [`fs::Metadata`].
///
/// [`fs::Metadata`]: ../../../../std/fs/struct.Metadata.html
/// [`fs::Metadata`]: crate::fs::Metadata
#[stable(feature = "metadata_ext", since = "1.1.0")]
pub trait MetadataExt {
/// Gain a reference to the underlying `stat` structure which contains

View File

@ -8,7 +8,7 @@ use crate::os::emscripten::raw;
/// OS-specific extensions to [`fs::Metadata`].
///
/// [`fs::Metadata`]: ../../../../std/fs/struct.Metadata.html
/// [`fs::Metadata`]: crate::fs::Metadata
#[stable(feature = "metadata_ext", since = "1.1.0")]
pub trait MetadataExt {
/// Gain a reference to the underlying `stat` structure which contains

View File

@ -8,7 +8,7 @@ use crate::os::freebsd::raw;
/// OS-specific extensions to [`fs::Metadata`].
///
/// [`fs::Metadata`]: ../../../../std/fs/struct.Metadata.html
/// [`fs::Metadata`]: crate::fs::Metadata
#[stable(feature = "metadata_ext", since = "1.1.0")]
pub trait MetadataExt {
/// Gain a reference to the underlying `stat` structure which contains

View File

@ -5,7 +5,7 @@ use crate::sys_common::AsInner;
/// OS-specific extensions to [`fs::Metadata`].
///
/// [`fs::Metadata`]: ../../../../std/fs/struct.Metadata.html
/// [`fs::Metadata`]: crate::fs::Metadata
#[stable(feature = "metadata_ext", since = "1.1.0")]
pub trait MetadataExt {
#[stable(feature = "metadata_ext2", since = "1.8.0")]

View File

@ -8,7 +8,7 @@ use crate::os::haiku::raw;
/// OS-specific extensions to [`fs::Metadata`].
///
/// [`fs::Metadata`]: ../../../../std/fs/struct.Metadata.html
/// [`fs::Metadata`]: crate::fs::Metadata
#[stable(feature = "metadata_ext", since = "1.1.0")]
pub trait MetadataExt {
/// Gain a reference to the underlying `stat` structure which contains

View File

@ -8,7 +8,7 @@ use crate::os::illumos::raw;
/// OS-specific extensions to [`fs::Metadata`].
///
/// [`fs::Metadata`]: ../../../../std/fs/struct.Metadata.html
/// [`fs::Metadata`]: crate::fs::Metadata
#[stable(feature = "metadata_ext", since = "1.1.0")]
pub trait MetadataExt {
/// Gain a reference to the underlying `stat` structure which contains

View File

@ -8,7 +8,7 @@ use crate::os::ios::raw;
/// OS-specific extensions to [`fs::Metadata`].
///
/// [`fs::Metadata`]: ../../../../std/fs/struct.Metadata.html
/// [`fs::Metadata`]: crate::fs::Metadata
#[stable(feature = "metadata_ext", since = "1.1.0")]
pub trait MetadataExt {
/// Gain a reference to the underlying `stat` structure which contains

View File

@ -8,7 +8,7 @@ use crate::os::linux::raw;
/// OS-specific extensions to [`fs::Metadata`].
///
/// [`fs::Metadata`]: ../../../../std/fs/struct.Metadata.html
/// [`fs::Metadata`]: crate::fs::Metadata
#[stable(feature = "metadata_ext", since = "1.1.0")]
pub trait MetadataExt {
/// Gain a reference to the underlying `stat` structure which contains
@ -18,7 +18,7 @@ pub trait MetadataExt {
/// Unix platforms. The `os::unix::fs::MetadataExt` trait contains the
/// cross-Unix abstractions contained within the raw stat.
///
/// [`stat`]: ../../../../std/os/linux/raw/struct.stat.html
/// [`stat`]: crate::os::linux::raw::stat
///
/// # Examples
///

View File

@ -8,7 +8,7 @@ use crate::os::macos::raw;
/// OS-specific extensions to [`fs::Metadata`].
///
/// [`fs::Metadata`]: ../../../../std/fs/struct.Metadata.html
/// [`fs::Metadata`]: crate::fs::Metadata
#[stable(feature = "metadata_ext", since = "1.1.0")]
pub trait MetadataExt {
/// Gain a reference to the underlying `stat` structure which contains

View File

@ -8,7 +8,7 @@ use crate::os::netbsd::raw;
/// OS-specific extensions to [`fs::Metadata`].
///
/// [`fs::Metadata`]: ../../../../std/fs/struct.Metadata.html
/// [`fs::Metadata`]: crate::fs::Metadata
#[stable(feature = "metadata_ext", since = "1.1.0")]
pub trait MetadataExt {
/// Gain a reference to the underlying `stat` structure which contains

View File

@ -8,7 +8,7 @@ use crate::os::openbsd::raw;
/// OS-specific extensions to [`fs::Metadata`].
///
/// [`fs::Metadata`]: ../../../../std/fs/struct.Metadata.html
/// [`fs::Metadata`]: crate::fs::Metadata
#[stable(feature = "metadata_ext", since = "1.1.0")]
pub trait MetadataExt {
/// Gain a reference to the underlying `stat` structure which contains

View File

@ -5,7 +5,5 @@ Equivalent to C's `char` type.
C chars are most commonly used to make C strings. Unlike Rust, where the length of a string is included alongside the string, C strings mark the end of a string with the character `'\0'`. See [`CStr`] for more information.
[C's `char` type]: https://en.wikipedia.org/wiki/C_data_types#Basic_types
[Rust's `char` type]: ../../primitive.char.html
[`CStr`]: ../../ffi/struct.CStr.html
[`i8`]: ../../primitive.i8.html
[`u8`]: ../../primitive.u8.html
[Rust's `char` type]: char
[`CStr`]: crate::ffi::CStr

View File

@ -3,5 +3,4 @@ Equivalent to C's `double` type.
This type will almost always be [`f64`], which is guaranteed to be an [IEEE-754 double-precision float] in Rust. That said, the standard technically only guarantees that it be a floating-point number with at least the precision of a [`float`], and it may be `f32` or something entirely different from the IEEE-754 standard.
[IEEE-754 double-precision float]: https://en.wikipedia.org/wiki/IEEE_754
[`float`]: type.c_float.html
[`f64`]: ../../primitive.f64.html
[`float`]: c_float

View File

@ -3,4 +3,3 @@ Equivalent to C's `float` type.
This type will almost always be [`f32`], which is guaranteed to be an [IEEE-754 single-precision float] in Rust. That said, the standard technically only guarantees that it be a floating-point number, and it may have less precision than `f32` or not follow the IEEE-754 standard at all.
[IEEE-754 single-precision float]: https://en.wikipedia.org/wiki/IEEE_754
[`f32`]: ../../primitive.f32.html

View File

@ -2,6 +2,4 @@ Equivalent to C's `signed int` (`int`) type.
This type will almost always be [`i32`], but may differ on some esoteric systems. The C standard technically only requires that this type be a signed integer that is at least the size of a [`short`]; some systems define it as an [`i16`], for example.
[`short`]: type.c_short.html
[`i32`]: ../../primitive.i32.html
[`i16`]: ../../primitive.i16.html
[`short`]: c_short

View File

@ -2,6 +2,4 @@ Equivalent to C's `signed long` (`long`) type.
This type will always be [`i32`] or [`i64`]. Most notably, many Linux-based systems assume an `i64`, but Windows assumes `i32`. The C standard technically only requires that this type be a signed integer that is at least 32 bits and at least the size of an [`int`], although in practice, no system would have a `long` that is neither an `i32` nor `i64`.
[`int`]: type.c_int.html
[`i32`]: ../../primitive.i32.html
[`i64`]: ../../primitive.i64.html
[`int`]: c_int

View File

@ -2,6 +2,4 @@ Equivalent to C's `signed long long` (`long long`) type.
This type will almost always be [`i64`], but may differ on some systems. The C standard technically only requires that this type be a signed integer that is at least 64 bits and at least the size of a [`long`], although in practice, no system would have a `long long` that is not an `i64`, as most systems do not have a standardised [`i128`] type.
[`long`]: type.c_int.html
[`i64`]: ../../primitive.i64.html
[`i128`]: ../../primitive.i128.html
[`long`]: c_int

View File

@ -2,5 +2,4 @@ Equivalent to C's `signed char` type.
This type will always be [`i8`], but is included for completeness. It is defined as being a signed integer the same size as a C [`char`].
[`char`]: type.c_char.html
[`i8`]: ../../primitive.i8.html
[`char`]: c_char

View File

@ -2,5 +2,4 @@ Equivalent to C's `signed short` (`short`) type.
This type will almost always be [`i16`], but may differ on some esoteric systems. The C standard technically only requires that this type be a signed integer with at least 16 bits; some systems may define it as `i32`, for example.
[`char`]: type.c_char.html
[`i16`]: ../../primitive.i16.html
[`char`]: c_char

View File

@ -2,5 +2,4 @@ Equivalent to C's `unsigned char` type.
This type will always be [`u8`], but is included for completeness. It is defined as being an unsigned integer the same size as a C [`char`].
[`char`]: type.c_char.html
[`u8`]: ../../primitive.u8.html
[`char`]: c_char

View File

@ -2,6 +2,4 @@ Equivalent to C's `unsigned int` type.
This type will almost always be [`u32`], but may differ on some esoteric systems. The C standard technically only requires that this type be an unsigned integer with the same size as an [`int`]; some systems define it as a [`u16`], for example.
[`int`]: type.c_int.html
[`u32`]: ../../primitive.u32.html
[`u16`]: ../../primitive.u16.html
[`int`]: c_int

View File

@ -2,6 +2,4 @@ Equivalent to C's `unsigned long` type.
This type will always be [`u32`] or [`u64`]. Most notably, many Linux-based systems assume an `u64`, but Windows assumes `u32`. The C standard technically only requires that this type be an unsigned integer with the size of a [`long`], although in practice, no system would have a `ulong` that is neither a `u32` nor `u64`.
[`long`]: type.c_long.html
[`u32`]: ../../primitive.u32.html
[`u64`]: ../../primitive.u64.html
[`long`]: c_long

View File

@ -2,6 +2,4 @@ Equivalent to C's `unsigned long long` type.
This type will almost always be [`u64`], but may differ on some systems. The C standard technically only requires that this type be an unsigned integer with the size of a [`long long`], although in practice, no system would have a `long long` that is not a `u64`, as most systems do not have a standardised [`u128`] type.
[`long long`]: type.c_longlong.html
[`u64`]: ../../primitive.u64.html
[`u128`]: ../../primitive.u128.html
[`long long`]: c_longlong

View File

@ -2,5 +2,4 @@ Equivalent to C's `unsigned short` type.
This type will almost always be [`u16`], but may differ on some esoteric systems. The C standard technically only requires that this type be an unsigned integer with the same size as a [`short`].
[`short`]: type.c_short.html
[`u16`]: ../../primitive.u16.html
[`short`]: c_short

View File

@ -8,7 +8,7 @@ use crate::os::redox::raw;
/// OS-specific extensions to [`fs::Metadata`].
///
/// [`fs::Metadata`]: ../../../../std/fs/struct.Metadata.html
/// [`fs::Metadata`]: crate::fs::Metadata
#[stable(feature = "metadata_ext", since = "1.1.0")]
pub trait MetadataExt {
/// Gain a reference to the underlying `stat` structure which contains
@ -18,7 +18,7 @@ pub trait MetadataExt {
/// Unix platforms. The `os::unix::fs::MetadataExt` trait contains the
/// cross-Unix abstractions contained within the raw stat.
///
/// [`stat`]: ../../../../std/os/redox/raw/struct.stat.html
/// [`stat`]: crate::os::redox::raw::stat
///
/// # Examples
///

View File

@ -8,7 +8,7 @@ use crate::os::solaris::raw;
/// OS-specific extensions to [`fs::Metadata`].
///
/// [`fs::Metadata`]: ../../../../std/fs/struct.Metadata.html
/// [`fs::Metadata`]: crate::fs::Metadata
#[stable(feature = "metadata_ext", since = "1.1.0")]
pub trait MetadataExt {
/// Gain a reference to the underlying `stat` structure which contains

View File

@ -4,7 +4,7 @@ use crate::fs::Metadata;
use crate::sys_common::AsInner;
///
/// [`fs::Metadata`]: ../../../../std/fs/struct.Metadata.html
/// [`fs::Metadata`]: crate::fs::Metadata
#[stable(feature = "metadata_ext", since = "1.1.0")]
pub trait MetadataExt {
#[stable(feature = "metadata_ext2", since = "1.8.0")]

View File

@ -17,7 +17,7 @@
//! such as [`std::io::prelude`]. Various libraries in the Rust ecosystem may
//! also define their own preludes.
//!
//! [`std::io::prelude`]: ../io/prelude/index.html
//! [`std::io::prelude`]: crate::io::prelude
//!
//! The difference between 'the prelude' and these other preludes is that they
//! are not automatically `use`'d, and must be imported manually. This is still
@ -49,67 +49,34 @@
//! * [`std::iter`]::{[`Iterator`], [`Extend`], [`IntoIterator`],
//! [`DoubleEndedIterator`], [`ExactSizeIterator`]}. Iterators of various
//! kinds.
//! * [`std::option`]::[`Option`]::{`self`, `Some`, `None`}. A type which
//! expresses the presence or absence of a value. This type is so commonly
//! used, its variants are also exported.
//! * [`std::result`]::[`Result`]::{`self`, `Ok`, `Err`}. A type for functions
//! that may succeed or fail. Like [`Option`], its variants are exported as
//! well.
//! * [`std::option`]::[`Option`]::{[`self`][`Option`], [`Some`], [`None`]}. A
//! type which expresses the presence or absence of a value. This type is so
//! commonly used, its variants are also exported.
//! * [`std::result`]::[`Result`]::{[`self`][`Result`], [`Ok`], [`Err`]}. A type
//! for functions that may succeed or fail. Like [`Option`], its variants are
//! exported as well.
//! * [`std::string`]::{[`String`], [`ToString`]}, heap allocated strings.
//! * [`std::vec`]::[`Vec`](../vec/struct.Vec.html), a growable, heap-allocated
//! * [`std::vec`]::[`Vec`], a growable, heap-allocated
//! vector.
//!
//! [`AsMut`]: ../convert/trait.AsMut.html
//! [`AsRef`]: ../convert/trait.AsRef.html
//! [`Box`]: ../boxed/struct.Box.html
//! [`Clone`]: ../clone/trait.Clone.html
//! [`Copy`]: ../marker/trait.Copy.html
//! [`Default`]: ../default/trait.Default.html
//! [`DoubleEndedIterator`]: ../iter/trait.DoubleEndedIterator.html
//! [`Drop`]: ../ops/trait.Drop.html
//! [`Eq`]: ../cmp/trait.Eq.html
//! [`ExactSizeIterator`]: ../iter/trait.ExactSizeIterator.html
//! [`Extend`]: ../iter/trait.Extend.html
//! [`FnMut`]: ../ops/trait.FnMut.html
//! [`FnOnce`]: ../ops/trait.FnOnce.html
//! [`Fn`]: ../ops/trait.Fn.html
//! [`From`]: ../convert/trait.From.html
//! [`IntoIterator`]: ../iter/trait.IntoIterator.html
//! [`Into`]: ../convert/trait.Into.html
//! [`Iterator`]: ../iter/trait.Iterator.html
//! [`Option`]: ../option/enum.Option.html
//! [`Ord`]: ../cmp/trait.Ord.html
//! [`PartialEq`]: ../cmp/trait.PartialEq.html
//! [`PartialOrd`]: ../cmp/trait.PartialOrd.html
//! [`Result`]: ../result/enum.Result.html
//! [`Send`]: ../marker/trait.Send.html
//! [`Sized`]: ../marker/trait.Sized.html
//! [`SliceConcatExt`]: ../slice/trait.SliceConcatExt.html
//! [`String`]: ../string/struct.String.html
//! [`Sync`]: ../marker/trait.Sync.html
//! [`ToOwned`]: ../borrow/trait.ToOwned.html
//! [`ToString`]: ../string/trait.ToString.html
//! [`Unpin`]: ../marker/trait.Unpin.html
//! [`Vec`]: ../vec/struct.Vec.html
//! [`Clone::clone`]: ../clone/trait.Clone.html#tymethod.clone
//! [`mem::drop`]: ../mem/fn.drop.html
//! [`std::borrow`]: ../borrow/index.html
//! [`std::boxed`]: ../boxed/index.html
//! [`std::clone`]: ../clone/index.html
//! [`std::cmp`]: ../cmp/index.html
//! [`std::convert`]: ../convert/index.html
//! [`std::default`]: ../default/index.html
//! [`std::iter`]: ../iter/index.html
//! [`std::marker`]: ../marker/index.html
//! [`std::mem`]: ../mem/index.html
//! [`std::ops`]: ../ops/index.html
//! [`std::option`]: ../option/index.html
//! [`std::prelude::v1`]: v1/index.html
//! [`std::result`]: ../result/index.html
//! [`std::slice`]: ../slice/index.html
//! [`std::string`]: ../string/index.html
//! [`mem::drop`]: crate::mem::drop
//! [`std::borrow`]: crate::borrow
//! [`std::boxed`]: crate::boxed
//! [`std::clone`]: crate::clone
//! [`std::cmp`]: crate::cmp
//! [`std::convert`]: crate::convert
//! [`std::default`]: crate::default
//! [`std::iter`]: crate::iter
//! [`std::marker`]: crate::marker
//! [`std::mem`]: crate::mem
//! [`std::ops`]: crate::ops
//! [`std::option`]: crate::option
//! [`std::prelude::v1`]: v1
//! [`std::result`]: crate::result
//! [`std::slice`]: crate::slice
//! [`std::string`]: crate::string
//! [`std::vec`]: ../vec/index.html
//! [`to_owned`]: ../borrow/trait.ToOwned.html#tymethod.to_owned
//! [`to_owned`]: crate::borrow::ToOwned::to_owned
//! [book-closures]: ../../book/ch13-01-closures.html
//! [book-dtor]: ../../book/ch15-03-drop.html
//! [book-enums]: ../../book/ch06-01-defining-an-enum.html

View File

@ -764,19 +764,55 @@ mod prim_str {}
mod prim_tuple {}
#[doc(primitive = "f32")]
/// The 32-bit floating point type.
/// A 32-bit floating point type (specifically, the "binary32" type defined in IEEE 754-2008).
///
/// This type can represent a wide range of decimal numbers, like `3.5`, `27`,
/// `-113.75`, `0.0078125`, `34359738368`, `0`, `-1`. So unlike integer types
/// (such as `i32`), floating point types can represent non-integer numbers,
/// too.
///
/// However, being able to represent this wide range of numbers comes at the
/// cost of precision: floats can only represent some of the real numbers and
/// calculation with floats round to a nearby representable number. For example,
/// `5.0` and `1.0` can be exactly represented as `f32`, but `1.0 / 5.0` results
/// in `0.20000000298023223876953125` since `0.2` cannot be exactly represented
/// as `f32`. Note however, that printing floats with `println` and friends will
/// often discard insignificant digits: `println!("{}", 1.0f32 / 5.0f32)` will
/// print `0.2`.
///
/// Additionally, `f32` can represent a couple of special values:
///
/// - `-0`: this is just due to how floats are encoded. It is semantically
/// equivalent to `0` and `-0.0 == 0.0` results in `true`.
/// - [∞](#associatedconstant.INFINITY) and
/// [−∞](#associatedconstant.NEG_INFINITY): these result from calculations
/// like `1.0 / 0.0`.
/// - [NaN (not a number)](#associatedconstant.NAN): this value results from
/// calculations like `(-1.0).sqrt()`. NaN has some potentially unexpected
/// behavior: it is unequal to any float, including itself! It is also neither
/// smaller nor greater than any float, making it impossible to sort. Lastly,
/// it is considered infectious as almost all calculations where one of the
/// operands is NaN will also result in NaN.
///
/// For more information on floating point numbers, see [Wikipedia][wikipedia].
///
/// *[See also the `std::f32::consts` module](f32/consts/index.html).*
///
/// [wikipedia]: https://en.wikipedia.org/wiki/Single-precision_floating-point_format
#[stable(feature = "rust1", since = "1.0.0")]
mod prim_f32 {}
#[doc(primitive = "f64")]
//
/// The 64-bit floating point type.
/// A 64-bit floating point type (specifically, the "binary64" type defined in IEEE 754-2008).
///
/// This type is very similar to [`f32`](primitive.f32.html), but has increased
/// precision by using twice as many bits. Please see [the documentation for
/// `f32`](primitive.f32.html) or [Wikipedia on double precision
/// values][wikipedia] for more information.
///
/// *[See also the `std::f64::consts` module](f64/consts/index.html).*
///
/// [wikipedia]: https://en.wikipedia.org/wiki/Double-precision_floating-point_format
#[stable(feature = "rust1", since = "1.0.0")]
mod prim_f64 {}
@ -1022,6 +1058,8 @@ mod prim_ref {}
/// not be null, so if you want to pass a function pointer over FFI and be able to accommodate null
/// pointers, make your type `Option<fn()>` with your required signature.
///
/// ### Safety
///
/// Plain function pointers are obtained by casting either plain functions, or closures that don't
/// capture an environment:
///
@ -1059,23 +1097,60 @@ mod prim_ref {}
/// let really_safe_ptr: unsafe fn(usize) -> usize = add_one;
/// ```
///
/// On top of that, function pointers can vary based on what ABI they use. This is achieved by
/// adding the `extern` keyword to the type name, followed by the ABI in question. For example,
/// `fn()` is different from `extern "C" fn()`, which itself is different from `extern "stdcall"
/// fn()`, and so on for the various ABIs that Rust supports. Non-`extern` functions have an ABI
/// of `"Rust"`, and `extern` functions without an explicit ABI have an ABI of `"C"`. For more
/// information, see [the nomicon's section on foreign calling conventions][nomicon-abi].
/// ### ABI
///
/// [nomicon-abi]: ../nomicon/ffi.html#foreign-calling-conventions
/// On top of that, function pointers can vary based on what ABI they use. This
/// is achieved by adding the `extern` keyword before the type, followed by the
/// ABI in question. The default ABI is "Rust", i.e., `fn()` is the exact same
/// type as `extern "Rust" fn()`. A pointer to a function with C ABI would have
/// type `extern "C" fn()`.
///
/// `extern "ABI" { ... }` blocks declare functions with ABI "ABI". The default
/// here is "C", i.e., functions declared in an `extern {...}` block have "C"
/// ABI.
///
/// For more information and a list of supported ABIs, see [the nomicon's
/// section on foreign calling conventions][nomicon-abi].
///
/// ### Variadic functions
///
/// Extern function declarations with the "C" or "cdecl" ABIs can also be *variadic*, allowing them
/// to be called with a variable number of arguments. Normal rust functions, even those with an
/// to be called with a variable number of arguments. Normal Rust functions, even those with an
/// `extern "ABI"`, cannot be variadic. For more information, see [the nomicon's section on
/// variadic functions][nomicon-variadic].
///
/// [nomicon-variadic]: ../nomicon/ffi.html#variadic-functions
///
/// These markers can be combined, so `unsafe extern "stdcall" fn()` is a valid type.
/// ### Creating function pointers
///
/// When `bar` is the name of a function, then the expression `bar` is *not* a
/// function pointer. Rather, it denotes a value of an unnameable type that
/// uniquely identifies the function `bar`. The value is zero-sized because the
/// type already identifies the function. This has the advantage that "calling"
/// the value (it implements the `Fn*` traits) does not require dynamic
/// dispatch.
///
/// This zero-sized type *coerces* to a regular function pointer. For example:
///
/// ```rust
/// use std::mem;
///
/// fn bar(x: i32) {}
///
/// let not_bar_ptr = bar; // `not_bar_ptr` is zero-sized, uniquely identifying `bar`
/// assert_eq!(mem::size_of_val(&not_bar_ptr), 0);
///
/// let bar_ptr: fn(i32) = not_bar_ptr; // force coercion to function pointer
/// assert_eq!(mem::size_of_val(&bar_ptr), mem::size_of::<usize>());
///
/// let footgun = &bar; // this is a shared reference to the zero-sized type identifying `bar`
/// ```
///
/// The last line shows that `&bar` is not a function pointer either. Rather, it
/// is a reference to the function-specific ZST. `&bar` is basically never what you
/// want when `bar` is a function.
///
/// ### Traits
///
/// Function pointers implement the following traits:
///

View File

@ -84,25 +84,15 @@
//! assert_eq!(b"test", output.stdout.as_slice());
//! ```
//!
//! [`abort`]: fn.abort.html
//! [`exit`]: fn.exit.html
//! [`spawn`]: Command::spawn
//! [`output`]: Command::output
//!
//! [`Command`]: struct.Command.html
//! [`spawn`]: struct.Command.html#method.spawn
//! [`output`]: struct.Command.html#method.output
//! [`stdout`]: Command::stdout
//! [`stdin`]: Command::stdin
//! [`stderr`]: Command::stderr
//!
//! [`Child`]: struct.Child.html
//! [`ChildStdin`]: struct.ChildStdin.html
//! [`ChildStdout`]: struct.ChildStdout.html
//! [`ChildStderr`]: struct.ChildStderr.html
//! [`Stdio`]: struct.Stdio.html
//!
//! [`stdout`]: struct.Command.html#method.stdout
//! [`stdin`]: struct.Command.html#method.stdin
//! [`stderr`]: struct.Command.html#method.stderr
//!
//! [`Write`]: ../io/trait.Write.html
//! [`Read`]: ../io/trait.Read.html
//! [`Write`]: io::Write
//! [`Read`]: io::Read
#![stable(feature = "process", since = "1.0.0")]
@ -130,7 +120,7 @@ use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner};
/// run, even after the `Child` handle to the child process has gone out of
/// scope.
///
/// Calling [`wait`](#method.wait) (or other functions that wrap around it) will make
/// Calling [`wait`] (or other functions that wrap around it) will make
/// the parent process wait until the child has actually exited before
/// continuing.
///
@ -162,25 +152,44 @@ use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner};
/// assert!(ecode.success());
/// ```
///
/// [`Command`]: struct.Command.html
/// [`Drop`]: ../../core/ops/trait.Drop.html
/// [`wait`]: #method.wait
/// [`wait`]: Child::wait
#[stable(feature = "process", since = "1.0.0")]
pub struct Child {
handle: imp::Process,
/// The handle for writing to the child's standard input (stdin), if it has
/// been captured.
/// been captured. To avoid partially moving
/// the `child` and thus blocking yourself from calling
/// functions on `child` while using `stdin`,
/// you might find it helpful:
///
/// ```compile_fail,E0425
/// let stdin = child.stdin.take().unwrap();
/// ```
#[stable(feature = "process", since = "1.0.0")]
pub stdin: Option<ChildStdin>,
/// The handle for reading from the child's standard output (stdout), if it
/// has been captured.
/// has been captured. You might find it helpful to do
///
/// ```compile_fail,E0425
/// let stdout = child.stdout.take().unwrap();
/// ```
///
/// to avoid partially moving the `child` and thus blocking yourself from calling
/// functions on `child` while using `stdout`.
#[stable(feature = "process", since = "1.0.0")]
pub stdout: Option<ChildStdout>,
/// The handle for reading from the child's standard error (stderr), if it
/// has been captured.
/// has been captured. You might find it helpful to do
///
/// ```compile_fail,E0425
/// let stderr = child.stderr.take().unwrap();
/// ```
///
/// to avoid partially moving the `child` and thus blocking yourself from calling
/// functions on `child` while using `stderr`.
#[stable(feature = "process", since = "1.0.0")]
pub stderr: Option<ChildStderr>,
}
@ -227,9 +236,8 @@ impl fmt::Debug for Child {
/// file handle will be closed. If the child process was blocked on input prior
/// to being dropped, it will become unblocked after dropping.
///
/// [`Child`]: struct.Child.html
/// [`stdin`]: struct.Child.html#structfield.stdin
/// [dropped]: ../ops/trait.Drop.html
/// [`stdin`]: Child::stdin
/// [dropped]: Drop
#[stable(feature = "process", since = "1.0.0")]
pub struct ChildStdin {
inner: AnonPipe,
@ -286,9 +294,8 @@ impl fmt::Debug for ChildStdin {
/// When an instance of `ChildStdout` is [dropped], the `ChildStdout`'s
/// underlying file handle will be closed.
///
/// [`Child`]: struct.Child.html
/// [`stdout`]: struct.Child.html#structfield.stdout
/// [dropped]: ../ops/trait.Drop.html
/// [`stdout`]: Child::stdout
/// [dropped]: Drop
#[stable(feature = "process", since = "1.0.0")]
pub struct ChildStdout {
inner: AnonPipe,
@ -347,9 +354,8 @@ impl fmt::Debug for ChildStdout {
/// When an instance of `ChildStderr` is [dropped], the `ChildStderr`'s
/// underlying file handle will be closed.
///
/// [`Child`]: struct.Child.html
/// [`stderr`]: struct.Child.html#structfield.stderr
/// [dropped]: ../ops/trait.Drop.html
/// [`stderr`]: Child::stderr
/// [dropped]: Drop
#[stable(feature = "process", since = "1.0.0")]
pub struct ChildStderr {
inner: AnonPipe,
@ -522,7 +528,7 @@ impl Command {
///
/// To pass multiple arguments see [`args`].
///
/// [`args`]: #method.args
/// [`args`]: Command::args
///
/// # Examples
///
@ -547,7 +553,7 @@ impl Command {
///
/// To pass a single argument see [`arg`].
///
/// [`arg`]: #method.arg
/// [`arg`]: Command::arg
///
/// # Examples
///
@ -700,7 +706,7 @@ impl Command {
/// .expect("ls command failed to start");
/// ```
///
/// [`canonicalize`]: ../fs/fn.canonicalize.html
/// [`canonicalize`]: crate::fs::canonicalize
#[stable(feature = "process", since = "1.0.0")]
pub fn current_dir<P: AsRef<Path>>(&mut self, dir: P) -> &mut Command {
self.inner.cwd(dir.as_ref().as_ref());
@ -712,8 +718,8 @@ impl Command {
/// Defaults to [`inherit`] when used with `spawn` or `status`, and
/// defaults to [`piped`] when used with `output`.
///
/// [`inherit`]: struct.Stdio.html#method.inherit
/// [`piped`]: struct.Stdio.html#method.piped
/// [`inherit`]: Stdio::inherit
/// [`piped`]: Stdio::piped
///
/// # Examples
///
@ -738,8 +744,8 @@ impl Command {
/// Defaults to [`inherit`] when used with `spawn` or `status`, and
/// defaults to [`piped`] when used with `output`.
///
/// [`inherit`]: struct.Stdio.html#method.inherit
/// [`piped`]: struct.Stdio.html#method.piped
/// [`inherit`]: Stdio::inherit
/// [`piped`]: Stdio::piped
///
/// # Examples
///
@ -764,8 +770,8 @@ impl Command {
/// Defaults to [`inherit`] when used with `spawn` or `status`, and
/// defaults to [`piped`] when used with `output`.
///
/// [`inherit`]: struct.Stdio.html#method.inherit
/// [`piped`]: struct.Stdio.html#method.piped
/// [`inherit`]: Stdio::inherit
/// [`piped`]: Stdio::piped
///
/// # Examples
///
@ -893,10 +899,8 @@ impl AsInnerMut<imp::Command> for Command {
/// [`Command`], or the [`wait_with_output`] method of a [`Child`]
/// process.
///
/// [`Command`]: struct.Command.html
/// [`Child`]: struct.Child.html
/// [`output`]: struct.Command.html#method.output
/// [`wait_with_output`]: struct.Child.html#method.wait_with_output
/// [`output`]: Command::output
/// [`wait_with_output`]: Child::wait_with_output
#[derive(PartialEq, Eq, Clone)]
#[stable(feature = "process", since = "1.0.0")]
pub struct Output {
@ -939,10 +943,9 @@ impl fmt::Debug for Output {
/// Describes what to do with a standard I/O stream for a child process when
/// passed to the [`stdin`], [`stdout`], and [`stderr`] methods of [`Command`].
///
/// [`stdin`]: struct.Command.html#method.stdin
/// [`stdout`]: struct.Command.html#method.stdout
/// [`stderr`]: struct.Command.html#method.stderr
/// [`Command`]: struct.Command.html
/// [`stdin`]: Command::stdin
/// [`stdout`]: Command::stdout
/// [`stderr`]: Command::stderr
#[stable(feature = "process", since = "1.0.0")]
pub struct Stdio(imp::Stdio);
@ -1206,10 +1209,8 @@ impl From<fs::File> for Stdio {
/// status is exposed through the [`status`] method, or the [`wait`] method
/// of a [`Child`] process.
///
/// [`Command`]: struct.Command.html
/// [`Child`]: struct.Child.html
/// [`status`]: struct.Command.html#method.status
/// [`wait`]: struct.Child.html#method.wait
/// [`status`]: Command::status
/// [`wait`]: Child::wait
#[derive(PartialEq, Eq, Clone, Copy, Debug)]
#[stable(feature = "process", since = "1.0.0")]
pub struct ExitStatus(imp::ExitStatus);
@ -1294,8 +1295,8 @@ impl fmt::Display for ExitStatus {
/// For the platform's canonical successful and unsuccessful codes, see
/// the [`SUCCESS`] and [`FAILURE`] associated items.
///
/// [`SUCCESS`]: #associatedconstant.SUCCESS
/// [`FAILURE`]: #associatedconstant.FAILURE
/// [`SUCCESS`]: ExitCode::SUCCESS
/// [`FAILURE`]: ExitCode::FAILURE
///
/// **Warning**: While various forms of this were discussed in [RFC #1937],
/// it was ultimately cut from that RFC, and thus this type is more subject
@ -1349,9 +1350,9 @@ impl Child {
/// }
/// ```
///
/// [`ErrorKind`]: ../io/enum.ErrorKind.html
/// [`InvalidInput`]: ../io/enum.ErrorKind.html#variant.InvalidInput
/// [`Other`]: ../io/enum.ErrorKind.html#variant.Other
/// [`ErrorKind`]: io::ErrorKind
/// [`InvalidInput`]: io::ErrorKind::InvalidInput
/// [`Other`]: io::ErrorKind::Other
#[stable(feature = "process", since = "1.0.0")]
pub fn kill(&mut self) -> io::Result<()> {
self.handle.kill()
@ -1616,8 +1617,7 @@ pub fn exit(code: i32) -> ! {
/// }
/// ```
///
/// [`panic!`]: ../../std/macro.panic.html
/// [panic hook]: ../../std/panic/fn.set_hook.html
/// [panic hook]: crate::panic::set_hook
#[stable(feature = "process_abort", since = "1.17.0")]
pub fn abort() -> ! {
crate::sys::abort_internal();

View File

@ -46,6 +46,7 @@ pub struct DirEntry {
pub struct OpenOptions {
read: bool,
write: bool,
append: bool,
dirflags: wasi::Lookupflags,
fdflags: wasi::Fdflags,
oflags: wasi::Oflags,
@ -270,8 +271,9 @@ impl OpenOptions {
}
}
pub fn append(&mut self, set: bool) {
self.fdflag(wasi::FDFLAGS_APPEND, set);
pub fn append(&mut self, append: bool) {
self.append = append;
self.fdflag(wasi::FDFLAGS_APPEND, append);
}
pub fn dsync(&mut self, set: bool) {
@ -321,7 +323,7 @@ impl OpenOptions {
base |= wasi::RIGHTS_FD_READ;
base |= wasi::RIGHTS_FD_READDIR;
}
if self.write {
if self.write || self.append {
base |= wasi::RIGHTS_FD_WRITE;
base |= wasi::RIGHTS_FD_DATASYNC;
base |= wasi::RIGHTS_FD_ALLOCATE;

View File

@ -97,7 +97,6 @@ pub use core::time::Duration;
/// [clock_time_get (Monotonic Clock)]: https://nuxi.nl/cloudabi/#clock_time_get
///
/// **Disclaimer:** These system calls might change over time.
///
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[stable(feature = "time2", since = "1.8.0")]
pub struct Instant(time::Instant);
@ -125,11 +124,6 @@ pub struct Instant(time::Instant);
/// The size of a `SystemTime` struct may vary depending on the target operating
/// system.
///
/// [`Instant`]: ../../std/time/struct.Instant.html
/// [`Result`]: ../../std/result/enum.Result.html
/// [`Duration`]: ../../std/time/struct.Duration.html
/// [`UNIX_EPOCH`]: ../../std/time/constant.UNIX_EPOCH.html
///
/// Example:
///
/// ```no_run
@ -176,7 +170,6 @@ pub struct Instant(time::Instant);
/// [GetSystemTimeAsFileTime]: https://docs.microsoft.com/en-us/windows/win32/api/sysinfoapi/nf-sysinfoapi-getsystemtimeasfiletime
///
/// **Disclaimer:** These system calls might change over time.
///
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[stable(feature = "time2", since = "1.8.0")]
pub struct SystemTime(time::SystemTime);
@ -366,9 +359,7 @@ impl Add<Duration> for Instant {
/// # Panics
///
/// This function may panic if the resulting point in time cannot be represented by the
/// underlying data structure. See [`checked_add`] for a version without panic.
///
/// [`checked_add`]: ../../std/time/struct.Instant.html#method.checked_add
/// underlying data structure. See [`Instant::checked_add`] for a version without panic.
fn add(self, other: Duration) -> Instant {
self.checked_add(other).expect("overflow when adding duration to instant")
}
@ -463,11 +454,6 @@ impl SystemTime {
/// Returns an [`Err`] if `earlier` is later than `self`, and the error
/// contains how far from `self` the time is.
///
/// [`Ok`]: ../../std/result/enum.Result.html#variant.Ok
/// [`Duration`]: ../../std/time/struct.Duration.html
/// [`Err`]: ../../std/result/enum.Result.html#variant.Err
/// [`Instant`]: ../../std/time/struct.Instant.html
///
/// # Examples
///
/// ```
@ -497,11 +483,6 @@ impl SystemTime {
/// Returns an [`Err`] if `self` is later than the current system time, and
/// the error contains how far from the current system time `self` is.
///
/// [`Ok`]: ../../std/result/enum.Result.html#variant.Ok
/// [`Duration`]: ../../std/time/struct.Duration.html
/// [`Err`]: ../../std/result/enum.Result.html#variant.Err
/// [`Instant`]: ../../std/time/struct.Instant.html
///
/// # Examples
///
/// ```no_run
@ -542,9 +523,7 @@ impl Add<Duration> for SystemTime {
/// # Panics
///
/// This function may panic if the resulting point in time cannot be represented by the
/// underlying data structure. See [`checked_add`] for a version without panic.
///
/// [`checked_add`]: ../../std/time/struct.SystemTime.html#method.checked_add
/// underlying data structure. See [`SystemTime::checked_add`] for a version without panic.
fn add(self, dur: Duration) -> SystemTime {
self.checked_add(dur).expect("overflow when adding duration to instant")
}
@ -589,8 +568,6 @@ impl fmt::Debug for SystemTime {
/// measurement lies, and using `UNIX_EPOCH + duration` can be used to create a
/// [`SystemTime`] instance to represent another fixed point in time.
///
/// [`SystemTime`]: ../../std/time/struct.SystemTime.html
///
/// # Examples
///
/// ```no_run
@ -608,13 +585,9 @@ impl SystemTimeError {
/// Returns the positive duration which represents how far forward the
/// second system time was from the first.
///
/// A `SystemTimeError` is returned from the [`duration_since`] and [`elapsed`]
/// methods of [`SystemTime`] whenever the second system time represents a point later
/// in time than the `self` of the method call.
///
/// [`duration_since`]: ../../std/time/struct.SystemTime.html#method.duration_since
/// [`elapsed`]: ../../std/time/struct.SystemTime.html#method.elapsed
/// [`SystemTime`]: ../../std/time/struct.SystemTime.html
/// A `SystemTimeError` is returned from the [`SystemTime::duration_since`]
/// and [`SystemTime::elapsed`] methods whenever the second system time
/// represents a point later in time than the `self` of the method call.
///
/// # Examples
///

View File

@ -404,6 +404,7 @@ impl<'a> Builder<'a> {
test::CrateLibrustc,
test::CrateRustdoc,
test::Linkcheck,
test::TierCheck,
test::Cargotest,
test::Cargo,
test::Rls,

View File

@ -178,7 +178,7 @@ impl Step for Llvm {
.define("LLVM_TARGET_ARCH", target_native.split('-').next().unwrap())
.define("LLVM_DEFAULT_TARGET_TRIPLE", target_native);
if !target.contains("netbsd") {
if !target.contains("netbsd") && target != "aarch64-apple-darwin" {
cfg.define("LLVM_ENABLE_ZLIB", "ON");
} else {
// FIXME: Enable zlib on NetBSD too

View File

@ -2043,3 +2043,47 @@ impl Step for Bootstrap {
run.builder.ensure(Bootstrap);
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct TierCheck {
pub compiler: Compiler,
target: TargetSelection,
}
impl Step for TierCheck {
type Output = ();
const DEFAULT: bool = true;
const ONLY_HOSTS: bool = true;
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
run.path("src/tools/tier-check")
}
fn make_run(run: RunConfig<'_>) {
let compiler = run.builder.compiler_for(run.builder.top_stage, run.host, run.host);
run.builder.ensure(TierCheck { compiler, target: run.host });
}
/// Tests the Platform Support page in the rustc book.
fn run(self, builder: &Builder<'_>) {
builder.ensure(compile::Std { compiler: self.compiler, target: self.target });
let mut cargo = tool::prepare_tool_cargo(
builder,
self.compiler,
Mode::ToolRustc,
self.target,
"run",
"src/tools/tier-check",
SourceType::InTree,
&[],
);
cargo.arg(builder.src.join("src/doc/rustc/src/platform-support.md"));
cargo.arg(&builder.rustc(self.compiler));
if builder.is_verbose() {
cargo.arg("--verbose");
}
builder.info("platform support check");
try_run(builder, &mut cargo.into());
}
}

View File

@ -23,9 +23,9 @@ COPY scripts/sccache.sh /scripts/
RUN sh /scripts/sccache.sh
ENV \
AR_i686_unknown_freebsd=i686-unknown-freebsd10-ar \
CC_i686_unknown_freebsd=i686-unknown-freebsd10-clang \
CXX_i686_unknown_freebsd=i686-unknown-freebsd10-clang++
AR_i686_unknown_freebsd=i686-unknown-freebsd11-ar \
CC_i686_unknown_freebsd=i686-unknown-freebsd11-clang \
CXX_i686_unknown_freebsd=i686-unknown-freebsd11-clang++
ENV HOSTS=i686-unknown-freebsd

View File

@ -23,9 +23,9 @@ COPY scripts/sccache.sh /scripts/
RUN sh /scripts/sccache.sh
ENV \
AR_x86_64_unknown_freebsd=x86_64-unknown-freebsd10-ar \
CC_x86_64_unknown_freebsd=x86_64-unknown-freebsd10-clang \
CXX_x86_64_unknown_freebsd=x86_64-unknown-freebsd10-clang++
AR_x86_64_unknown_freebsd=x86_64-unknown-freebsd11-ar \
CC_x86_64_unknown_freebsd=x86_64-unknown-freebsd11-clang \
CXX_x86_64_unknown_freebsd=x86_64-unknown-freebsd11-clang++
ENV HOSTS=x86_64-unknown-freebsd

View File

@ -19,8 +19,13 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
COPY scripts/sccache.sh /scripts/
RUN sh /scripts/sccache.sh
RUN mkdir -p /config
RUN echo "[rust]" > /config/nopt-std-config.toml
RUN echo "optimize = false" >> /config/nopt-std-config.toml
ENV RUST_CONFIGURE_ARGS --build=i686-unknown-linux-gnu --disable-optimize-tests
ENV SCRIPT python3 ../x.py --stage 2 test
ENV SCRIPT python3 ../x.py test --stage 0 --config /config/nopt-std-config.toml library/std \
&& python3 ../x.py --stage 2 test
# FIXME(#59637) takes too long on CI right now
ENV NO_LLVM_ASSERTIONS=1 NO_DEBUG_ASSERTIONS=1

View File

@ -18,7 +18,12 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
COPY scripts/sccache.sh /scripts/
RUN sh /scripts/sccache.sh
RUN mkdir -p /config
RUN echo "[rust]" > /config/nopt-std-config.toml
RUN echo "optimize = false" >> /config/nopt-std-config.toml
ENV RUST_CONFIGURE_ARGS --build=x86_64-unknown-linux-gnu \
--disable-optimize-tests \
--set rust.test-compare-mode
ENV SCRIPT python3 ../x.py --stage 2 test
ENV SCRIPT python3 ../x.py test --stage 0 --config /config/nopt-std-config.toml library/std \
&& python3 ../x.py --stage 2 test

View File

@ -5,8 +5,8 @@ set -eux
arch=$1
binutils_version=2.25.1
freebsd_version=10.3
triple=$arch-unknown-freebsd10
freebsd_version=11.4
triple=$arch-unknown-freebsd11
sysroot=/usr/local/$triple
hide_output() {
@ -58,31 +58,17 @@ for lib in c++ c_nonshared compiler_rt execinfo gcc pthread rt ssp_nonshared; do
done
# Originally downloaded from:
# https://download.freebsd.org/ftp/releases/${freebsd_arch}/${freebsd_version}-RELEASE/base.txz
URL=https://ci-mirrors.rust-lang.org/rustc/2019-04-04-freebsd-${freebsd_arch}-${freebsd_version}-RELEASE-base.txz
# URL=https://download.freebsd.org/ftp/releases/${freebsd_arch}/${freebsd_version}-RELEASE/base.txz
URL=https://ci-mirrors.rust-lang.org/rustc/2020-08-09-freebsd-${freebsd_arch}-${freebsd_version}-RELEASE-base.txz
curl "$URL" | tar xJf - -C "$sysroot" --wildcards "${files_to_extract[@]}"
# Fix up absolute symlinks from the system image. This can be removed
# for FreeBSD 11. (If there's an easy way to make them relative
# symlinks instead, feel free to change this.)
set +x
find "$sysroot" -type l | while read symlink_path; do
symlink_target=$(readlink "$symlink_path")
case $symlink_target in
(/*)
echo "Fixing symlink ${symlink_path} -> ${sysroot}${symlink_target}" >&2
ln -nfs "${sysroot}${symlink_target}" "${symlink_path}" ;;
esac
done
set -x
# Clang can do cross-builds out of the box, if we give it the right
# flags. (The local binutils seem to work, but they set the ELF
# header "OS/ABI" (EI_OSABI) field to SysV rather than FreeBSD, so
# there might be other problems.)
#
# The --target option is last because the cross-build of LLVM uses
# --target without an OS version ("-freebsd" vs. "-freebsd10"). This
# --target without an OS version ("-freebsd" vs. "-freebsd11"). This
# makes Clang default to libstdc++ (which no longer exists), and also
# controls other features, like GNU-style symbol table hashing and
# anything predicated on the version number in the __FreeBSD__

View File

@ -490,15 +490,17 @@ jobs:
# 32/64-bit MinGW builds.
#
# We are using MinGW with posix threads since LLVM does not compile with
# the win32 threads version due to missing support for C++'s std::thread.
# We are using MinGW with POSIX threads since LLVM requires
# C++'s std::thread which is disabled in libstdc++ with win32 threads.
# FIXME: Libc++ doesn't have this limitation so we can avoid
# winpthreads if we switch to it.
#
# Instead of relying on the MinGW version installed on appveryor we download
# and install one ourselves so we won't be surprised by changes to appveyor's
# Instead of relying on the MinGW version installed on CI we download
# and install one ourselves so we won't be surprised by changes to CI's
# build image.
#
# Finally, note that the downloads below are all in the `rust-lang-ci` S3
# bucket, but they cleraly didn't originate there! The downloads originally
# bucket, but they clearly didn't originate there! The downloads originally
# came from the mingw-w64 SourceForge download site. Unfortunately
# SourceForge is notoriously flaky, so we mirror it on our own infrastructure.

View File

@ -11,6 +11,7 @@
- [Deny-by-default lints](lints/listing/deny-by-default.md)
- [Codegen options](codegen-options/index.md)
- [JSON Output](json.md)
- [Platform Support](platform-support.md)
- [Targets](targets/index.md)
- [Built-in Targets](targets/built-in.md)
- [Custom Targets](targets/custom.md)

View File

@ -0,0 +1,223 @@
# Platform Support
<style type="text/css">
td code {
white-space: nowrap;
}
</style>
Support for different platforms are organized into three tiers, each with a
different set of guarantees.
Platforms are identified by their "target triple" which is the string to
inform the compiler what kind of output should be produced. The columns in the
tables below have the following meanings:
* std:
* ✓ indicates the full standard library is available.
* \* indicates the target only supports [`no_std`] development.
* ? indicates the standard library support is unknown or a work-in-progress.
* host: A ✓ indicates that `rustc` and `cargo` can run on the host platform.
[`no_std`]: https://rust-embedded.github.io/book/intro/no-std.html
## Tier 1
Tier 1 platforms can be thought of as "guaranteed to work".
Specifically they will each satisfy the following requirements:
* Official binary releases are provided for the platform.
* Automated testing is set up to run tests for the platform.
* Landing changes to the `rust-lang/rust` repository's master branch is gated
on tests passing.
* Documentation for how to use and how to build the platform is available.
target | std | host | notes
-------|-----|------|-------
`i686-pc-windows-gnu` | ✓ | ✓ | 32-bit MinGW (Windows 7+)
`i686-pc-windows-msvc` | ✓ | ✓ | 32-bit MSVC (Windows 7+)
`i686-unknown-linux-gnu` | ✓ | ✓ | 32-bit Linux (kernel 2.6.32+, glibc 2.11+)
`x86_64-apple-darwin` | ✓ | ✓ | 64-bit OSX (10.7+, Lion+)
`x86_64-pc-windows-gnu` | ✓ | ✓ | 64-bit MinGW (Windows 7+)
`x86_64-pc-windows-msvc` | ✓ | ✓ | 64-bit MSVC (Windows 7+)
`x86_64-unknown-linux-gnu` | ✓ | ✓ | 64-bit Linux (kernel 2.6.32+, glibc 2.11+)
## Tier 2
Tier 2 platforms can be thought of as "guaranteed to build". Automated tests
are not run so it's not guaranteed to produce a working build, but platforms
often work to quite a good degree and patches are always welcome!
Specifically, these platforms are required to have each of the following:
* Official binary releases are provided for the platform.
* Automated building is set up, but may not be running tests.
* Landing changes to the `rust-lang/rust` repository's master branch is gated on
platforms **building**. For some platforms only the standard library is
compiled, but for others `rustc` and `cargo` are too.
target | std | host | notes
-------|-----|------|-------
`aarch64-apple-ios` | ✓[^apple] | | ARM64 iOS
`aarch64-fuchsia` | ✓ | | ARM64 Fuchsia
`aarch64-linux-android` | ✓ | | ARM64 Android
`aarch64-pc-windows-msvc` | ✓ | | ARM64 Windows MSVC
`aarch64-unknown-linux-gnu` | ✓ | ✓ | ARM64 Linux (kernel 4.2, glibc 2.17)
`aarch64-unknown-linux-musl` | ✓ | | ARM64 Linux with MUSL
`aarch64-unknown-none` | * | | Bare ARM64, hardfloat
`aarch64-unknown-none-softfloat` | * | | Bare ARM64, softfloat
`arm-linux-androideabi` | ✓ | | ARMv7 Android
`arm-unknown-linux-gnueabi` | ✓ | ✓ | ARMv6 Linux (kernel 3.2, glibc 2.17)
`arm-unknown-linux-gnueabihf` | ✓ | ✓ | ARMv6 Linux, hardfloat (kernel 3.2, glibc 2.17)
`arm-unknown-linux-musleabi` | ✓ | | ARMv6 Linux with MUSL
`arm-unknown-linux-musleabihf` | ✓ | | ARMv6 Linux with MUSL, hardfloat
`armebv7r-none-eabi` | * | | Bare ARMv7-R, Big Endian
`armebv7r-none-eabihf` | * | | Bare ARMv7-R, Big Endian, hardfloat
`armv5te-unknown-linux-gnueabi` | ✓ | | ARMv5TE Linux (kernel 4.4, glibc 2.23)
`armv5te-unknown-linux-musleabi` | ✓ | | ARMv5TE Linux with MUSL
`armv7-linux-androideabi` | ✓ | | ARMv7a Android
`armv7a-none-eabi` | * | | Bare ARMv7-A
`armv7r-none-eabi` | * | | Bare ARMv7-R
`armv7r-none-eabihf` | * | | Bare ARMv7-R, hardfloat
`armv7-unknown-linux-gnueabi` | ✓ | | ARMv7 Linux (kernel 4.15, glibc 2.27)
`armv7-unknown-linux-gnueabihf` | ✓ | ✓ | ARMv7 Linux, hardfloat (kernel 3.2, glibc 2.17)
`armv7-unknown-linux-musleabi` | ✓ | | ARMv7 Linux, MUSL
`armv7-unknown-linux-musleabihf` | ✓ | | ARMv7 Linux with MUSL
`asmjs-unknown-emscripten` | ✓ | | asm.js via Emscripten
`i586-pc-windows-msvc` | ✓ | | 32-bit Windows w/o SSE
`i586-unknown-linux-gnu` | ✓ | | 32-bit Linux w/o SSE (kernel 4.4, glibc 2.23)
`i586-unknown-linux-musl` | ✓ | | 32-bit Linux w/o SSE, MUSL
`i686-linux-android` | ✓ | | 32-bit x86 Android
`i686-unknown-freebsd` | ✓ | ✓ | 32-bit FreeBSD
`i686-unknown-linux-musl` | ✓ | | 32-bit Linux with MUSL
`mips-unknown-linux-gnu` | ✓ | ✓ | MIPS Linux (kernel 4.4, glibc 2.23)
`mips-unknown-linux-musl` | ✓ | | MIPS Linux with MUSL
`mips64-unknown-linux-gnuabi64` | ✓ | ✓ | MIPS64 Linux, n64 ABI (kernel 4.4, glibc 2.23)
`mips64-unknown-linux-muslabi64` | ✓ | | MIPS64 Linux, n64 ABI, MUSL
`mips64el-unknown-linux-gnuabi64` | ✓ | ✓ | MIPS64 (LE) Linux, n64 ABI (kernel 4.4, glibc 2.23)
`mips64el-unknown-linux-muslabi64` | ✓ | | MIPS64 (LE) Linux, n64 ABI, MUSL
`mipsel-unknown-linux-gnu` | ✓ | ✓ | MIPS (LE) Linux (kernel 4.4, glibc 2.23)
`mipsel-unknown-linux-musl` | ✓ | | MIPS (LE) Linux with MUSL
`nvptx64-nvidia-cuda` | ✓ | | --emit=asm generates PTX code that [runs on NVIDIA GPUs]
`powerpc-unknown-linux-gnu` | ✓ | ✓ | PowerPC Linux (kernel 2.6.32, glibc 2.11)
`powerpc64-unknown-linux-gnu` | ✓ | ✓ | PPC64 Linux (kernel 2.6.32, glibc 2.11)
`powerpc64le-unknown-linux-gnu` | ✓ | ✓ | PPC64LE Linux (kernel 3.10, glibc 2.17)
`riscv32i-unknown-none-elf` | * | | Bare RISC-V (RV32I ISA)
`riscv32imac-unknown-none-elf` | * | | Bare RISC-V (RV32IMAC ISA)
`riscv32imc-unknown-none-elf` | * | | Bare RISC-V (RV32IMC ISA)
`riscv64gc-unknown-linux-gnu` | ✓ | ✓ | RISC-V Linux (kernel 4.20, glibc 2.29)
`riscv64gc-unknown-none-elf` | * | | Bare RISC-V (RV64IMAFDC ISA)
`riscv64imac-unknown-none-elf` | * | | Bare RISC-V (RV64IMAC ISA)
`s390x-unknown-linux-gnu` | ✓ | ✓ | S390x Linux (kernel 2.6.32, glibc 2.11)
`sparc64-unknown-linux-gnu` | ✓ | | SPARC Linux (kernel 4.4, glibc 2.23)
`sparcv9-sun-solaris` | ✓ | | SPARC Solaris 10/11, illumos
`thumbv6m-none-eabi` | * | | Bare Cortex-M0, M0+, M1
`thumbv7em-none-eabi` | * | | Bare Cortex-M4, M7
`thumbv7em-none-eabihf` | * | | Bare Cortex-M4F, M7F, FPU, hardfloat
`thumbv7m-none-eabi` | * | | Bare Cortex-M3
`thumbv7neon-linux-androideabi` | ✓ | | Thumb2-mode ARMv7a Android with NEON
`thumbv7neon-unknown-linux-gnueabihf` | ✓ | | Thumb2-mode ARMv7a Linux with NEON (kernel 4.4, glibc 2.23)
`thumbv8m.base-none-eabi` | * | | ARMv8-M Baseline
`thumbv8m.main-none-eabi` | * | | ARMv8-M Mainline
`thumbv8m.main-none-eabihf` | * | | ARMv8-M Baseline, hardfloat
`wasm32-unknown-emscripten` | ✓ | | WebAssembly via Emscripten
`wasm32-unknown-unknown` | ✓ | | WebAssembly
`wasm32-wasi` | ✓ | | WebAssembly with WASI
`x86_64-apple-ios` | ✓[^apple] | | 64-bit x86 iOS
`x86_64-fortanix-unknown-sgx` | ✓ | | [Fortanix ABI] for 64-bit Intel SGX
`x86_64-fuchsia` | ✓ | | 64-bit Fuchsia
`x86_64-linux-android` | ✓ | | 64-bit x86 Android
`x86_64-rumprun-netbsd` | ✓ | | 64-bit NetBSD Rump Kernel
`x86_64-sun-solaris` | ✓ | | 64-bit Solaris 10/11, illumos
`x86_64-unknown-cloudabi` | ✓ | | 64-bit CloudABI
`x86_64-unknown-freebsd` | ✓ | ✓ | 64-bit FreeBSD
`x86_64-unknown-illumos` | ✓ | ✓ | illumos
`x86_64-unknown-linux-gnux32` | ✓ | | 64-bit Linux (x32 ABI) (kernel 4.15, glibc 2.27)
`x86_64-unknown-linux-musl` | ✓ | ✓ | 64-bit Linux with MUSL
`x86_64-unknown-netbsd` | ✓ | ✓ | NetBSD/amd64
`x86_64-unknown-redox` | ✓ | | Redox OS
[Fortanix ABI]: https://edp.fortanix.com/
## Tier 3
Tier 3 platforms are those which the Rust codebase has support for, but which
are not built or tested automatically, and may not work. Official builds are
not available.
target | std | host | notes
-------|-----|------|-------
`aarch64-apple-darwin` | ? | | ARM64 macOS
`aarch64-apple-tvos` | *[^apple] | | ARM64 tvOS
`aarch64-unknown-cloudabi` | ✓ | | ARM64 CloudABI
`aarch64-unknown-freebsd` | ✓ | ✓ | ARM64 FreeBSD
`aarch64-unknown-hermit` | ? | |
`aarch64-unknown-netbsd` | ? | |
`aarch64-unknown-openbsd` | ✓ | ✓ | ARM64 OpenBSD
`aarch64-unknown-redox` | ? | | ARM64 Redox OS
`aarch64-uwp-windows-msvc` | ? | |
`aarch64-wrs-vxworks` | ? | |
`armv4t-unknown-linux-gnueabi` | ? | |
`armv6-unknown-freebsd` | ✓ | ✓ | ARMv6 FreeBSD
`armv6-unknown-netbsd-eabihf` | ? | |
`armv7-apple-ios` | ✓[^apple] | | ARMv7 iOS, Cortex-a8
`armv7-unknown-cloudabi-eabihf` | ✓ | | ARMv7 CloudABI, hardfloat
`armv7-unknown-freebsd` | ✓ | ✓ | ARMv7 FreeBSD
`armv7-unknown-netbsd-eabihf` | ? | |
`armv7-wrs-vxworks-eabihf` | ? | |
`armv7a-none-eabihf` | * | | ARM Cortex-A, hardfloat
`armv7s-apple-ios` | ✓[^apple] | |
`avr-unknown-unknown` | ? | | AVR
`hexagon-unknown-linux-musl` | ? | |
`i386-apple-ios` | ✓[^apple] | | 32-bit x86 iOS
`i686-apple-darwin` | ✓ | ✓ | 32-bit OSX (10.7+, Lion+)
`i686-pc-windows-msvc` | ✓ | | 32-bit Windows XP support
`i686-unknown-cloudabi` | ✓ | | 32-bit CloudABI
`i686-unknown-uefi` | ? | | 32-bit UEFI
`i686-unknown-haiku` | ✓ | ✓ | 32-bit Haiku
`i686-unknown-netbsd` | ✓ | | NetBSD/i386 with SSE2
`i686-unknown-openbsd` | ✓ | ✓ | 32-bit OpenBSD
`i686-uwp-windows-gnu` | ? | |
`i686-uwp-windows-msvc` | ? | |
`i686-wrs-vxworks` | ? | |
`mips-unknown-linux-uclibc` | ✓ | | MIPS Linux with uClibc
`mipsel-unknown-linux-uclibc` | ✓ | | MIPS (LE) Linux with uClibc
`mipsel-sony-psp` | * | | MIPS (LE) Sony PlayStation Portable (PSP)
`mipsisa32r6-unknown-linux-gnu` | ? | |
`mipsisa32r6el-unknown-linux-gnu` | ? | |
`mipsisa64r6-unknown-linux-gnuabi64` | ? | |
`mipsisa64r6el-unknown-linux-gnuabi64` | ? | |
`msp430-none-elf` | * | | 16-bit MSP430 microcontrollers
`powerpc-unknown-linux-gnuspe` | ✓ | | PowerPC SPE Linux
`powerpc-unknown-linux-musl` | ? | |
`powerpc-unknown-netbsd` | ? | |
`powerpc-wrs-vxworks` | ? | |
`powerpc-wrs-vxworks-spe` | ? | |
`powerpc64-unknown-freebsd` | ✓ | ✓ | PPC64 FreeBSD (ELFv1 and ELFv2)
`powerpc64-unknown-linux-musl` | ? | |
`powerpc64-wrs-vxworks` | ? | |
`powerpc64le-unknown-linux-musl` | ? | |
`sparc-unknown-linux-gnu` | ✓ | | 32-bit SPARC Linux
`sparc64-unknown-netbsd` | ✓ | ✓ | NetBSD/sparc64
`sparc64-unknown-openbsd` | ? | |
`thumbv7a-pc-windows-msvc` | ? | |
`thumbv7a-uwp-windows-msvc` | ✓ | |
`thumbv7neon-unknown-linux-musleabihf` | ? | | Thumb2-mode ARMv7a Linux with NEON, MUSL
`thumbv4t-none-eabi` | * | | ARMv4T T32
`x86_64-apple-ios-macabi` | ✓[^apple] | | Apple Catalyst
`x86_64-apple-tvos` | *[^apple] | | x86 64-bit tvOS
`x86_64-linux-kernel` | ? | | Linux kernel modules
`x86_64-pc-solaris` | ? | |
`x86_64-pc-windows-msvc` | ✓ | | 64-bit Windows XP support
`x86_64-unknown-dragonfly` | ✓ | ✓ | 64-bit DragonFlyBSD
`x86_64-unknown-haiku` | ✓ | ✓ | 64-bit Haiku
`x86_64-unknown-hermit` | ? | |
`x86_64-unknown-hermit-kernel` | ? | | HermitCore kernel
`x86_64-unknown-l4re-uclibc` | ? | |
`x86_64-unknown-openbsd` | ✓ | ✓ | 64-bit OpenBSD
`x86_64-unknown-uefi` | ? | |
`x86_64-uwp-windows-gnu` | ✓ | |
`x86_64-uwp-windows-msvc` | ✓ | |
`x86_64-wrs-vxworks` | ? | |
[runs on NVIDIA GPUs]: https://github.com/japaric-archived/nvptx#targets
[^apple]: These targets are only available on macOS.

View File

@ -2,9 +2,14 @@
`rustc` ships with the ability to compile to many targets automatically, we
call these "built-in" targets, and they generally correspond to targets that
the team is supporting directly.
the team is supporting directly. To see the list of built-in targets, you can
run `rustc --print target-list`.
To see the list of built-in targets, you can run `rustc --print target-list`,
or look at [the API
docs](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_target/spec/index.html#modules).
Each module there defines a builder for a particular target.
Typically, a target needs a compiled copy of the Rust standard library to
work. If using [rustup], then check out the documentation on
[Cross-compilation][rustup-cross] on how to download a pre-built standard
library built by the official Rust distributions. Most targets will need a
system linker, and possibly other things.
[rustup]: https://github.com/rust-lang/rustup
[rustup-cross]: https://github.com/rust-lang/rustup#cross-compilation

View File

@ -18,7 +18,15 @@ It can be used to embed handwritten assembly in the assembly output generated by
Generally this should not be necessary, but might be where the required performance or timing
cannot be otherwise achieved. Accessing low level hardware primitives, e.g. in kernel code, may also demand this functionality.
> **Note**: the examples here are given in x86/x86-64 assembly, but ARM, AArch64 and RISC-V are also supported.
> **Note**: the examples here are given in x86/x86-64 assembly, but other architectures are also supported.
Inline assembly is currently supported on the following architectures:
- x86 and x86-64
- ARM
- AArch64
- RISC-V
- NVPTX
- Hexagon
## Basic usage
@ -606,6 +614,10 @@ Some registers cannot be used for input or output operands:
| RISC-V | `gp`, `tp` | These registers are reserved and cannot be used as inputs or outputs. |
| Hexagon | `lr` | This is the link register which cannot be used as an input or output. |
In some cases LLVM will allocate a "reserved register" for `reg` operands even though this register cannot be explicitly specified. Assembly code making use of reserved registers should be careful since `reg` operands may alias with those registers. Reserved registers are:
- The frame pointer on all architectures.
- `r6` on ARM.
## Template modifiers
The placeholders can be augmented by modifiers which are specified after the `:` in the curly braces. These modifiers do not affect register allocation, but change the way operands are formatted when inserted into the template string. Only one modifier is allowed per template placeholder.

View File

@ -611,11 +611,7 @@ macro_rules! which_arena_for_type {
#[macro_export]
macro_rules! declare_arena {
// This macro has to take the same input as
// `impl_arena_allocatable_decoders` which requires a second version of
// each type. We ignore that type until we can fix
// `impl_arena_allocatable_decoders`.
([], [$($a:tt $name:ident: $ty:ty, $_gen_ty:ty;)*], $tcx:lifetime) => {
([], [$($a:tt $name:ident: $ty:ty,)*], $tcx:lifetime) => {
#[derive(Default)]
pub struct Arena<$tcx> {
pub dropless: $crate::DroplessArena,

View File

@ -35,6 +35,7 @@ use rustc_span::source_map::{respan, Spanned};
use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::{Span, DUMMY_SP};
use std::cmp::Ordering;
use std::convert::TryFrom;
use std::fmt;
use std::iter;
@ -52,7 +53,7 @@ mod tests;
/// ```
///
/// `'outer` is a label.
#[derive(Clone, RustcEncodable, RustcDecodable, Copy, HashStable_Generic)]
#[derive(Clone, Encodable, Decodable, Copy, HashStable_Generic)]
pub struct Label {
pub ident: Ident,
}
@ -65,7 +66,7 @@ impl fmt::Debug for Label {
/// A "Lifetime" is an annotation of the scope in which variable
/// can be used, e.g. `'a` in `&'a i32`.
#[derive(Clone, RustcEncodable, RustcDecodable, Copy)]
#[derive(Clone, Encodable, Decodable, Copy)]
pub struct Lifetime {
pub id: NodeId,
pub ident: Ident,
@ -89,7 +90,7 @@ impl fmt::Display for Lifetime {
/// along with a bunch of supporting information.
///
/// E.g., `std::cmp::PartialEq`.
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
#[derive(Clone, Encodable, Decodable, Debug)]
pub struct Path {
pub span: Span,
/// The segments in the path: the things separated by `::`.
@ -127,7 +128,7 @@ impl Path {
/// A segment of a path: an identifier, an optional lifetime, and a set of types.
///
/// E.g., `std`, `String` or `Box<T>`.
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
#[derive(Clone, Encodable, Decodable, Debug)]
pub struct PathSegment {
/// The identifier portion of this path segment.
pub ident: Ident,
@ -155,7 +156,7 @@ impl PathSegment {
/// The arguments of a path segment.
///
/// E.g., `<A, B>` as in `Foo<A, B>` or `(A, B)` as in `Foo(A, B)`.
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
#[derive(Clone, Encodable, Decodable, Debug)]
pub enum GenericArgs {
/// The `<'a, A, B, C>` in `foo::bar::baz::<'a, A, B, C>`.
AngleBracketed(AngleBracketedArgs),
@ -187,7 +188,7 @@ impl GenericArgs {
}
/// Concrete argument in the sequence of generic args.
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
#[derive(Clone, Encodable, Decodable, Debug)]
pub enum GenericArg {
/// `'a` in `Foo<'a>`
Lifetime(Lifetime),
@ -208,7 +209,7 @@ impl GenericArg {
}
/// A path like `Foo<'a, T>`.
#[derive(Clone, RustcEncodable, RustcDecodable, Debug, Default)]
#[derive(Clone, Encodable, Decodable, Debug, Default)]
pub struct AngleBracketedArgs {
/// The overall span.
pub span: Span,
@ -218,7 +219,7 @@ pub struct AngleBracketedArgs {
/// Either an argument for a parameter e.g., `'a`, `Vec<u8>`, `0`,
/// or a constraint on an associated item, e.g., `Item = String` or `Item: Bound`.
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
#[derive(Clone, Encodable, Decodable, Debug)]
pub enum AngleBracketedArg {
/// Argument for a generic parameter.
Arg(GenericArg),
@ -239,7 +240,7 @@ impl Into<Option<P<GenericArgs>>> for ParenthesizedArgs {
}
/// A path like `Foo(A, B) -> C`.
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
#[derive(Clone, Encodable, Decodable, Debug)]
pub struct ParenthesizedArgs {
/// Overall span
pub span: Span,
@ -268,7 +269,7 @@ pub use crate::node_id::{NodeId, CRATE_NODE_ID, DUMMY_NODE_ID};
/// A modifier on a bound, e.g., `?Sized` or `?const Trait`.
///
/// Negative bounds should also be handled here.
#[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Debug)]
#[derive(Copy, Clone, PartialEq, Eq, Encodable, Decodable, Debug)]
pub enum TraitBoundModifier {
/// No modifiers
None,
@ -289,7 +290,7 @@ pub enum TraitBoundModifier {
/// `typeck::collect::compute_bounds` matches these against
/// the "special" built-in traits (see `middle::lang_items`) and
/// detects `Copy`, `Send` and `Sync`.
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
#[derive(Clone, Encodable, Decodable, Debug)]
pub enum GenericBound {
Trait(PolyTraitRef, TraitBoundModifier),
Outlives(Lifetime),
@ -309,24 +310,54 @@ pub type GenericBounds = Vec<GenericBound>;
/// Specifies the enforced ordering for generic parameters. In the future,
/// if we wanted to relax this order, we could override `PartialEq` and
/// `PartialOrd`, to allow the kinds to be unordered.
#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy)]
#[derive(Hash, Clone, Copy)]
pub enum ParamKindOrd {
Lifetime,
Type,
Const,
// `unordered` is only `true` if `sess.has_features().const_generics`
// is active. Specifically, if it's only `min_const_generics`, it will still require
// ordering consts after types.
Const { unordered: bool },
}
impl Ord for ParamKindOrd {
fn cmp(&self, other: &Self) -> Ordering {
use ParamKindOrd::*;
let to_int = |v| match v {
Lifetime => 0,
Type | Const { unordered: true } => 1,
// technically both consts should be ordered equally,
// but only one is ever encountered at a time, so this is
// fine.
Const { unordered: false } => 2,
};
to_int(*self).cmp(&to_int(*other))
}
}
impl PartialOrd for ParamKindOrd {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl PartialEq for ParamKindOrd {
fn eq(&self, other: &Self) -> bool {
self.cmp(other) == Ordering::Equal
}
}
impl Eq for ParamKindOrd {}
impl fmt::Display for ParamKindOrd {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
ParamKindOrd::Lifetime => "lifetime".fmt(f),
ParamKindOrd::Type => "type".fmt(f),
ParamKindOrd::Const => "const".fmt(f),
ParamKindOrd::Const { .. } => "const".fmt(f),
}
}
}
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
#[derive(Clone, Encodable, Decodable, Debug)]
pub enum GenericParamKind {
/// A lifetime definition (e.g., `'a: 'b + 'c + 'd`).
Lifetime,
@ -340,7 +371,7 @@ pub enum GenericParamKind {
},
}
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
#[derive(Clone, Encodable, Decodable, Debug)]
pub struct GenericParam {
pub id: NodeId,
pub ident: Ident,
@ -352,7 +383,7 @@ pub struct GenericParam {
/// Represents lifetime, type and const parameters attached to a declaration of
/// a function, enum, trait, etc.
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
#[derive(Clone, Encodable, Decodable, Debug)]
pub struct Generics {
pub params: Vec<GenericParam>,
pub where_clause: WhereClause,
@ -375,7 +406,7 @@ impl Default for Generics {
}
/// A where-clause in a definition.
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
#[derive(Clone, Encodable, Decodable, Debug)]
pub struct WhereClause {
/// `true` if we ate a `where` token: this can happen
/// if we parsed no predicates (e.g. `struct Foo where {}`).
@ -387,7 +418,7 @@ pub struct WhereClause {
}
/// A single predicate in a where-clause.
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
#[derive(Clone, Encodable, Decodable, Debug)]
pub enum WherePredicate {
/// A type binding (e.g., `for<'c> Foo: Send + Clone + 'c`).
BoundPredicate(WhereBoundPredicate),
@ -410,7 +441,7 @@ impl WherePredicate {
/// A type bound.
///
/// E.g., `for<'c> Foo: Send + Clone + 'c`.
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
#[derive(Clone, Encodable, Decodable, Debug)]
pub struct WhereBoundPredicate {
pub span: Span,
/// Any generics from a `for` binding.
@ -424,7 +455,7 @@ pub struct WhereBoundPredicate {
/// A lifetime predicate.
///
/// E.g., `'a: 'b + 'c`.
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
#[derive(Clone, Encodable, Decodable, Debug)]
pub struct WhereRegionPredicate {
pub span: Span,
pub lifetime: Lifetime,
@ -434,7 +465,7 @@ pub struct WhereRegionPredicate {
/// An equality predicate (unsupported).
///
/// E.g., `T = int`.
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
#[derive(Clone, Encodable, Decodable, Debug)]
pub struct WhereEqPredicate {
pub id: NodeId,
pub span: Span,
@ -442,7 +473,7 @@ pub struct WhereEqPredicate {
pub rhs_ty: P<Ty>,
}
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
#[derive(Clone, Encodable, Decodable, Debug)]
pub struct Crate {
pub module: Mod,
pub attrs: Vec<Attribute>,
@ -459,7 +490,7 @@ pub struct Crate {
/// Possible values inside of compile-time attribute lists.
///
/// E.g., the '..' in `#[name(..)]`.
#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
#[derive(Clone, Encodable, Decodable, Debug, HashStable_Generic)]
pub enum NestedMetaItem {
/// A full MetaItem, for recursive meta items.
MetaItem(MetaItem),
@ -472,7 +503,7 @@ pub enum NestedMetaItem {
/// A spanned compile-time attribute item.
///
/// E.g., `#[test]`, `#[derive(..)]`, `#[rustfmt::skip]` or `#[feature = "foo"]`.
#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
#[derive(Clone, Encodable, Decodable, Debug, HashStable_Generic)]
pub struct MetaItem {
pub path: Path,
pub kind: MetaItemKind,
@ -482,7 +513,7 @@ pub struct MetaItem {
/// A compile-time attribute item.
///
/// E.g., `#[test]`, `#[derive(..)]` or `#[feature = "foo"]`.
#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
#[derive(Clone, Encodable, Decodable, Debug, HashStable_Generic)]
pub enum MetaItemKind {
/// Word meta item.
///
@ -501,7 +532,7 @@ pub enum MetaItemKind {
/// A block (`{ .. }`).
///
/// E.g., `{ .. }` as in `fn foo() { .. }`.
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
#[derive(Clone, Encodable, Decodable, Debug)]
pub struct Block {
/// The statements in the block.
pub stmts: Vec<Stmt>,
@ -514,7 +545,7 @@ pub struct Block {
/// A match pattern.
///
/// Patterns appear in match statements and some other contexts, such as `let` and `if let`.
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
#[derive(Clone, Encodable, Decodable, Debug)]
pub struct Pat {
pub id: NodeId,
pub kind: PatKind,
@ -605,7 +636,7 @@ impl Pat {
/// Patterns like the fields of Foo `{ x, ref y, ref mut z }`
/// are treated the same as` x: x, y: ref y, z: ref mut z`,
/// except is_shorthand is true
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
#[derive(Clone, Encodable, Decodable, Debug)]
pub struct FieldPat {
/// The identifier for the field
pub ident: Ident,
@ -618,19 +649,19 @@ pub struct FieldPat {
pub is_placeholder: bool,
}
#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, Copy)]
#[derive(Clone, PartialEq, Encodable, Decodable, Debug, Copy)]
pub enum BindingMode {
ByRef(Mutability),
ByValue(Mutability),
}
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
#[derive(Clone, Encodable, Decodable, Debug)]
pub enum RangeEnd {
Included(RangeSyntax),
Excluded,
}
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
#[derive(Clone, Encodable, Decodable, Debug)]
pub enum RangeSyntax {
/// `...`
DotDotDot,
@ -638,7 +669,7 @@ pub enum RangeSyntax {
DotDotEq,
}
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
#[derive(Clone, Encodable, Decodable, Debug)]
pub enum PatKind {
/// Represents a wildcard pattern (`_`).
Wild,
@ -705,8 +736,8 @@ pub enum PatKind {
MacCall(MacCall),
}
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable, Debug, Copy)]
#[derive(HashStable_Generic)]
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Copy)]
#[derive(HashStable_Generic, Encodable, Decodable)]
pub enum Mutability {
Mut,
Not,
@ -739,7 +770,7 @@ impl Mutability {
/// The kind of borrow in an `AddrOf` expression,
/// e.g., `&place` or `&raw const place`.
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
#[derive(RustcEncodable, RustcDecodable, HashStable_Generic)]
#[derive(Encodable, Decodable, HashStable_Generic)]
pub enum BorrowKind {
/// A normal borrow, `&$expr` or `&mut $expr`.
/// The resulting type is either `&'a T` or `&'a mut T`
@ -751,7 +782,7 @@ pub enum BorrowKind {
Raw,
}
#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, Copy)]
#[derive(Clone, PartialEq, Encodable, Decodable, Debug, Copy)]
pub enum BinOpKind {
/// The `+` operator (addition)
Add,
@ -850,7 +881,7 @@ pub type BinOp = Spanned<BinOpKind>;
/// Unary operator.
///
/// Note that `&data` is not an operator, it's an `AddrOf` expression.
#[derive(Clone, RustcEncodable, RustcDecodable, Debug, Copy)]
#[derive(Clone, Encodable, Decodable, Debug, Copy)]
pub enum UnOp {
/// The `*` operator for dereferencing
Deref,
@ -879,7 +910,7 @@ impl UnOp {
}
/// A statement
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
#[derive(Clone, Encodable, Decodable, Debug)]
pub struct Stmt {
pub id: NodeId,
pub kind: StmtKind,
@ -913,7 +944,7 @@ impl Stmt {
}
}
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
#[derive(Clone, Encodable, Decodable, Debug)]
pub enum StmtKind {
/// A local (let) binding.
Local(P<Local>),
@ -929,7 +960,7 @@ pub enum StmtKind {
MacCall(P<(MacCall, MacStmtStyle, AttrVec)>),
}
#[derive(Clone, Copy, PartialEq, RustcEncodable, RustcDecodable, Debug)]
#[derive(Clone, Copy, PartialEq, Encodable, Decodable, Debug)]
pub enum MacStmtStyle {
/// The macro statement had a trailing semicolon (e.g., `foo! { ... };`
/// `foo!(...);`, `foo![...];`).
@ -943,7 +974,7 @@ pub enum MacStmtStyle {
}
/// Local represents a `let` statement, e.g., `let <pat>:<ty> = <expr>;`.
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
#[derive(Clone, Encodable, Decodable, Debug)]
pub struct Local {
pub id: NodeId,
pub pat: P<Pat>,
@ -964,7 +995,7 @@ pub struct Local {
/// _ => { println!("no match!") },
/// }
/// ```
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
#[derive(Clone, Encodable, Decodable, Debug)]
pub struct Arm {
pub attrs: Vec<Attribute>,
/// Match arm pattern, e.g. `10` in `match foo { 10 => {}, _ => {} }`
@ -979,7 +1010,7 @@ pub struct Arm {
}
/// Access of a named (e.g., `obj.foo`) or unnamed (e.g., `obj.0`) struct field.
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
#[derive(Clone, Encodable, Decodable, Debug)]
pub struct Field {
pub attrs: AttrVec,
pub id: NodeId,
@ -990,13 +1021,13 @@ pub struct Field {
pub is_placeholder: bool,
}
#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, Copy)]
#[derive(Clone, PartialEq, Encodable, Decodable, Debug, Copy)]
pub enum BlockCheckMode {
Default,
Unsafe(UnsafeSource),
}
#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, Copy)]
#[derive(Clone, PartialEq, Encodable, Decodable, Debug, Copy)]
pub enum UnsafeSource {
CompilerGenerated,
UserProvided,
@ -1007,14 +1038,14 @@ pub enum UnsafeSource {
/// These are usually found nested inside types (e.g., array lengths)
/// or expressions (e.g., repeat counts), and also used to define
/// explicit discriminant values for enum variants.
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
#[derive(Clone, Encodable, Decodable, Debug)]
pub struct AnonConst {
pub id: NodeId,
pub value: P<Expr>,
}
/// An expression.
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
#[derive(Clone, Encodable, Decodable, Debug)]
pub struct Expr {
pub id: NodeId,
pub kind: ExprKind,
@ -1173,7 +1204,7 @@ impl Expr {
}
/// Limit types of a range (inclusive or exclusive)
#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, Debug)]
#[derive(Copy, Clone, PartialEq, Encodable, Decodable, Debug)]
pub enum RangeLimits {
/// Inclusive at the beginning, exclusive at the end
HalfOpen,
@ -1181,7 +1212,7 @@ pub enum RangeLimits {
Closed,
}
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
#[derive(Clone, Encodable, Decodable, Debug)]
pub enum ExprKind {
/// A `box x` expression.
Box(P<Expr>),
@ -1338,7 +1369,7 @@ pub enum ExprKind {
/// ^~~~~ ^
/// ty position = 0
/// ```
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
#[derive(Clone, Encodable, Decodable, Debug)]
pub struct QSelf {
pub ty: P<Ty>,
@ -1350,7 +1381,7 @@ pub struct QSelf {
}
/// A capture clause used in closures and `async` blocks.
#[derive(Clone, Copy, PartialEq, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
#[derive(Clone, Copy, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)]
pub enum CaptureBy {
/// `move |x| y + x`.
Value,
@ -1360,7 +1391,7 @@ pub enum CaptureBy {
/// The movability of a generator / closure literal:
/// whether a generator contains self-references, causing it to be `!Unpin`.
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable, Debug, Copy)]
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Encodable, Decodable, Debug, Copy)]
#[derive(HashStable_Generic)]
pub enum Movability {
/// May contain self-references, `!Unpin`.
@ -1371,7 +1402,7 @@ pub enum Movability {
/// Represents a macro invocation. The `path` indicates which macro
/// is being invoked, and the `args` are arguments passed to it.
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
#[derive(Clone, Encodable, Decodable, Debug)]
pub struct MacCall {
pub path: Path,
pub args: P<MacArgs>,
@ -1385,7 +1416,7 @@ impl MacCall {
}
/// Arguments passed to an attribute or a function-like macro.
#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
#[derive(Clone, Encodable, Decodable, Debug, HashStable_Generic)]
pub enum MacArgs {
/// No arguments - `#[attr]`.
Empty,
@ -1446,7 +1477,7 @@ impl MacArgs {
}
}
#[derive(Copy, Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
#[derive(Copy, Clone, PartialEq, Eq, Encodable, Decodable, Debug, HashStable_Generic)]
pub enum MacDelimiter {
Parenthesis,
Bracket,
@ -1473,14 +1504,14 @@ impl MacDelimiter {
}
/// Represents a macro definition.
#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
#[derive(Clone, Encodable, Decodable, Debug, HashStable_Generic)]
pub struct MacroDef {
pub body: P<MacArgs>,
/// `true` if macro was defined with `macro_rules`.
pub macro_rules: bool,
}
#[derive(Clone, RustcEncodable, RustcDecodable, Debug, Copy, Hash, Eq, PartialEq)]
#[derive(Clone, Encodable, Decodable, Debug, Copy, Hash, Eq, PartialEq)]
#[derive(HashStable_Generic)]
pub enum StrStyle {
/// A regular string, like `"foo"`.
@ -1492,7 +1523,7 @@ pub enum StrStyle {
}
/// An AST literal.
#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
#[derive(Clone, Encodable, Decodable, Debug, HashStable_Generic)]
pub struct Lit {
/// The original literal token as written in source code.
pub token: token::Lit,
@ -1504,7 +1535,7 @@ pub struct Lit {
}
/// Same as `Lit`, but restricted to string literals.
#[derive(Clone, Copy, RustcEncodable, RustcDecodable, Debug)]
#[derive(Clone, Copy, Encodable, Decodable, Debug)]
pub struct StrLit {
/// The original literal token as written in source code.
pub style: StrStyle,
@ -1531,7 +1562,7 @@ impl StrLit {
}
/// Type of the integer literal based on provided suffix.
#[derive(Clone, Copy, RustcEncodable, RustcDecodable, Debug, Hash, Eq, PartialEq)]
#[derive(Clone, Copy, Encodable, Decodable, Debug, Hash, Eq, PartialEq)]
#[derive(HashStable_Generic)]
pub enum LitIntType {
/// e.g. `42_i32`.
@ -1543,7 +1574,7 @@ pub enum LitIntType {
}
/// Type of the float literal based on provided suffix.
#[derive(Clone, Copy, RustcEncodable, RustcDecodable, Debug, Hash, Eq, PartialEq)]
#[derive(Clone, Copy, Encodable, Decodable, Debug, Hash, Eq, PartialEq)]
#[derive(HashStable_Generic)]
pub enum LitFloatType {
/// A float literal with a suffix (`1f32` or `1E10f32`).
@ -1555,7 +1586,7 @@ pub enum LitFloatType {
/// Literal kind.
///
/// E.g., `"foo"`, `42`, `12.34`, or `bool`.
#[derive(Clone, RustcEncodable, RustcDecodable, Debug, Hash, Eq, PartialEq, HashStable_Generic)]
#[derive(Clone, Encodable, Decodable, Debug, Hash, Eq, PartialEq, HashStable_Generic)]
pub enum LitKind {
/// A string literal (`"foo"`).
Str(Symbol, StrStyle),
@ -1627,7 +1658,7 @@ impl LitKind {
// N.B., If you change this, you'll probably want to change the corresponding
// type structure in `middle/ty.rs` as well.
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
#[derive(Clone, Encodable, Decodable, Debug)]
pub struct MutTy {
pub ty: P<Ty>,
pub mutbl: Mutability,
@ -1635,14 +1666,14 @@ pub struct MutTy {
/// Represents a function's signature in a trait declaration,
/// trait implementation, or free function.
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
#[derive(Clone, Encodable, Decodable, Debug)]
pub struct FnSig {
pub header: FnHeader,
pub decl: P<FnDecl>,
}
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable, Debug)]
#[derive(HashStable_Generic)]
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
#[derive(Encodable, Decodable, HashStable_Generic)]
pub enum FloatTy {
F32,
F64,
@ -1671,8 +1702,8 @@ impl FloatTy {
}
}
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable, Debug)]
#[derive(HashStable_Generic)]
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
#[derive(Encodable, Decodable, HashStable_Generic)]
pub enum IntTy {
Isize,
I8,
@ -1736,8 +1767,8 @@ impl IntTy {
}
}
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable, Copy, Debug)]
#[derive(HashStable_Generic)]
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Copy, Debug)]
#[derive(Encodable, Decodable, HashStable_Generic)]
pub enum UintTy {
Usize,
U8,
@ -1800,7 +1831,7 @@ impl UintTy {
/// A constraint on an associated type (e.g., `A = Bar` in `Foo<A = Bar>` or
/// `A: TraitA + TraitB` in `Foo<A: TraitA + TraitB>`).
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
#[derive(Clone, Encodable, Decodable, Debug)]
pub struct AssocTyConstraint {
pub id: NodeId,
pub ident: Ident,
@ -1809,7 +1840,7 @@ pub struct AssocTyConstraint {
}
/// The kinds of an `AssocTyConstraint`.
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
#[derive(Clone, Encodable, Decodable, Debug)]
pub enum AssocTyConstraintKind {
/// E.g., `A = Bar` in `Foo<A = Bar>`.
Equality { ty: P<Ty> },
@ -1817,14 +1848,14 @@ pub enum AssocTyConstraintKind {
Bound { bounds: GenericBounds },
}
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
#[derive(Clone, Encodable, Decodable, Debug)]
pub struct Ty {
pub id: NodeId,
pub kind: TyKind,
pub span: Span,
}
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
#[derive(Clone, Encodable, Decodable, Debug)]
pub struct BareFnTy {
pub unsafety: Unsafe,
pub ext: Extern,
@ -1833,7 +1864,7 @@ pub struct BareFnTy {
}
/// The various kinds of type recognized by the compiler.
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
#[derive(Clone, Encodable, Decodable, Debug)]
pub enum TyKind {
/// A variable-length slice (`[T]`).
Slice(P<Ty>),
@ -1892,7 +1923,7 @@ impl TyKind {
}
/// Syntax used to declare a trait object.
#[derive(Clone, Copy, PartialEq, RustcEncodable, RustcDecodable, Debug)]
#[derive(Clone, Copy, PartialEq, Encodable, Decodable, Debug)]
pub enum TraitObjectSyntax {
Dyn,
None,
@ -1901,14 +1932,14 @@ pub enum TraitObjectSyntax {
/// Inline assembly operand explicit register or register class.
///
/// E.g., `"eax"` as in `asm!("mov eax, 2", out("eax") result)`.
#[derive(Clone, Copy, RustcEncodable, RustcDecodable, Debug)]
#[derive(Clone, Copy, Encodable, Decodable, Debug)]
pub enum InlineAsmRegOrRegClass {
Reg(Symbol),
RegClass(Symbol),
}
bitflags::bitflags! {
#[derive(RustcEncodable, RustcDecodable, HashStable_Generic)]
#[derive(Encodable, Decodable, HashStable_Generic)]
pub struct InlineAsmOptions: u8 {
const PURE = 1 << 0;
const NOMEM = 1 << 1;
@ -1920,7 +1951,7 @@ bitflags::bitflags! {
}
}
#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
#[derive(Clone, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)]
pub enum InlineAsmTemplatePiece {
String(String),
Placeholder { operand_idx: usize, modifier: Option<char>, span: Span },
@ -1964,7 +1995,7 @@ impl InlineAsmTemplatePiece {
/// Inline assembly operand.
///
/// E.g., `out("eax") result` as in `asm!("mov eax, 2", out("eax") result)`.
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
#[derive(Clone, Encodable, Decodable, Debug)]
pub enum InlineAsmOperand {
In {
reg: InlineAsmRegOrRegClass,
@ -1997,7 +2028,7 @@ pub enum InlineAsmOperand {
/// Inline assembly.
///
/// E.g., `asm!("NOP");`.
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
#[derive(Clone, Encodable, Decodable, Debug)]
pub struct InlineAsm {
pub template: Vec<InlineAsmTemplatePiece>,
pub operands: Vec<(InlineAsmOperand, Span)>,
@ -2008,7 +2039,7 @@ pub struct InlineAsm {
/// Inline assembly dialect.
///
/// E.g., `"intel"` as in `llvm_asm!("mov eax, 2" : "={eax}"(result) : : : "intel")`.
#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, Copy, HashStable_Generic)]
#[derive(Clone, PartialEq, Encodable, Decodable, Debug, Copy, HashStable_Generic)]
pub enum LlvmAsmDialect {
Att,
Intel,
@ -2017,7 +2048,7 @@ pub enum LlvmAsmDialect {
/// LLVM-style inline assembly.
///
/// E.g., `"={eax}"(result)` as in `llvm_asm!("mov eax, 2" : "={eax}"(result) : : : "intel")`.
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
#[derive(Clone, Encodable, Decodable, Debug)]
pub struct LlvmInlineAsmOutput {
pub constraint: Symbol,
pub expr: P<Expr>,
@ -2028,7 +2059,7 @@ pub struct LlvmInlineAsmOutput {
/// LLVM-style inline assembly.
///
/// E.g., `llvm_asm!("NOP");`.
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
#[derive(Clone, Encodable, Decodable, Debug)]
pub struct LlvmInlineAsm {
pub asm: Symbol,
pub asm_str_style: StrStyle,
@ -2043,7 +2074,7 @@ pub struct LlvmInlineAsm {
/// A parameter in a function header.
///
/// E.g., `bar: usize` as in `fn foo(bar: usize)`.
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
#[derive(Clone, Encodable, Decodable, Debug)]
pub struct Param {
pub attrs: AttrVec,
pub ty: P<Ty>,
@ -2056,7 +2087,7 @@ pub struct Param {
/// Alternative representation for `Arg`s describing `self` parameter of methods.
///
/// E.g., `&mut self` as in `fn foo(&mut self)`.
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
#[derive(Clone, Encodable, Decodable, Debug)]
pub enum SelfKind {
/// `self`, `mut self`
Value(Mutability),
@ -2134,7 +2165,7 @@ impl Param {
///
/// Please note that it's different from `FnHeader` structure
/// which contains metadata about function safety, asyncness, constness and ABI.
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
#[derive(Clone, Encodable, Decodable, Debug)]
pub struct FnDecl {
pub inputs: Vec<Param>,
pub output: FnRetTy,
@ -2156,20 +2187,20 @@ impl FnDecl {
}
/// Is the trait definition an auto trait?
#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
#[derive(Copy, Clone, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)]
pub enum IsAuto {
Yes,
No,
}
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable, Debug)]
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Encodable, Decodable, Debug)]
#[derive(HashStable_Generic)]
pub enum Unsafe {
Yes(Span),
No,
}
#[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug)]
#[derive(Copy, Clone, Encodable, Decodable, Debug)]
pub enum Async {
Yes { span: Span, closure_id: NodeId, return_impl_trait_id: NodeId },
No,
@ -2189,7 +2220,7 @@ impl Async {
}
}
#[derive(Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, Debug)]
#[derive(Copy, Clone, PartialEq, Eq, Hash, Encodable, Decodable, Debug)]
#[derive(HashStable_Generic)]
pub enum Const {
Yes(Span),
@ -2198,13 +2229,13 @@ pub enum Const {
/// Item defaultness.
/// For details see the [RFC #2532](https://github.com/rust-lang/rfcs/pull/2532).
#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
#[derive(Copy, Clone, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)]
pub enum Defaultness {
Default(Span),
Final,
}
#[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, HashStable_Generic)]
#[derive(Copy, Clone, PartialEq, Encodable, Decodable, HashStable_Generic)]
pub enum ImplPolarity {
/// `impl Trait for Type`
Positive,
@ -2221,7 +2252,7 @@ impl fmt::Debug for ImplPolarity {
}
}
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
#[derive(Clone, Encodable, Decodable, Debug)]
pub enum FnRetTy {
/// Returns type is not specified.
///
@ -2244,7 +2275,7 @@ impl FnRetTy {
/// Module declaration.
///
/// E.g., `mod foo;` or `mod foo { .. }`.
#[derive(Clone, RustcEncodable, RustcDecodable, Debug, Default)]
#[derive(Clone, Encodable, Decodable, Debug, Default)]
pub struct Mod {
/// A span from the first token past `{` to the last token until `}`.
/// For `mod foo;`, the inner span ranges from the first token
@ -2258,7 +2289,7 @@ pub struct Mod {
/// Foreign module declaration.
///
/// E.g., `extern { .. }` or `extern C { .. }`.
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
#[derive(Clone, Encodable, Decodable, Debug)]
pub struct ForeignMod {
pub abi: Option<StrLit>,
pub items: Vec<P<ForeignItem>>,
@ -2267,17 +2298,17 @@ pub struct ForeignMod {
/// Global inline assembly.
///
/// Also known as "module-level assembly" or "file-scoped assembly".
#[derive(Clone, RustcEncodable, RustcDecodable, Debug, Copy)]
#[derive(Clone, Encodable, Decodable, Debug, Copy)]
pub struct GlobalAsm {
pub asm: Symbol,
}
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
#[derive(Clone, Encodable, Decodable, Debug)]
pub struct EnumDef {
pub variants: Vec<Variant>,
}
/// Enum variant.
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
#[derive(Clone, Encodable, Decodable, Debug)]
pub struct Variant {
/// Attributes of the variant.
pub attrs: Vec<Attribute>,
@ -2299,7 +2330,7 @@ pub struct Variant {
}
/// Part of `use` item to the right of its prefix.
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
#[derive(Clone, Encodable, Decodable, Debug)]
pub enum UseTreeKind {
/// `use prefix` or `use prefix as rename`
///
@ -2314,7 +2345,7 @@ pub enum UseTreeKind {
/// A tree of paths sharing common prefixes.
/// Used in `use` items both at top-level and inside of braces in import groups.
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
#[derive(Clone, Encodable, Decodable, Debug)]
pub struct UseTree {
pub prefix: Path,
pub kind: UseTreeKind,
@ -2336,7 +2367,7 @@ impl UseTree {
/// Distinguishes between `Attribute`s that decorate items and Attributes that
/// are contained as statements within items. These two cases need to be
/// distinguished for pretty-printing.
#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, Copy, HashStable_Generic)]
#[derive(Clone, PartialEq, Encodable, Decodable, Debug, Copy, HashStable_Generic)]
pub enum AttrStyle {
Outer,
Inner,
@ -2349,19 +2380,19 @@ rustc_index::newtype_index! {
}
}
impl rustc_serialize::Encodable for AttrId {
fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
impl<S: Encoder> rustc_serialize::Encodable<S> for AttrId {
fn encode(&self, s: &mut S) -> Result<(), S::Error> {
s.emit_unit()
}
}
impl rustc_serialize::Decodable for AttrId {
fn decode<D: Decoder>(d: &mut D) -> Result<AttrId, D::Error> {
impl<D: Decoder> rustc_serialize::Decodable<D> for AttrId {
fn decode(d: &mut D) -> Result<AttrId, D::Error> {
d.read_nil().map(|_| crate::attr::mk_attr_id())
}
}
#[derive(Clone, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
#[derive(Clone, Encodable, Decodable, Debug, HashStable_Generic)]
pub struct AttrItem {
pub path: Path,
pub args: MacArgs,
@ -2371,7 +2402,7 @@ pub struct AttrItem {
pub type AttrVec = ThinVec<Attribute>;
/// Metadata associated with an item.
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
#[derive(Clone, Encodable, Decodable, Debug)]
pub struct Attribute {
pub kind: AttrKind,
pub id: AttrId,
@ -2381,7 +2412,7 @@ pub struct Attribute {
pub span: Span,
}
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
#[derive(Clone, Encodable, Decodable, Debug)]
pub enum AttrKind {
/// A normal attribute.
Normal(AttrItem),
@ -2398,13 +2429,13 @@ pub enum AttrKind {
/// that the `ref_id` is for. The `impl_id` maps to the "self type" of this impl.
/// If this impl is an `ItemKind::Impl`, the `impl_id` is redundant (it could be the
/// same as the impl's `NodeId`).
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
#[derive(Clone, Encodable, Decodable, Debug)]
pub struct TraitRef {
pub path: Path,
pub ref_id: NodeId,
}
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
#[derive(Clone, Encodable, Decodable, Debug)]
pub struct PolyTraitRef {
/// The `'a` in `<'a> Foo<&'a T>`.
pub bound_generic_params: Vec<GenericParam>,
@ -2425,7 +2456,7 @@ impl PolyTraitRef {
}
}
#[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
#[derive(Copy, Clone, Encodable, Decodable, Debug, HashStable_Generic)]
pub enum CrateSugar {
/// Source is `pub(crate)`.
PubCrate,
@ -2436,7 +2467,7 @@ pub enum CrateSugar {
pub type Visibility = Spanned<VisibilityKind>;
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
#[derive(Clone, Encodable, Decodable, Debug)]
pub enum VisibilityKind {
Public,
Crate(CrateSugar),
@ -2453,7 +2484,7 @@ impl VisibilityKind {
/// Field of a struct.
///
/// E.g., `bar: usize` as in `struct Foo { bar: usize }`.
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
#[derive(Clone, Encodable, Decodable, Debug)]
pub struct StructField {
pub attrs: Vec<Attribute>,
pub id: NodeId,
@ -2466,7 +2497,7 @@ pub struct StructField {
}
/// Fields and constructor ids of enum variants and structs.
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
#[derive(Clone, Encodable, Decodable, Debug)]
pub enum VariantData {
/// Struct variant.
///
@ -2501,7 +2532,7 @@ impl VariantData {
}
/// An item definition.
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
#[derive(Clone, Encodable, Decodable, Debug)]
pub struct Item<K = ItemKind> {
pub attrs: Vec<Attribute>,
pub id: NodeId,
@ -2538,7 +2569,7 @@ impl<K: Into<ItemKind>> Item<K> {
}
/// `extern` qualifier on a function item or function type.
#[derive(Clone, Copy, RustcEncodable, RustcDecodable, Debug)]
#[derive(Clone, Copy, Encodable, Decodable, Debug)]
pub enum Extern {
None,
Implicit,
@ -2555,7 +2586,7 @@ impl Extern {
///
/// All the information between the visibility and the name of the function is
/// included in this struct (e.g., `async unsafe fn` or `const extern "C" fn`).
#[derive(Clone, Copy, RustcEncodable, RustcDecodable, Debug)]
#[derive(Clone, Copy, Encodable, Decodable, Debug)]
pub struct FnHeader {
pub unsafety: Unsafe,
pub asyncness: Async,
@ -2585,7 +2616,7 @@ impl Default for FnHeader {
}
}
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
#[derive(Clone, Encodable, Decodable, Debug)]
pub enum ItemKind {
/// An `extern crate` item, with the optional *original* crate name if the crate was renamed.
///
@ -2724,7 +2755,7 @@ pub type AssocItem = Item<AssocItemKind>;
/// In an implementation, all items must be provided.
/// The `Option`s below denote the bodies, where `Some(_)`
/// means "provided" and conversely `None` means "required".
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
#[derive(Clone, Encodable, Decodable, Debug)]
pub enum AssocItemKind {
/// An associated constant, `const $ident: $ty $def?;` where `def ::= "=" $expr? ;`.
/// If `def` is parsed, then the constant is provided, and otherwise required.
@ -2772,7 +2803,7 @@ impl TryFrom<ItemKind> for AssocItemKind {
}
/// An item in `extern` block.
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
#[derive(Clone, Encodable, Decodable, Debug)]
pub enum ForeignItemKind {
/// A foreign static item (`static FOO: u8`).
Static(P<Ty>, Mutability, Option<P<Expr>>),

View File

@ -3,6 +3,9 @@ use super::*;
// Are ASTs encodable?
#[test]
fn check_asts_encodable() {
fn assert_encodable<T: rustc_serialize::Encodable>() {}
fn assert_encodable<
T: for<'a> rustc_serialize::Encodable<rustc_serialize::json::Encoder<'a>>,
>() {
}
assert_encodable::<Crate>();
}

View File

@ -9,7 +9,7 @@ use std::fmt;
/// Hash value constructed out of all the `-C metadata` arguments passed to the
/// compiler. Together with the crate-name forms a unique global identifier for
/// the crate.
#[derive(Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Clone, Copy, RustcEncodable, RustcDecodable)]
#[derive(Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Clone, Copy, Encodable, Decodable)]
pub struct CrateDisambiguator(Fingerprint);
impl CrateDisambiguator {

View File

@ -18,8 +18,7 @@
#![feature(unicode_internals)]
#![recursion_limit = "256"]
// FIXME(#56935): Work around ICEs during cross-compilation.
#[allow(unused)]
#[macro_use]
extern crate rustc_macros;
#[macro_export]

View File

@ -1,10 +1,8 @@
use rustc_serialize::{Decoder, Encoder};
use rustc_span::ExpnId;
use std::fmt;
rustc_index::newtype_index! {
pub struct NodeId {
ENCODABLE = custom
DEBUG_FORMAT = "NodeId({})"
}
}
@ -34,15 +32,3 @@ impl fmt::Display for NodeId {
fmt::Display::fmt(&self.as_u32(), f)
}
}
impl rustc_serialize::UseSpecializedEncodable for NodeId {
fn default_encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
s.emit_u32(self.as_u32())
}
}
impl rustc_serialize::UseSpecializedDecodable for NodeId {
fn default_decode<D: Decoder>(d: &mut D) -> Result<NodeId, D::Error> {
d.read_u32().map(NodeId::from_u32)
}
}

View File

@ -114,14 +114,14 @@ impl<T> fmt::Pointer for P<T> {
}
}
impl<T: 'static + Decodable> Decodable for P<T> {
fn decode<D: Decoder>(d: &mut D) -> Result<P<T>, D::Error> {
impl<D: Decoder, T: 'static + Decodable<D>> Decodable<D> for P<T> {
fn decode(d: &mut D) -> Result<P<T>, D::Error> {
Decodable::decode(d).map(P)
}
}
impl<T: Encodable> Encodable for P<T> {
fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
impl<S: Encoder, T: Encodable<S>> Encodable<S> for P<T> {
fn encode(&self, s: &mut S) -> Result<(), S::Error> {
(**self).encode(s)
}
}
@ -197,14 +197,14 @@ impl<'a, T> IntoIterator for &'a P<[T]> {
}
}
impl<T: Encodable> Encodable for P<[T]> {
fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
impl<S: Encoder, T: Encodable<S>> Encodable<S> for P<[T]> {
fn encode(&self, s: &mut S) -> Result<(), S::Error> {
Encodable::encode(&**self, s)
}
}
impl<T: Decodable> Decodable for P<[T]> {
fn decode<D: Decoder>(d: &mut D) -> Result<P<[T]>, D::Error> {
impl<D: Decoder, T: Decodable<D>> Decodable<D> for P<[T]> {
fn decode(d: &mut D) -> Result<P<[T]>, D::Error> {
Ok(P::from_vec(Decodable::decode(d)?))
}
}

View File

@ -17,13 +17,13 @@ use rustc_span::{self, Span, DUMMY_SP};
use std::borrow::Cow;
use std::{fmt, mem};
#[derive(Clone, Copy, PartialEq, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
#[derive(Clone, Copy, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)]
pub enum CommentKind {
Line,
Block,
}
#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
#[derive(Clone, PartialEq, Encodable, Decodable, Hash, Debug, Copy)]
#[derive(HashStable_Generic)]
pub enum BinOpToken {
Plus,
@ -39,7 +39,7 @@ pub enum BinOpToken {
}
/// A delimiter token.
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
#[derive(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Debug, Copy)]
#[derive(HashStable_Generic)]
pub enum DelimToken {
/// A round parenthesis (i.e., `(` or `)`).
@ -62,7 +62,7 @@ impl DelimToken {
}
}
#[derive(Clone, Copy, PartialEq, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
#[derive(Clone, Copy, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)]
pub enum LitKind {
Bool, // AST only, must never appear in a `Token`
Byte,
@ -77,7 +77,7 @@ pub enum LitKind {
}
/// A literal token.
#[derive(Clone, Copy, PartialEq, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
#[derive(Clone, Copy, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)]
pub struct Lit {
pub kind: LitKind,
pub symbol: Symbol,
@ -188,7 +188,7 @@ fn ident_can_begin_type(name: Symbol, span: Span, is_raw: bool) -> bool {
.contains(&name)
}
#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
#[derive(Clone, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)]
pub enum TokenKind {
/* Expression-operator symbols. */
Eq,
@ -267,7 +267,7 @@ pub enum TokenKind {
#[cfg(target_arch = "x86_64")]
rustc_data_structures::static_assert_size!(TokenKind, 16);
#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, Debug, HashStable_Generic)]
#[derive(Clone, PartialEq, Encodable, Decodable, Debug, HashStable_Generic)]
pub struct Token {
pub kind: TokenKind,
pub span: Span,
@ -688,7 +688,7 @@ impl PartialEq<TokenKind> for Token {
}
}
#[derive(Clone, RustcEncodable, RustcDecodable)]
#[derive(Clone, Encodable, Decodable)]
/// For interpolation during macro expansion.
pub enum Nonterminal {
NtItem(P<ast::Item>),
@ -711,7 +711,7 @@ pub enum Nonterminal {
#[cfg(target_arch = "x86_64")]
rustc_data_structures::static_assert_size!(Nonterminal, 40);
#[derive(Debug, Copy, Clone, PartialEq, RustcEncodable, RustcDecodable)]
#[derive(Debug, Copy, Clone, PartialEq, Encodable, Decodable)]
pub enum NonterminalKind {
Item,
Block,

View File

@ -35,7 +35,7 @@ use std::{iter, mem};
///
/// The RHS of an MBE macro is the only place `SubstNt`s are substituted.
/// Nothing special happens to misnamed or misplaced `SubstNt`s.
#[derive(Debug, Clone, PartialEq, RustcEncodable, RustcDecodable, HashStable_Generic)]
#[derive(Debug, Clone, PartialEq, Encodable, Decodable, HashStable_Generic)]
pub enum TokenTree {
/// A single token
Token(Token),
@ -124,7 +124,7 @@ where
/// The goal is for procedural macros to work with `TokenStream`s and `TokenTree`s
/// instead of a representation of the abstract syntax tree.
/// Today's `TokenTree`s can still contain AST via `token::Interpolated` for back-compat.
#[derive(Clone, Debug, Default, RustcEncodable, RustcDecodable)]
#[derive(Clone, Debug, Default, Encodable, Decodable)]
pub struct TokenStream(pub Lrc<Vec<TreeAndJoint>>);
pub type TreeAndJoint = (TokenTree, IsJoint);
@ -133,7 +133,7 @@ pub type TreeAndJoint = (TokenTree, IsJoint);
#[cfg(target_arch = "x86_64")]
rustc_data_structures::static_assert_size!(TokenStream, 8);
#[derive(Clone, Copy, Debug, PartialEq, RustcEncodable, RustcDecodable)]
#[derive(Clone, Copy, Debug, PartialEq, Encodable, Decodable)]
pub enum IsJoint {
Joint,
NonJoint,
@ -408,7 +408,7 @@ impl Cursor {
}
}
#[derive(Debug, Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, HashStable_Generic)]
#[derive(Debug, Copy, Clone, PartialEq, Encodable, Decodable, HashStable_Generic)]
pub struct DelimSpan {
pub open: Span,
pub close: Span,

View File

@ -222,7 +222,6 @@ impl AssocOp {
Greater | // `{ 42 } > 3`
GreaterEqual | // `{ 42 } >= 3`
AssignOp(_) | // `{ 42 } +=`
LAnd | // `{ 42 } &&foo`
As | // `{ 42 } as usize`
// Equal | // `{ 42 } == { 42 }` Accepting these here would regress incorrect
// NotEqual | // `{ 42 } != { 42 } struct literals parser recovery.

View File

@ -50,6 +50,13 @@ impl<'a> FnKind<'a> {
}
}
pub fn ident(&self) -> Option<&Ident> {
match self {
FnKind::Fn(_, ident, ..) => Some(ident),
_ => None,
}
}
pub fn decl(&self) -> &'a FnDecl {
match self {
FnKind::Fn(_, _, sig, _, _) => &sig.decl,

View File

@ -773,13 +773,13 @@ fn validate_generic_param_order<'a>(
err.span_suggestion(
span,
&format!(
"reorder the parameters: lifetimes, then types{}",
if sess.features_untracked().const_generics
|| sess.features_untracked().min_const_generics
{
", then consts"
"reorder the parameters: lifetimes{}",
if sess.features_untracked().const_generics {
", then consts and types"
} else if sess.features_untracked().min_const_generics {
", then types, then consts"
} else {
""
", then types"
},
),
ordered_params.clone(),
@ -1156,7 +1156,11 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
GenericParamKind::Type { default: _ } => (ParamKindOrd::Type, ident),
GenericParamKind::Const { ref ty, kw_span: _ } => {
let ty = pprust::ty_to_string(ty);
(ParamKindOrd::Const, Some(format!("const {}: {}", param.ident, ty)))
let unordered = self.session.features_untracked().const_generics;
(
ParamKindOrd::Const { unordered },
Some(format!("const {}: {}", param.ident, ty)),
)
}
};
(kind, Some(&*param.bounds), param.ident.span, ident)

View File

@ -16,6 +16,7 @@ rustc_errors = { path = "../librustc_errors" }
rustc_span = { path = "../librustc_span" }
rustc_data_structures = { path = "../librustc_data_structures" }
rustc_feature = { path = "../librustc_feature" }
rustc_lexer = { path = "../librustc_lexer" }
rustc_macros = { path = "../librustc_macros" }
rustc_session = { path = "../librustc_session" }
rustc_ast = { path = "../librustc_ast" }

View File

@ -20,6 +20,7 @@ enum AttrError {
MultipleItem(String),
UnknownMetaItem(String, &'static [&'static str]),
MissingSince,
NonIdentFeature,
MissingFeature,
MultipleStabilityLevels,
UnsupportedLiteral(&'static str, /* is_bytestr */ bool),
@ -40,6 +41,9 @@ fn handle_errors(sess: &ParseSess, span: Span, error: AttrError) {
AttrError::MissingSince => {
struct_span_err!(diag, span, E0542, "missing 'since'").emit();
}
AttrError::NonIdentFeature => {
struct_span_err!(diag, span, E0546, "'feature' is not an identifier").emit();
}
AttrError::MissingFeature => {
struct_span_err!(diag, span, E0546, "missing 'feature'").emit();
}
@ -63,7 +67,7 @@ fn handle_errors(sess: &ParseSess, span: Span, error: AttrError) {
}
}
#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable)]
#[derive(Clone, PartialEq, Encodable, Decodable)]
pub enum InlineAttr {
None,
Hint,
@ -71,7 +75,7 @@ pub enum InlineAttr {
Never,
}
#[derive(Clone, RustcEncodable, RustcDecodable)]
#[derive(Clone, Encodable, Decodable)]
pub enum OptimizeAttr {
None,
Speed,
@ -126,7 +130,7 @@ pub fn find_unwind_attr(sess: &Session, attrs: &[Attribute]) -> Option<UnwindAtt
///
/// - `#[stable]`
/// - `#[unstable]`
#[derive(RustcEncodable, RustcDecodable, Copy, Clone, Debug, PartialEq, Eq, Hash)]
#[derive(Encodable, Decodable, Copy, Clone, Debug, PartialEq, Eq, Hash)]
#[derive(HashStable_Generic)]
pub struct Stability {
pub level: StabilityLevel,
@ -134,7 +138,7 @@ pub struct Stability {
}
/// Represents the `#[rustc_const_unstable]` and `#[rustc_const_stable]` attributes.
#[derive(RustcEncodable, RustcDecodable, Copy, Clone, Debug, PartialEq, Eq, Hash)]
#[derive(Encodable, Decodable, Copy, Clone, Debug, PartialEq, Eq, Hash)]
#[derive(HashStable_Generic)]
pub struct ConstStability {
pub level: StabilityLevel,
@ -146,7 +150,7 @@ pub struct ConstStability {
}
/// The available stability levels.
#[derive(RustcEncodable, RustcDecodable, PartialEq, PartialOrd, Copy, Clone, Debug, Eq, Hash)]
#[derive(Encodable, Decodable, PartialEq, PartialOrd, Copy, Clone, Debug, Eq, Hash)]
#[derive(HashStable_Generic)]
pub enum StabilityLevel {
// Reason for the current stability level and the relevant rust-lang issue
@ -344,6 +348,14 @@ where
match (feature, reason, issue) {
(Some(feature), reason, Some(_)) => {
if !rustc_lexer::is_ident(&feature.as_str()) {
handle_errors(
&sess.parse_sess,
attr.span,
AttrError::NonIdentFeature,
);
continue;
}
let level = Unstable { reason, issue: issue_num, is_soft };
if sym::unstable == meta_name {
stab = Some(Stability { level, feature });
@ -620,7 +632,7 @@ pub fn eval_condition(
}
}
#[derive(RustcEncodable, RustcDecodable, Clone, HashStable_Generic)]
#[derive(Encodable, Decodable, Clone, HashStable_Generic)]
pub struct Deprecation {
pub since: Option<Symbol>,
/// The note to issue a reason.
@ -785,7 +797,7 @@ where
depr
}
#[derive(PartialEq, Debug, RustcEncodable, RustcDecodable, Copy, Clone)]
#[derive(PartialEq, Debug, Encodable, Decodable, Copy, Clone)]
pub enum ReprAttr {
ReprInt(IntType),
ReprC,
@ -796,7 +808,8 @@ pub enum ReprAttr {
ReprNoNiche,
}
#[derive(Eq, PartialEq, Debug, RustcEncodable, RustcDecodable, Copy, Clone, HashStable_Generic)]
#[derive(Eq, PartialEq, Debug, Copy, Clone)]
#[derive(Encodable, Decodable, HashStable_Generic)]
pub enum IntType {
SignedInt(ast::IntTy),
UnsignedInt(ast::UintTy),

View File

@ -6,8 +6,7 @@
#![feature(or_patterns)]
// FIXME(#56935): Work around ICEs during cross-compilation.
#[allow(unused)]
#[macro_use]
extern crate rustc_macros;
mod builtin;

Some files were not shown because too many files have changed in this diff Show More