mirror of
https://forge.sourceware.org/marek/gcc.git
synced 2026-02-22 03:47:02 -05:00
gccrs: Import libcore 1.49.0
This commit imports libcore 1.49.0 into a new directory, "libgrust/rustc-lib/core". LICENSE-* files are taken from the rustc 1.49.0 repository root. libgrust/ChangeLog: * rustc-lib/LICENSE-APACHE: New file. * rustc-lib/LICENSE-MIT: New file. * rustc-lib/version-info: New file. Signed-off-by: Owen Avery <powerboat9.gamer@gmail.com>
This commit is contained in:
176
libgrust/rustc-lib/LICENSE-APACHE
Normal file
176
libgrust/rustc-lib/LICENSE-APACHE
Normal file
@@ -0,0 +1,176 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
23
libgrust/rustc-lib/LICENSE-MIT
Normal file
23
libgrust/rustc-lib/LICENSE-MIT
Normal file
@@ -0,0 +1,23 @@
|
||||
Permission is hereby granted, free of charge, to any
|
||||
person obtaining a copy of this software and associated
|
||||
documentation files (the "Software"), to deal in the
|
||||
Software without restriction, including without
|
||||
limitation the rights to use, copy, modify, merge,
|
||||
publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software
|
||||
is furnished to do so, subject to the following
|
||||
conditions:
|
||||
|
||||
The above copyright notice and this permission notice
|
||||
shall be included in all copies or substantial portions
|
||||
of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
||||
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||||
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
|
||||
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
|
||||
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
27
libgrust/rustc-lib/core/Cargo.toml
Normal file
27
libgrust/rustc-lib/core/Cargo.toml
Normal file
@@ -0,0 +1,27 @@
|
||||
[package]
|
||||
authors = ["The Rust Project Developers"]
|
||||
name = "core"
|
||||
version = "0.0.0"
|
||||
autotests = false
|
||||
autobenches = false
|
||||
edition = "2018"
|
||||
|
||||
[lib]
|
||||
test = false
|
||||
bench = false
|
||||
|
||||
[[test]]
|
||||
name = "coretests"
|
||||
path = "tests/lib.rs"
|
||||
|
||||
[[bench]]
|
||||
name = "corebenches"
|
||||
path = "benches/lib.rs"
|
||||
test = true
|
||||
|
||||
[dev-dependencies]
|
||||
rand = "0.7"
|
||||
|
||||
[features]
|
||||
# Make panics and failed asserts immediately abort without formatting any message
|
||||
panic_immediate_abort = []
|
||||
12
libgrust/rustc-lib/core/benches/any.rs
Normal file
12
libgrust/rustc-lib/core/benches/any.rs
Normal file
@@ -0,0 +1,12 @@
|
||||
use core::any::*;
|
||||
use test::{black_box, Bencher};
|
||||
|
||||
#[bench]
|
||||
fn bench_downcast_ref(b: &mut Bencher) {
|
||||
b.iter(|| {
|
||||
let mut x = 0;
|
||||
let mut y = &mut x as &mut dyn Any;
|
||||
black_box(&mut y);
|
||||
black_box(y.downcast_ref::<isize>() == Some(&0));
|
||||
});
|
||||
}
|
||||
351
libgrust/rustc-lib/core/benches/ascii.rs
Normal file
351
libgrust/rustc-lib/core/benches/ascii.rs
Normal file
@@ -0,0 +1,351 @@
|
||||
mod is_ascii;
|
||||
|
||||
// Lower-case ASCII 'a' is the first byte that has its highest bit set
|
||||
// after wrap-adding 0x1F:
|
||||
//
|
||||
// b'a' + 0x1F == 0x80 == 0b1000_0000
|
||||
// b'z' + 0x1F == 0x98 == 0b1001_1000
|
||||
//
|
||||
// Lower-case ASCII 'z' is the last byte that has its highest bit unset
|
||||
// after wrap-adding 0x05:
|
||||
//
|
||||
// b'a' + 0x05 == 0x66 == 0b0110_0110
|
||||
// b'z' + 0x05 == 0x7F == 0b0111_1111
|
||||
//
|
||||
// … except for 0xFB to 0xFF, but those are in the range of bytes
|
||||
// that have the highest bit unset again after adding 0x1F.
|
||||
//
|
||||
// So `(byte + 0x1f) & !(byte + 5)` has its highest bit set
|
||||
// iff `byte` is a lower-case ASCII letter.
|
||||
//
|
||||
// Lower-case ASCII letters all have the 0x20 bit set.
|
||||
// (Two positions right of 0x80, the highest bit.)
|
||||
// Unsetting that bit produces the same letter, in upper-case.
|
||||
//
|
||||
// Therefore:
|
||||
fn branchless_to_ascii_upper_case(byte: u8) -> u8 {
|
||||
byte & !((byte.wrapping_add(0x1f) & !byte.wrapping_add(0x05) & 0x80) >> 2)
|
||||
}
|
||||
|
||||
macro_rules! benches {
|
||||
($( fn $name: ident($arg: ident: &mut [u8]) $body: block )+ @iter $( $is_: ident, )+) => {
|
||||
benches! {@
|
||||
$( fn $name($arg: &mut [u8]) $body )+
|
||||
$( fn $is_(bytes: &mut [u8]) { bytes.iter().all(u8::$is_) } )+
|
||||
}
|
||||
};
|
||||
|
||||
(@$( fn $name: ident($arg: ident: &mut [u8]) $body: block )+) => {
|
||||
benches!(mod short SHORT $($name $arg $body)+);
|
||||
benches!(mod medium MEDIUM $($name $arg $body)+);
|
||||
benches!(mod long LONG $($name $arg $body)+);
|
||||
};
|
||||
|
||||
(mod $mod_name: ident $input: ident $($name: ident $arg: ident $body: block)+) => {
|
||||
mod $mod_name {
|
||||
use super::*;
|
||||
|
||||
$(
|
||||
#[bench]
|
||||
fn $name(bencher: &mut Bencher) {
|
||||
bencher.bytes = $input.len() as u64;
|
||||
bencher.iter(|| {
|
||||
let mut vec = $input.as_bytes().to_vec();
|
||||
{
|
||||
let $arg = &mut vec[..];
|
||||
black_box($body);
|
||||
}
|
||||
vec
|
||||
})
|
||||
}
|
||||
)+
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
use test::black_box;
|
||||
use test::Bencher;
|
||||
|
||||
benches! {
|
||||
fn case00_alloc_only(_bytes: &mut [u8]) {}
|
||||
|
||||
fn case01_black_box_read_each_byte(bytes: &mut [u8]) {
|
||||
for byte in bytes {
|
||||
black_box(*byte);
|
||||
}
|
||||
}
|
||||
|
||||
fn case02_lookup_table(bytes: &mut [u8]) {
|
||||
for byte in bytes {
|
||||
*byte = ASCII_UPPERCASE_MAP[*byte as usize]
|
||||
}
|
||||
}
|
||||
|
||||
fn case03_branch_and_subtract(bytes: &mut [u8]) {
|
||||
for byte in bytes {
|
||||
*byte = if b'a' <= *byte && *byte <= b'z' {
|
||||
*byte - b'a' + b'A'
|
||||
} else {
|
||||
*byte
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn case04_branch_and_mask(bytes: &mut [u8]) {
|
||||
for byte in bytes {
|
||||
*byte = if b'a' <= *byte && *byte <= b'z' {
|
||||
*byte & !0x20
|
||||
} else {
|
||||
*byte
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn case05_branchless(bytes: &mut [u8]) {
|
||||
for byte in bytes {
|
||||
*byte = branchless_to_ascii_upper_case(*byte)
|
||||
}
|
||||
}
|
||||
|
||||
fn case06_libcore(bytes: &mut [u8]) {
|
||||
bytes.make_ascii_uppercase()
|
||||
}
|
||||
|
||||
fn case07_fake_simd_u32(bytes: &mut [u8]) {
|
||||
// SAFETY: transmuting a sequence of `u8` to `u32` is always fine
|
||||
let (before, aligned, after) = unsafe {
|
||||
bytes.align_to_mut::<u32>()
|
||||
};
|
||||
for byte in before {
|
||||
*byte = branchless_to_ascii_upper_case(*byte)
|
||||
}
|
||||
for word in aligned {
|
||||
// FIXME: this is incorrect for some byte values:
|
||||
// addition within a byte can carry/overflow into the next byte.
|
||||
// Test case: b"\xFFz "
|
||||
*word &= !(
|
||||
(
|
||||
word.wrapping_add(0x1f1f1f1f) &
|
||||
!word.wrapping_add(0x05050505) &
|
||||
0x80808080
|
||||
) >> 2
|
||||
)
|
||||
}
|
||||
for byte in after {
|
||||
*byte = branchless_to_ascii_upper_case(*byte)
|
||||
}
|
||||
}
|
||||
|
||||
fn case08_fake_simd_u64(bytes: &mut [u8]) {
|
||||
// SAFETY: transmuting a sequence of `u8` to `u64` is always fine
|
||||
let (before, aligned, after) = unsafe {
|
||||
bytes.align_to_mut::<u64>()
|
||||
};
|
||||
for byte in before {
|
||||
*byte = branchless_to_ascii_upper_case(*byte)
|
||||
}
|
||||
for word in aligned {
|
||||
// FIXME: like above, this is incorrect for some byte values.
|
||||
*word &= !(
|
||||
(
|
||||
word.wrapping_add(0x1f1f1f1f_1f1f1f1f) &
|
||||
!word.wrapping_add(0x05050505_05050505) &
|
||||
0x80808080_80808080
|
||||
) >> 2
|
||||
)
|
||||
}
|
||||
for byte in after {
|
||||
*byte = branchless_to_ascii_upper_case(*byte)
|
||||
}
|
||||
}
|
||||
|
||||
fn case09_mask_mult_bool_branchy_lookup_table(bytes: &mut [u8]) {
|
||||
fn is_ascii_lowercase(b: u8) -> bool {
|
||||
if b >= 0x80 { return false }
|
||||
match ASCII_CHARACTER_CLASS[b as usize] {
|
||||
L | Lx => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
for byte in bytes {
|
||||
*byte &= !(0x20 * (is_ascii_lowercase(*byte) as u8))
|
||||
}
|
||||
}
|
||||
|
||||
fn case10_mask_mult_bool_lookup_table(bytes: &mut [u8]) {
|
||||
fn is_ascii_lowercase(b: u8) -> bool {
|
||||
match ASCII_CHARACTER_CLASS[b as usize] {
|
||||
L | Lx => true,
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
for byte in bytes {
|
||||
*byte &= !(0x20 * (is_ascii_lowercase(*byte) as u8))
|
||||
}
|
||||
}
|
||||
|
||||
fn case11_mask_mult_bool_match_range(bytes: &mut [u8]) {
|
||||
fn is_ascii_lowercase(b: u8) -> bool {
|
||||
match b {
|
||||
b'a'..=b'z' => true,
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
for byte in bytes {
|
||||
*byte &= !(0x20 * (is_ascii_lowercase(*byte) as u8))
|
||||
}
|
||||
}
|
||||
|
||||
fn case12_mask_shifted_bool_match_range(bytes: &mut [u8]) {
|
||||
fn is_ascii_lowercase(b: u8) -> bool {
|
||||
match b {
|
||||
b'a'..=b'z' => true,
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
for byte in bytes {
|
||||
*byte &= !((is_ascii_lowercase(*byte) as u8) << 5)
|
||||
}
|
||||
}
|
||||
|
||||
fn case13_subtract_shifted_bool_match_range(bytes: &mut [u8]) {
|
||||
fn is_ascii_lowercase(b: u8) -> bool {
|
||||
match b {
|
||||
b'a'..=b'z' => true,
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
for byte in bytes {
|
||||
*byte -= (is_ascii_lowercase(*byte) as u8) << 5
|
||||
}
|
||||
}
|
||||
|
||||
fn case14_subtract_multiplied_bool_match_range(bytes: &mut [u8]) {
|
||||
fn is_ascii_lowercase(b: u8) -> bool {
|
||||
match b {
|
||||
b'a'..=b'z' => true,
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
for byte in bytes {
|
||||
*byte -= (b'a' - b'A') * is_ascii_lowercase(*byte) as u8
|
||||
}
|
||||
}
|
||||
|
||||
@iter
|
||||
|
||||
is_ascii,
|
||||
is_ascii_alphabetic,
|
||||
is_ascii_uppercase,
|
||||
is_ascii_lowercase,
|
||||
is_ascii_alphanumeric,
|
||||
is_ascii_digit,
|
||||
is_ascii_hexdigit,
|
||||
is_ascii_punctuation,
|
||||
is_ascii_graphic,
|
||||
is_ascii_whitespace,
|
||||
is_ascii_control,
|
||||
}
|
||||
|
||||
macro_rules! repeat {
|
||||
($s: expr) => {
|
||||
concat!($s, $s, $s, $s, $s, $s, $s, $s, $s, $s)
|
||||
};
|
||||
}
|
||||
|
||||
const SHORT: &str = "Alice's";
|
||||
const MEDIUM: &str = "Alice's Adventures in Wonderland";
|
||||
const LONG: &str = repeat!(
|
||||
r#"
|
||||
La Guida di Bragia, a Ballad Opera for the Marionette Theatre (around 1850)
|
||||
Alice's Adventures in Wonderland (1865)
|
||||
Phantasmagoria and Other Poems (1869)
|
||||
Through the Looking-Glass, and What Alice Found There
|
||||
(includes "Jabberwocky" and "The Walrus and the Carpenter") (1871)
|
||||
The Hunting of the Snark (1876)
|
||||
Rhyme? And Reason? (1883) – shares some contents with the 1869 collection,
|
||||
including the long poem "Phantasmagoria"
|
||||
A Tangled Tale (1885)
|
||||
Sylvie and Bruno (1889)
|
||||
Sylvie and Bruno Concluded (1893)
|
||||
Pillow Problems (1893)
|
||||
What the Tortoise Said to Achilles (1895)
|
||||
Three Sunsets and Other Poems (1898)
|
||||
The Manlet (1903)[106]
|
||||
"#
|
||||
);
|
||||
|
||||
#[rustfmt::skip]
|
||||
const ASCII_UPPERCASE_MAP: [u8; 256] = [
|
||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
|
||||
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
|
||||
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
|
||||
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
|
||||
b' ', b'!', b'"', b'#', b'$', b'%', b'&', b'\'',
|
||||
b'(', b')', b'*', b'+', b',', b'-', b'.', b'/',
|
||||
b'0', b'1', b'2', b'3', b'4', b'5', b'6', b'7',
|
||||
b'8', b'9', b':', b';', b'<', b'=', b'>', b'?',
|
||||
b'@', b'A', b'B', b'C', b'D', b'E', b'F', b'G',
|
||||
b'H', b'I', b'J', b'K', b'L', b'M', b'N', b'O',
|
||||
b'P', b'Q', b'R', b'S', b'T', b'U', b'V', b'W',
|
||||
b'X', b'Y', b'Z', b'[', b'\\', b']', b'^', b'_',
|
||||
b'`',
|
||||
|
||||
b'A', b'B', b'C', b'D', b'E', b'F', b'G',
|
||||
b'H', b'I', b'J', b'K', b'L', b'M', b'N', b'O',
|
||||
b'P', b'Q', b'R', b'S', b'T', b'U', b'V', b'W',
|
||||
b'X', b'Y', b'Z',
|
||||
|
||||
b'{', b'|', b'}', b'~', 0x7f,
|
||||
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
|
||||
0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
|
||||
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
|
||||
0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
|
||||
0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
|
||||
0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
|
||||
0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
|
||||
0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
|
||||
0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
|
||||
0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
|
||||
0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
|
||||
0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
|
||||
0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
|
||||
0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
|
||||
0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
|
||||
0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
|
||||
];
|
||||
|
||||
enum AsciiCharacterClass {
|
||||
C, // control
|
||||
Cw, // control whitespace
|
||||
W, // whitespace
|
||||
D, // digit
|
||||
L, // lowercase
|
||||
Lx, // lowercase hex digit
|
||||
U, // uppercase
|
||||
Ux, // uppercase hex digit
|
||||
P, // punctuation
|
||||
N, // Non-ASCII
|
||||
}
|
||||
use self::AsciiCharacterClass::*;
|
||||
|
||||
#[rustfmt::skip]
|
||||
static ASCII_CHARACTER_CLASS: [AsciiCharacterClass; 256] = [
|
||||
// _0 _1 _2 _3 _4 _5 _6 _7 _8 _9 _a _b _c _d _e _f
|
||||
C, C, C, C, C, C, C, C, C, Cw,Cw,C, Cw,Cw,C, C, // 0_
|
||||
C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, // 1_
|
||||
W, P, P, P, P, P, P, P, P, P, P, P, P, P, P, P, // 2_
|
||||
D, D, D, D, D, D, D, D, D, D, P, P, P, P, P, P, // 3_
|
||||
P, Ux,Ux,Ux,Ux,Ux,Ux,U, U, U, U, U, U, U, U, U, // 4_
|
||||
U, U, U, U, U, U, U, U, U, U, U, P, P, P, P, P, // 5_
|
||||
P, Lx,Lx,Lx,Lx,Lx,Lx,L, L, L, L, L, L, L, L, L, // 6_
|
||||
L, L, L, L, L, L, L, L, L, L, L, P, P, P, P, C, // 7_
|
||||
N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N,
|
||||
N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N,
|
||||
N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N,
|
||||
N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N,
|
||||
N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N,
|
||||
N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N,
|
||||
N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N,
|
||||
N, N, N, N, N, N, N, N, N, N, N, N, N, N, N, N,
|
||||
];
|
||||
82
libgrust/rustc-lib/core/benches/ascii/is_ascii.rs
Normal file
82
libgrust/rustc-lib/core/benches/ascii/is_ascii.rs
Normal file
@@ -0,0 +1,82 @@
|
||||
use super::{LONG, MEDIUM, SHORT};
|
||||
use test::black_box;
|
||||
use test::Bencher;
|
||||
|
||||
macro_rules! benches {
|
||||
($( fn $name: ident($arg: ident: &[u8]) $body: block )+) => {
|
||||
benches!(mod short SHORT[..] $($name $arg $body)+);
|
||||
benches!(mod medium MEDIUM[..] $($name $arg $body)+);
|
||||
benches!(mod long LONG[..] $($name $arg $body)+);
|
||||
// Ensure we benchmark cases where the functions are called with strings
|
||||
// that are not perfectly aligned or have a length which is not a
|
||||
// multiple of size_of::<usize>() (or both)
|
||||
benches!(mod unaligned_head MEDIUM[1..] $($name $arg $body)+);
|
||||
benches!(mod unaligned_tail MEDIUM[..(MEDIUM.len() - 1)] $($name $arg $body)+);
|
||||
benches!(mod unaligned_both MEDIUM[1..(MEDIUM.len() - 1)] $($name $arg $body)+);
|
||||
};
|
||||
|
||||
(mod $mod_name: ident $input: ident [$range: expr] $($name: ident $arg: ident $body: block)+) => {
|
||||
mod $mod_name {
|
||||
use super::*;
|
||||
$(
|
||||
#[bench]
|
||||
fn $name(bencher: &mut Bencher) {
|
||||
bencher.bytes = $input[$range].len() as u64;
|
||||
let mut vec = $input.as_bytes().to_vec();
|
||||
bencher.iter(|| {
|
||||
let $arg: &[u8] = &black_box(&mut vec)[$range];
|
||||
black_box($body)
|
||||
})
|
||||
}
|
||||
)+
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
benches! {
|
||||
fn case00_libcore(bytes: &[u8]) {
|
||||
bytes.is_ascii()
|
||||
}
|
||||
|
||||
fn case01_iter_all(bytes: &[u8]) {
|
||||
bytes.iter().all(|b| b.is_ascii())
|
||||
}
|
||||
|
||||
fn case02_align_to(bytes: &[u8]) {
|
||||
is_ascii_align_to(bytes)
|
||||
}
|
||||
|
||||
fn case03_align_to_unrolled(bytes: &[u8]) {
|
||||
is_ascii_align_to_unrolled(bytes)
|
||||
}
|
||||
}
|
||||
|
||||
// These are separate since it's easier to debug errors if they don't go through
|
||||
// macro expansion first.
|
||||
fn is_ascii_align_to(bytes: &[u8]) -> bool {
|
||||
if bytes.len() < core::mem::size_of::<usize>() {
|
||||
return bytes.iter().all(|b| b.is_ascii());
|
||||
}
|
||||
// SAFETY: transmuting a sequence of `u8` to `usize` is always fine
|
||||
let (head, body, tail) = unsafe { bytes.align_to::<usize>() };
|
||||
head.iter().all(|b| b.is_ascii())
|
||||
&& body.iter().all(|w| !contains_nonascii(*w))
|
||||
&& tail.iter().all(|b| b.is_ascii())
|
||||
}
|
||||
|
||||
fn is_ascii_align_to_unrolled(bytes: &[u8]) -> bool {
|
||||
if bytes.len() < core::mem::size_of::<usize>() {
|
||||
return bytes.iter().all(|b| b.is_ascii());
|
||||
}
|
||||
// SAFETY: transmuting a sequence of `u8` to `[usize; 2]` is always fine
|
||||
let (head, body, tail) = unsafe { bytes.align_to::<[usize; 2]>() };
|
||||
head.iter().all(|b| b.is_ascii())
|
||||
&& body.iter().all(|w| !contains_nonascii(w[0] | w[1]))
|
||||
&& tail.iter().all(|b| b.is_ascii())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn contains_nonascii(v: usize) -> bool {
|
||||
const NONASCII_MASK: usize = 0x80808080_80808080u64 as usize;
|
||||
(NONASCII_MASK & v) != 0
|
||||
}
|
||||
37
libgrust/rustc-lib/core/benches/char/methods.rs
Normal file
37
libgrust/rustc-lib/core/benches/char/methods.rs
Normal file
@@ -0,0 +1,37 @@
|
||||
use test::Bencher;
|
||||
|
||||
const CHARS: [char; 9] = ['0', 'x', '2', '5', 'A', 'f', '7', '8', '9'];
|
||||
const RADIX: [u32; 5] = [2, 8, 10, 16, 32];
|
||||
|
||||
#[bench]
|
||||
fn bench_to_digit_radix_2(b: &mut Bencher) {
|
||||
b.iter(|| CHARS.iter().cycle().take(10_000).map(|c| c.to_digit(2)).min())
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_to_digit_radix_10(b: &mut Bencher) {
|
||||
b.iter(|| CHARS.iter().cycle().take(10_000).map(|c| c.to_digit(10)).min())
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_to_digit_radix_16(b: &mut Bencher) {
|
||||
b.iter(|| CHARS.iter().cycle().take(10_000).map(|c| c.to_digit(16)).min())
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_to_digit_radix_36(b: &mut Bencher) {
|
||||
b.iter(|| CHARS.iter().cycle().take(10_000).map(|c| c.to_digit(36)).min())
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_to_digit_radix_var(b: &mut Bencher) {
|
||||
b.iter(|| {
|
||||
CHARS
|
||||
.iter()
|
||||
.cycle()
|
||||
.zip(RADIX.iter().cycle())
|
||||
.take(10_000)
|
||||
.map(|(c, radix)| c.to_digit(*radix))
|
||||
.min()
|
||||
})
|
||||
}
|
||||
1
libgrust/rustc-lib/core/benches/char/mod.rs
Normal file
1
libgrust/rustc-lib/core/benches/char/mod.rs
Normal file
@@ -0,0 +1 @@
|
||||
mod methods;
|
||||
139
libgrust/rustc-lib/core/benches/fmt.rs
Normal file
139
libgrust/rustc-lib/core/benches/fmt.rs
Normal file
@@ -0,0 +1,139 @@
|
||||
use std::fmt::{self, Write as FmtWrite};
|
||||
use std::io::{self, Write as IoWrite};
|
||||
use test::Bencher;
|
||||
|
||||
#[bench]
|
||||
fn write_vec_value(bh: &mut Bencher) {
|
||||
bh.iter(|| {
|
||||
let mut mem = Vec::new();
|
||||
for _ in 0..1000 {
|
||||
mem.write_all("abc".as_bytes()).unwrap();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn write_vec_ref(bh: &mut Bencher) {
|
||||
bh.iter(|| {
|
||||
let mut mem = Vec::new();
|
||||
let wr = &mut mem as &mut dyn io::Write;
|
||||
for _ in 0..1000 {
|
||||
wr.write_all("abc".as_bytes()).unwrap();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn write_vec_macro1(bh: &mut Bencher) {
|
||||
bh.iter(|| {
|
||||
let mut mem = Vec::new();
|
||||
let wr = &mut mem as &mut dyn io::Write;
|
||||
for _ in 0..1000 {
|
||||
write!(wr, "abc").unwrap();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn write_vec_macro2(bh: &mut Bencher) {
|
||||
bh.iter(|| {
|
||||
let mut mem = Vec::new();
|
||||
let wr = &mut mem as &mut dyn io::Write;
|
||||
for _ in 0..1000 {
|
||||
write!(wr, "{}", "abc").unwrap();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn write_vec_macro_debug(bh: &mut Bencher) {
|
||||
bh.iter(|| {
|
||||
let mut mem = Vec::new();
|
||||
let wr = &mut mem as &mut dyn io::Write;
|
||||
for _ in 0..1000 {
|
||||
write!(wr, "{:?}", "☃").unwrap();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn write_str_value(bh: &mut Bencher) {
|
||||
bh.iter(|| {
|
||||
let mut mem = String::new();
|
||||
for _ in 0..1000 {
|
||||
mem.write_str("abc").unwrap();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn write_str_ref(bh: &mut Bencher) {
|
||||
bh.iter(|| {
|
||||
let mut mem = String::new();
|
||||
let wr = &mut mem as &mut dyn fmt::Write;
|
||||
for _ in 0..1000 {
|
||||
wr.write_str("abc").unwrap();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn write_str_macro1(bh: &mut Bencher) {
|
||||
bh.iter(|| {
|
||||
let mut mem = String::new();
|
||||
for _ in 0..1000 {
|
||||
write!(mem, "abc").unwrap();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn write_str_macro2(bh: &mut Bencher) {
|
||||
bh.iter(|| {
|
||||
let mut mem = String::new();
|
||||
let wr = &mut mem as &mut dyn fmt::Write;
|
||||
for _ in 0..1000 {
|
||||
write!(wr, "{}", "abc").unwrap();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn write_str_macro_debug(bh: &mut Bencher) {
|
||||
bh.iter(|| {
|
||||
let mut mem = String::new();
|
||||
let wr = &mut mem as &mut dyn fmt::Write;
|
||||
for _ in 0..1000 {
|
||||
write!(wr, "{:?}", "☃").unwrap();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn write_u128_max(bh: &mut Bencher) {
|
||||
bh.iter(|| {
|
||||
std::hint::black_box(format!("{}", u128::MAX));
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn write_u128_min(bh: &mut Bencher) {
|
||||
bh.iter(|| {
|
||||
let s = format!("{}", 0u128);
|
||||
std::hint::black_box(s);
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn write_u64_max(bh: &mut Bencher) {
|
||||
bh.iter(|| {
|
||||
std::hint::black_box(format!("{}", u64::MAX));
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn write_u64_min(bh: &mut Bencher) {
|
||||
bh.iter(|| {
|
||||
std::hint::black_box(format!("{}", 0u64));
|
||||
});
|
||||
}
|
||||
1
libgrust/rustc-lib/core/benches/hash/mod.rs
Normal file
1
libgrust/rustc-lib/core/benches/hash/mod.rs
Normal file
@@ -0,0 +1 @@
|
||||
mod sip;
|
||||
123
libgrust/rustc-lib/core/benches/hash/sip.rs
Normal file
123
libgrust/rustc-lib/core/benches/hash/sip.rs
Normal file
@@ -0,0 +1,123 @@
|
||||
#![allow(deprecated)]
|
||||
|
||||
use core::hash::*;
|
||||
use test::{black_box, Bencher};
|
||||
|
||||
fn hash_bytes<H: Hasher>(mut s: H, x: &[u8]) -> u64 {
|
||||
Hasher::write(&mut s, x);
|
||||
s.finish()
|
||||
}
|
||||
|
||||
fn hash_with<H: Hasher, T: Hash>(mut st: H, x: &T) -> u64 {
|
||||
x.hash(&mut st);
|
||||
st.finish()
|
||||
}
|
||||
|
||||
fn hash<T: Hash>(x: &T) -> u64 {
|
||||
hash_with(SipHasher::new(), x)
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_str_under_8_bytes(b: &mut Bencher) {
|
||||
let s = "foo";
|
||||
b.iter(|| {
|
||||
assert_eq!(hash(&s), 16262950014981195938);
|
||||
})
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_str_of_8_bytes(b: &mut Bencher) {
|
||||
let s = "foobar78";
|
||||
b.iter(|| {
|
||||
assert_eq!(hash(&s), 4898293253460910787);
|
||||
})
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_str_over_8_bytes(b: &mut Bencher) {
|
||||
let s = "foobarbaz0";
|
||||
b.iter(|| {
|
||||
assert_eq!(hash(&s), 10581415515220175264);
|
||||
})
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_long_str(b: &mut Bencher) {
|
||||
let s = "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor \
|
||||
incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud \
|
||||
exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute \
|
||||
irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla \
|
||||
pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui \
|
||||
officia deserunt mollit anim id est laborum.";
|
||||
b.iter(|| {
|
||||
assert_eq!(hash(&s), 17717065544121360093);
|
||||
})
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_u32(b: &mut Bencher) {
|
||||
let u = 162629500u32;
|
||||
let u = black_box(u);
|
||||
b.iter(|| hash(&u));
|
||||
b.bytes = 8;
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_u32_keyed(b: &mut Bencher) {
|
||||
let u = 162629500u32;
|
||||
let u = black_box(u);
|
||||
let k1 = black_box(0x1);
|
||||
let k2 = black_box(0x2);
|
||||
b.iter(|| hash_with(SipHasher::new_with_keys(k1, k2), &u));
|
||||
b.bytes = 8;
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_u64(b: &mut Bencher) {
|
||||
let u = 16262950014981195938u64;
|
||||
let u = black_box(u);
|
||||
b.iter(|| hash(&u));
|
||||
b.bytes = 8;
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_bytes_4(b: &mut Bencher) {
|
||||
let data = black_box([b' '; 4]);
|
||||
b.iter(|| hash_bytes(SipHasher::default(), &data));
|
||||
b.bytes = 4;
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_bytes_7(b: &mut Bencher) {
|
||||
let data = black_box([b' '; 7]);
|
||||
b.iter(|| hash_bytes(SipHasher::default(), &data));
|
||||
b.bytes = 7;
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_bytes_8(b: &mut Bencher) {
|
||||
let data = black_box([b' '; 8]);
|
||||
b.iter(|| hash_bytes(SipHasher::default(), &data));
|
||||
b.bytes = 8;
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_bytes_a_16(b: &mut Bencher) {
|
||||
let data = black_box([b' '; 16]);
|
||||
b.iter(|| hash_bytes(SipHasher::default(), &data));
|
||||
b.bytes = 16;
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_bytes_b_32(b: &mut Bencher) {
|
||||
let data = black_box([b' '; 32]);
|
||||
b.iter(|| hash_bytes(SipHasher::default(), &data));
|
||||
b.bytes = 32;
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_bytes_c_128(b: &mut Bencher) {
|
||||
let data = black_box([b' '; 128]);
|
||||
b.iter(|| hash_bytes(SipHasher::default(), &data));
|
||||
b.bytes = 128;
|
||||
}
|
||||
347
libgrust/rustc-lib/core/benches/iter.rs
Normal file
347
libgrust/rustc-lib/core/benches/iter.rs
Normal file
@@ -0,0 +1,347 @@
|
||||
use core::iter::*;
|
||||
use test::{black_box, Bencher};
|
||||
|
||||
#[bench]
|
||||
fn bench_rposition(b: &mut Bencher) {
|
||||
let it: Vec<usize> = (0..300).collect();
|
||||
b.iter(|| {
|
||||
it.iter().rposition(|&x| x <= 150);
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_skip_while(b: &mut Bencher) {
|
||||
b.iter(|| {
|
||||
let it = 0..100;
|
||||
let mut sum = 0;
|
||||
it.skip_while(|&x| {
|
||||
sum += x;
|
||||
sum < 4000
|
||||
})
|
||||
.all(|_| true);
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_multiple_take(b: &mut Bencher) {
|
||||
let mut it = (0..42).cycle();
|
||||
b.iter(|| {
|
||||
let n = it.next().unwrap();
|
||||
for _ in 0..n {
|
||||
it.clone().take(it.next().unwrap()).all(|_| true);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
fn scatter(x: i32) -> i32 {
|
||||
(x * 31) % 127
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_max_by_key(b: &mut Bencher) {
|
||||
b.iter(|| {
|
||||
let it = 0..100;
|
||||
it.map(black_box).max_by_key(|&x| scatter(x))
|
||||
})
|
||||
}
|
||||
|
||||
// http://www.reddit.com/r/rust/comments/31syce/using_iterators_to_find_the_index_of_the_min_or/
|
||||
#[bench]
|
||||
fn bench_max_by_key2(b: &mut Bencher) {
|
||||
fn max_index_iter(array: &[i32]) -> usize {
|
||||
array.iter().enumerate().max_by_key(|&(_, item)| item).unwrap().0
|
||||
}
|
||||
|
||||
let mut data = vec![0; 1638];
|
||||
data[514] = 9999;
|
||||
|
||||
b.iter(|| max_index_iter(&data));
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_max(b: &mut Bencher) {
|
||||
b.iter(|| {
|
||||
let it = 0..100;
|
||||
it.map(black_box).map(scatter).max()
|
||||
})
|
||||
}
|
||||
|
||||
pub fn copy_zip(xs: &[u8], ys: &mut [u8]) {
|
||||
for (a, b) in ys.iter_mut().zip(xs) {
|
||||
*a = *b;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_zip(xs: &[f32], ys: &mut [f32]) {
|
||||
for (a, b) in ys.iter_mut().zip(xs) {
|
||||
*a += *b;
|
||||
}
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_zip_copy(b: &mut Bencher) {
|
||||
let source = vec![0u8; 16 * 1024];
|
||||
let mut dst = black_box(vec![0u8; 16 * 1024]);
|
||||
b.iter(|| copy_zip(&source, &mut dst))
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_zip_add(b: &mut Bencher) {
|
||||
let source = vec![1.; 16 * 1024];
|
||||
let mut dst = vec![0.; 16 * 1024];
|
||||
b.iter(|| add_zip(&source, &mut dst));
|
||||
}
|
||||
|
||||
/// `Iterator::for_each` implemented as a plain loop.
|
||||
fn for_each_loop<I, F>(iter: I, mut f: F)
|
||||
where
|
||||
I: Iterator,
|
||||
F: FnMut(I::Item),
|
||||
{
|
||||
for item in iter {
|
||||
f(item);
|
||||
}
|
||||
}
|
||||
|
||||
/// `Iterator::for_each` implemented with `fold` for internal iteration.
|
||||
/// (except when `by_ref()` effectively disables that optimization.)
|
||||
fn for_each_fold<I, F>(iter: I, mut f: F)
|
||||
where
|
||||
I: Iterator,
|
||||
F: FnMut(I::Item),
|
||||
{
|
||||
iter.fold((), move |(), item| f(item));
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_for_each_chain_loop(b: &mut Bencher) {
|
||||
b.iter(|| {
|
||||
let mut acc = 0;
|
||||
let iter = (0i64..1000000).chain(0..1000000).map(black_box);
|
||||
for_each_loop(iter, |x| acc += x);
|
||||
acc
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_for_each_chain_fold(b: &mut Bencher) {
|
||||
b.iter(|| {
|
||||
let mut acc = 0;
|
||||
let iter = (0i64..1000000).chain(0..1000000).map(black_box);
|
||||
for_each_fold(iter, |x| acc += x);
|
||||
acc
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_for_each_chain_ref_fold(b: &mut Bencher) {
|
||||
b.iter(|| {
|
||||
let mut acc = 0;
|
||||
let mut iter = (0i64..1000000).chain(0..1000000).map(black_box);
|
||||
for_each_fold(iter.by_ref(), |x| acc += x);
|
||||
acc
|
||||
});
|
||||
}
|
||||
|
||||
/// Helper to benchmark `sum` for iterators taken by value which
|
||||
/// can optimize `fold`, and by reference which cannot.
|
||||
macro_rules! bench_sums {
|
||||
($bench_sum:ident, $bench_ref_sum:ident, $iter:expr) => {
|
||||
#[bench]
|
||||
fn $bench_sum(b: &mut Bencher) {
|
||||
b.iter(|| -> i64 { $iter.map(black_box).sum() });
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn $bench_ref_sum(b: &mut Bencher) {
|
||||
b.iter(|| -> i64 { $iter.map(black_box).by_ref().sum() });
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
bench_sums! {
|
||||
bench_flat_map_sum,
|
||||
bench_flat_map_ref_sum,
|
||||
(0i64..1000).flat_map(|x| x..x+1000)
|
||||
}
|
||||
|
||||
bench_sums! {
|
||||
bench_flat_map_chain_sum,
|
||||
bench_flat_map_chain_ref_sum,
|
||||
(0i64..1000000).flat_map(|x| once(x).chain(once(x)))
|
||||
}
|
||||
|
||||
bench_sums! {
|
||||
bench_enumerate_sum,
|
||||
bench_enumerate_ref_sum,
|
||||
(0i64..1000000).enumerate().map(|(i, x)| x * i as i64)
|
||||
}
|
||||
|
||||
bench_sums! {
|
||||
bench_enumerate_chain_sum,
|
||||
bench_enumerate_chain_ref_sum,
|
||||
(0i64..1000000).chain(0..1000000).enumerate().map(|(i, x)| x * i as i64)
|
||||
}
|
||||
|
||||
bench_sums! {
|
||||
bench_filter_sum,
|
||||
bench_filter_ref_sum,
|
||||
(0i64..1000000).filter(|x| x % 3 == 0)
|
||||
}
|
||||
|
||||
bench_sums! {
|
||||
bench_filter_chain_sum,
|
||||
bench_filter_chain_ref_sum,
|
||||
(0i64..1000000).chain(0..1000000).filter(|x| x % 3 == 0)
|
||||
}
|
||||
|
||||
bench_sums! {
|
||||
bench_filter_map_sum,
|
||||
bench_filter_map_ref_sum,
|
||||
(0i64..1000000).filter_map(|x| x.checked_mul(x))
|
||||
}
|
||||
|
||||
bench_sums! {
|
||||
bench_filter_map_chain_sum,
|
||||
bench_filter_map_chain_ref_sum,
|
||||
(0i64..1000000).chain(0..1000000).filter_map(|x| x.checked_mul(x))
|
||||
}
|
||||
|
||||
bench_sums! {
|
||||
bench_fuse_sum,
|
||||
bench_fuse_ref_sum,
|
||||
(0i64..1000000).fuse()
|
||||
}
|
||||
|
||||
bench_sums! {
|
||||
bench_fuse_chain_sum,
|
||||
bench_fuse_chain_ref_sum,
|
||||
(0i64..1000000).chain(0..1000000).fuse()
|
||||
}
|
||||
|
||||
bench_sums! {
|
||||
bench_inspect_sum,
|
||||
bench_inspect_ref_sum,
|
||||
(0i64..1000000).inspect(|_| {})
|
||||
}
|
||||
|
||||
bench_sums! {
|
||||
bench_inspect_chain_sum,
|
||||
bench_inspect_chain_ref_sum,
|
||||
(0i64..1000000).chain(0..1000000).inspect(|_| {})
|
||||
}
|
||||
|
||||
bench_sums! {
|
||||
bench_peekable_sum,
|
||||
bench_peekable_ref_sum,
|
||||
(0i64..1000000).peekable()
|
||||
}
|
||||
|
||||
bench_sums! {
|
||||
bench_peekable_chain_sum,
|
||||
bench_peekable_chain_ref_sum,
|
||||
(0i64..1000000).chain(0..1000000).peekable()
|
||||
}
|
||||
|
||||
bench_sums! {
|
||||
bench_skip_sum,
|
||||
bench_skip_ref_sum,
|
||||
(0i64..1000000).skip(1000)
|
||||
}
|
||||
|
||||
bench_sums! {
|
||||
bench_skip_chain_sum,
|
||||
bench_skip_chain_ref_sum,
|
||||
(0i64..1000000).chain(0..1000000).skip(1000)
|
||||
}
|
||||
|
||||
bench_sums! {
|
||||
bench_skip_while_sum,
|
||||
bench_skip_while_ref_sum,
|
||||
(0i64..1000000).skip_while(|&x| x < 1000)
|
||||
}
|
||||
|
||||
bench_sums! {
|
||||
bench_skip_while_chain_sum,
|
||||
bench_skip_while_chain_ref_sum,
|
||||
(0i64..1000000).chain(0..1000000).skip_while(|&x| x < 1000)
|
||||
}
|
||||
|
||||
bench_sums! {
|
||||
bench_take_while_chain_sum,
|
||||
bench_take_while_chain_ref_sum,
|
||||
(0i64..1000000).chain(1000000..).take_while(|&x| x < 1111111)
|
||||
}
|
||||
|
||||
bench_sums! {
|
||||
bench_cycle_take_sum,
|
||||
bench_cycle_take_ref_sum,
|
||||
(0i64..10000).cycle().take(1000000)
|
||||
}
|
||||
|
||||
// Checks whether Skip<Zip<A,B>> is as fast as Zip<Skip<A>, Skip<B>>, from
|
||||
// https://users.rust-lang.org/t/performance-difference-between-iterator-zip-and-skip-order/15743
|
||||
#[bench]
|
||||
fn bench_zip_then_skip(b: &mut Bencher) {
|
||||
let v: Vec<_> = (0..100_000).collect();
|
||||
let t: Vec<_> = (0..100_000).collect();
|
||||
|
||||
b.iter(|| {
|
||||
let s = v
|
||||
.iter()
|
||||
.zip(t.iter())
|
||||
.skip(10000)
|
||||
.take_while(|t| *t.0 < 10100)
|
||||
.map(|(a, b)| *a + *b)
|
||||
.sum::<u64>();
|
||||
assert_eq!(s, 2009900);
|
||||
});
|
||||
}
|
||||
#[bench]
|
||||
fn bench_skip_then_zip(b: &mut Bencher) {
|
||||
let v: Vec<_> = (0..100_000).collect();
|
||||
let t: Vec<_> = (0..100_000).collect();
|
||||
|
||||
b.iter(|| {
|
||||
let s = v
|
||||
.iter()
|
||||
.skip(10000)
|
||||
.zip(t.iter().skip(10000))
|
||||
.take_while(|t| *t.0 < 10100)
|
||||
.map(|(a, b)| *a + *b)
|
||||
.sum::<u64>();
|
||||
assert_eq!(s, 2009900);
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_filter_count(b: &mut Bencher) {
|
||||
b.iter(|| (0i64..1000000).map(black_box).filter(|x| x % 3 == 0).count())
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_filter_ref_count(b: &mut Bencher) {
|
||||
b.iter(|| (0i64..1000000).map(black_box).by_ref().filter(|x| x % 3 == 0).count())
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_filter_chain_count(b: &mut Bencher) {
|
||||
b.iter(|| (0i64..1000000).chain(0..1000000).map(black_box).filter(|x| x % 3 == 0).count())
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_filter_chain_ref_count(b: &mut Bencher) {
|
||||
b.iter(|| {
|
||||
(0i64..1000000).chain(0..1000000).map(black_box).by_ref().filter(|x| x % 3 == 0).count()
|
||||
})
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_partial_cmp(b: &mut Bencher) {
|
||||
b.iter(|| (0..100000).map(black_box).partial_cmp((0..100000).map(black_box)))
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_lt(b: &mut Bencher) {
|
||||
b.iter(|| (0..100000).map(black_box).lt((0..100000).map(black_box)))
|
||||
}
|
||||
17
libgrust/rustc-lib/core/benches/lib.rs
Normal file
17
libgrust/rustc-lib/core/benches/lib.rs
Normal file
@@ -0,0 +1,17 @@
|
||||
// wasm32 does not support benches (no time).
|
||||
#![cfg(not(target_arch = "wasm32"))]
|
||||
#![feature(flt2dec)]
|
||||
#![feature(test)]
|
||||
|
||||
extern crate test;
|
||||
|
||||
mod any;
|
||||
mod ascii;
|
||||
mod char;
|
||||
mod fmt;
|
||||
mod hash;
|
||||
mod iter;
|
||||
mod num;
|
||||
mod ops;
|
||||
mod pattern;
|
||||
mod slice;
|
||||
57
libgrust/rustc-lib/core/benches/num/dec2flt/mod.rs
Normal file
57
libgrust/rustc-lib/core/benches/num/dec2flt/mod.rs
Normal file
@@ -0,0 +1,57 @@
|
||||
use test::Bencher;
|
||||
|
||||
#[bench]
|
||||
fn bench_0(b: &mut Bencher) {
|
||||
b.iter(|| "0.0".parse::<f64>());
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_42(b: &mut Bencher) {
|
||||
b.iter(|| "42".parse::<f64>());
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_huge_int(b: &mut Bencher) {
|
||||
// 2^128 - 1
|
||||
b.iter(|| "170141183460469231731687303715884105727".parse::<f64>());
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_short_decimal(b: &mut Bencher) {
|
||||
b.iter(|| "1234.5678".parse::<f64>());
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_pi_long(b: &mut Bencher) {
|
||||
b.iter(|| "3.14159265358979323846264338327950288".parse::<f64>());
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_pi_short(b: &mut Bencher) {
|
||||
b.iter(|| "3.141592653589793".parse::<f64>())
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_1e150(b: &mut Bencher) {
|
||||
b.iter(|| "1e150".parse::<f64>());
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_long_decimal_and_exp(b: &mut Bencher) {
|
||||
b.iter(|| "727501488517303786137132964064381141071e-123".parse::<f64>());
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_min_subnormal(b: &mut Bencher) {
|
||||
b.iter(|| "5e-324".parse::<f64>());
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_min_normal(b: &mut Bencher) {
|
||||
b.iter(|| "2.2250738585072014e-308".parse::<f64>());
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_max(b: &mut Bencher) {
|
||||
b.iter(|| "1.7976931348623157e308".parse::<f64>());
|
||||
}
|
||||
37
libgrust/rustc-lib/core/benches/num/flt2dec/mod.rs
Normal file
37
libgrust/rustc-lib/core/benches/num/flt2dec/mod.rs
Normal file
@@ -0,0 +1,37 @@
|
||||
mod strategy {
|
||||
mod dragon;
|
||||
mod grisu;
|
||||
}
|
||||
|
||||
use core::num::flt2dec::MAX_SIG_DIGITS;
|
||||
use core::num::flt2dec::{decode, DecodableFloat, Decoded, FullDecoded};
|
||||
use std::io::Write;
|
||||
use std::vec::Vec;
|
||||
use test::Bencher;
|
||||
|
||||
pub fn decode_finite<T: DecodableFloat>(v: T) -> Decoded {
|
||||
match decode(v).1 {
|
||||
FullDecoded::Finite(decoded) => decoded,
|
||||
full_decoded => panic!("expected finite, got {:?} instead", full_decoded),
|
||||
}
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_small_shortest(b: &mut Bencher) {
|
||||
let mut buf = Vec::with_capacity(20);
|
||||
|
||||
b.iter(|| {
|
||||
buf.clear();
|
||||
write!(&mut buf, "{}", 3.1415926f64).unwrap()
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_big_shortest(b: &mut Bencher) {
|
||||
let mut buf = Vec::with_capacity(300);
|
||||
|
||||
b.iter(|| {
|
||||
buf.clear();
|
||||
write!(&mut buf, "{}", f64::MAX).unwrap()
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
use super::super::*;
|
||||
use core::num::flt2dec::strategy::dragon::*;
|
||||
use std::mem::MaybeUninit;
|
||||
use test::Bencher;
|
||||
|
||||
#[bench]
|
||||
fn bench_small_shortest(b: &mut Bencher) {
|
||||
let decoded = decode_finite(3.141592f64);
|
||||
let mut buf = [MaybeUninit::new(0); MAX_SIG_DIGITS];
|
||||
b.iter(|| {
|
||||
format_shortest(&decoded, &mut buf);
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_big_shortest(b: &mut Bencher) {
|
||||
let decoded = decode_finite(f64::MAX);
|
||||
let mut buf = [MaybeUninit::new(0); MAX_SIG_DIGITS];
|
||||
b.iter(|| {
|
||||
format_shortest(&decoded, &mut buf);
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_small_exact_3(b: &mut Bencher) {
|
||||
let decoded = decode_finite(3.141592f64);
|
||||
let mut buf = [MaybeUninit::new(0); 3];
|
||||
b.iter(|| {
|
||||
format_exact(&decoded, &mut buf, i16::MIN);
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_big_exact_3(b: &mut Bencher) {
|
||||
let decoded = decode_finite(f64::MAX);
|
||||
let mut buf = [MaybeUninit::new(0); 3];
|
||||
b.iter(|| {
|
||||
format_exact(&decoded, &mut buf, i16::MIN);
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_small_exact_12(b: &mut Bencher) {
|
||||
let decoded = decode_finite(3.141592f64);
|
||||
let mut buf = [MaybeUninit::new(0); 12];
|
||||
b.iter(|| {
|
||||
format_exact(&decoded, &mut buf, i16::MIN);
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_big_exact_12(b: &mut Bencher) {
|
||||
let decoded = decode_finite(f64::MAX);
|
||||
let mut buf = [MaybeUninit::new(0); 12];
|
||||
b.iter(|| {
|
||||
format_exact(&decoded, &mut buf, i16::MIN);
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_small_exact_inf(b: &mut Bencher) {
|
||||
let decoded = decode_finite(3.141592f64);
|
||||
let mut buf = [MaybeUninit::new(0); 1024];
|
||||
b.iter(|| {
|
||||
format_exact(&decoded, &mut buf, i16::MIN);
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_big_exact_inf(b: &mut Bencher) {
|
||||
let decoded = decode_finite(f64::MAX);
|
||||
let mut buf = [MaybeUninit::new(0); 1024];
|
||||
b.iter(|| {
|
||||
format_exact(&decoded, &mut buf, i16::MIN);
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
use super::super::*;
|
||||
use core::num::flt2dec::strategy::grisu::*;
|
||||
use std::mem::MaybeUninit;
|
||||
use test::Bencher;
|
||||
|
||||
pub fn decode_finite<T: DecodableFloat>(v: T) -> Decoded {
|
||||
match decode(v).1 {
|
||||
FullDecoded::Finite(decoded) => decoded,
|
||||
full_decoded => panic!("expected finite, got {:?} instead", full_decoded),
|
||||
}
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_small_shortest(b: &mut Bencher) {
|
||||
let decoded = decode_finite(3.141592f64);
|
||||
let mut buf = [MaybeUninit::new(0); MAX_SIG_DIGITS];
|
||||
b.iter(|| {
|
||||
format_shortest(&decoded, &mut buf);
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_big_shortest(b: &mut Bencher) {
|
||||
let decoded = decode_finite(f64::MAX);
|
||||
let mut buf = [MaybeUninit::new(0); MAX_SIG_DIGITS];
|
||||
b.iter(|| {
|
||||
format_shortest(&decoded, &mut buf);
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_small_exact_3(b: &mut Bencher) {
|
||||
let decoded = decode_finite(3.141592f64);
|
||||
let mut buf = [MaybeUninit::new(0); 3];
|
||||
b.iter(|| {
|
||||
format_exact(&decoded, &mut buf, i16::MIN);
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_big_exact_3(b: &mut Bencher) {
|
||||
let decoded = decode_finite(f64::MAX);
|
||||
let mut buf = [MaybeUninit::new(0); 3];
|
||||
b.iter(|| {
|
||||
format_exact(&decoded, &mut buf, i16::MIN);
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_small_exact_12(b: &mut Bencher) {
|
||||
let decoded = decode_finite(3.141592f64);
|
||||
let mut buf = [MaybeUninit::new(0); 12];
|
||||
b.iter(|| {
|
||||
format_exact(&decoded, &mut buf, i16::MIN);
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_big_exact_12(b: &mut Bencher) {
|
||||
let decoded = decode_finite(f64::MAX);
|
||||
let mut buf = [MaybeUninit::new(0); 12];
|
||||
b.iter(|| {
|
||||
format_exact(&decoded, &mut buf, i16::MIN);
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_small_exact_inf(b: &mut Bencher) {
|
||||
let decoded = decode_finite(3.141592f64);
|
||||
let mut buf = [MaybeUninit::new(0); 1024];
|
||||
b.iter(|| {
|
||||
format_exact(&decoded, &mut buf, i16::MIN);
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_big_exact_inf(b: &mut Bencher) {
|
||||
let decoded = decode_finite(f64::MAX);
|
||||
let mut buf = [MaybeUninit::new(0); 1024];
|
||||
b.iter(|| {
|
||||
format_exact(&decoded, &mut buf, i16::MIN);
|
||||
});
|
||||
}
|
||||
107
libgrust/rustc-lib/core/benches/num/mod.rs
Normal file
107
libgrust/rustc-lib/core/benches/num/mod.rs
Normal file
@@ -0,0 +1,107 @@
|
||||
mod dec2flt;
|
||||
mod flt2dec;
|
||||
|
||||
use std::str::FromStr;
|
||||
use test::Bencher;
|
||||
|
||||
const ASCII_NUMBERS: [&str; 19] = [
|
||||
"0",
|
||||
"1",
|
||||
"2",
|
||||
"43",
|
||||
"765",
|
||||
"76567",
|
||||
"987245987",
|
||||
"-4aa32",
|
||||
"1786235",
|
||||
"8723095",
|
||||
"f##5s",
|
||||
"83638730",
|
||||
"-2345",
|
||||
"562aa43",
|
||||
"-1",
|
||||
"-0",
|
||||
"abc",
|
||||
"xyz",
|
||||
"c0ffee",
|
||||
];
|
||||
|
||||
macro_rules! from_str_bench {
|
||||
($mac:ident, $t:ty) => {
|
||||
#[bench]
|
||||
fn $mac(b: &mut Bencher) {
|
||||
b.iter(|| {
|
||||
ASCII_NUMBERS
|
||||
.iter()
|
||||
.cycle()
|
||||
.take(5_000)
|
||||
.filter_map(|s| <$t>::from_str(s).ok())
|
||||
.max()
|
||||
})
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! from_str_radix_bench {
|
||||
($mac:ident, $t:ty, $radix:expr) => {
|
||||
#[bench]
|
||||
fn $mac(b: &mut Bencher) {
|
||||
b.iter(|| {
|
||||
ASCII_NUMBERS
|
||||
.iter()
|
||||
.cycle()
|
||||
.take(5_000)
|
||||
.filter_map(|s| <$t>::from_str_radix(s, $radix).ok())
|
||||
.max()
|
||||
})
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
from_str_bench!(bench_u8_from_str, u8);
|
||||
from_str_radix_bench!(bench_u8_from_str_radix_2, u8, 2);
|
||||
from_str_radix_bench!(bench_u8_from_str_radix_10, u8, 10);
|
||||
from_str_radix_bench!(bench_u8_from_str_radix_16, u8, 16);
|
||||
from_str_radix_bench!(bench_u8_from_str_radix_36, u8, 36);
|
||||
|
||||
from_str_bench!(bench_u16_from_str, u16);
|
||||
from_str_radix_bench!(bench_u16_from_str_radix_2, u16, 2);
|
||||
from_str_radix_bench!(bench_u16_from_str_radix_10, u16, 10);
|
||||
from_str_radix_bench!(bench_u16_from_str_radix_16, u16, 16);
|
||||
from_str_radix_bench!(bench_u16_from_str_radix_36, u16, 36);
|
||||
|
||||
from_str_bench!(bench_u32_from_str, u32);
|
||||
from_str_radix_bench!(bench_u32_from_str_radix_2, u32, 2);
|
||||
from_str_radix_bench!(bench_u32_from_str_radix_10, u32, 10);
|
||||
from_str_radix_bench!(bench_u32_from_str_radix_16, u32, 16);
|
||||
from_str_radix_bench!(bench_u32_from_str_radix_36, u32, 36);
|
||||
|
||||
from_str_bench!(bench_u64_from_str, u64);
|
||||
from_str_radix_bench!(bench_u64_from_str_radix_2, u64, 2);
|
||||
from_str_radix_bench!(bench_u64_from_str_radix_10, u64, 10);
|
||||
from_str_radix_bench!(bench_u64_from_str_radix_16, u64, 16);
|
||||
from_str_radix_bench!(bench_u64_from_str_radix_36, u64, 36);
|
||||
|
||||
from_str_bench!(bench_i8_from_str, i8);
|
||||
from_str_radix_bench!(bench_i8_from_str_radix_2, i8, 2);
|
||||
from_str_radix_bench!(bench_i8_from_str_radix_10, i8, 10);
|
||||
from_str_radix_bench!(bench_i8_from_str_radix_16, i8, 16);
|
||||
from_str_radix_bench!(bench_i8_from_str_radix_36, i8, 36);
|
||||
|
||||
from_str_bench!(bench_i16_from_str, i16);
|
||||
from_str_radix_bench!(bench_i16_from_str_radix_2, i16, 2);
|
||||
from_str_radix_bench!(bench_i16_from_str_radix_10, i16, 10);
|
||||
from_str_radix_bench!(bench_i16_from_str_radix_16, i16, 16);
|
||||
from_str_radix_bench!(bench_i16_from_str_radix_36, i16, 36);
|
||||
|
||||
from_str_bench!(bench_i32_from_str, i32);
|
||||
from_str_radix_bench!(bench_i32_from_str_radix_2, i32, 2);
|
||||
from_str_radix_bench!(bench_i32_from_str_radix_10, i32, 10);
|
||||
from_str_radix_bench!(bench_i32_from_str_radix_16, i32, 16);
|
||||
from_str_radix_bench!(bench_i32_from_str_radix_36, i32, 36);
|
||||
|
||||
from_str_bench!(bench_i64_from_str, i64);
|
||||
from_str_radix_bench!(bench_i64_from_str_radix_2, i64, 2);
|
||||
from_str_radix_bench!(bench_i64_from_str_radix_10, i64, 10);
|
||||
from_str_radix_bench!(bench_i64_from_str_radix_16, i64, 16);
|
||||
from_str_radix_bench!(bench_i64_from_str_radix_36, i64, 36);
|
||||
19
libgrust/rustc-lib/core/benches/ops.rs
Normal file
19
libgrust/rustc-lib/core/benches/ops.rs
Normal file
@@ -0,0 +1,19 @@
|
||||
use core::ops::*;
|
||||
use test::Bencher;
|
||||
|
||||
// Overhead of dtors
|
||||
|
||||
struct HasDtor {
|
||||
_x: isize,
|
||||
}
|
||||
|
||||
impl Drop for HasDtor {
|
||||
fn drop(&mut self) {}
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn alloc_obj_with_dtor(b: &mut Bencher) {
|
||||
b.iter(|| {
|
||||
HasDtor { _x: 10 };
|
||||
})
|
||||
}
|
||||
42
libgrust/rustc-lib/core/benches/pattern.rs
Normal file
42
libgrust/rustc-lib/core/benches/pattern.rs
Normal file
@@ -0,0 +1,42 @@
|
||||
use test::black_box;
|
||||
use test::Bencher;
|
||||
|
||||
#[bench]
|
||||
fn starts_with_char(b: &mut Bencher) {
|
||||
let text = black_box("kdjsfhlakfhlsghlkvcnljknfqiunvcijqenwodind");
|
||||
b.iter(|| {
|
||||
for _ in 0..1024 {
|
||||
black_box(text.starts_with('k'));
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn starts_with_str(b: &mut Bencher) {
|
||||
let text = black_box("kdjsfhlakfhlsghlkvcnljknfqiunvcijqenwodind");
|
||||
b.iter(|| {
|
||||
for _ in 0..1024 {
|
||||
black_box(text.starts_with("k"));
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn ends_with_char(b: &mut Bencher) {
|
||||
let text = black_box("kdjsfhlakfhlsghlkvcnljknfqiunvcijqenwodind");
|
||||
b.iter(|| {
|
||||
for _ in 0..1024 {
|
||||
black_box(text.ends_with('k'));
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn ends_with_str(b: &mut Bencher) {
|
||||
let text = black_box("kdjsfhlakfhlsghlkvcnljknfqiunvcijqenwodind");
|
||||
b.iter(|| {
|
||||
for _ in 0..1024 {
|
||||
black_box(text.ends_with("k"));
|
||||
}
|
||||
})
|
||||
}
|
||||
84
libgrust/rustc-lib/core/benches/slice.rs
Normal file
84
libgrust/rustc-lib/core/benches/slice.rs
Normal file
@@ -0,0 +1,84 @@
|
||||
use test::black_box;
|
||||
use test::Bencher;
|
||||
|
||||
enum Cache {
|
||||
L1,
|
||||
L2,
|
||||
L3,
|
||||
}
|
||||
|
||||
fn binary_search<F>(b: &mut Bencher, cache: Cache, mapper: F)
|
||||
where
|
||||
F: Fn(usize) -> usize,
|
||||
{
|
||||
let size = match cache {
|
||||
Cache::L1 => 1000, // 8kb
|
||||
Cache::L2 => 10_000, // 80kb
|
||||
Cache::L3 => 1_000_000, // 8Mb
|
||||
};
|
||||
let v = (0..size).map(&mapper).collect::<Vec<_>>();
|
||||
let mut r = 0usize;
|
||||
b.iter(move || {
|
||||
// LCG constants from https://en.wikipedia.org/wiki/Numerical_Recipes.
|
||||
r = r.wrapping_mul(1664525).wrapping_add(1013904223);
|
||||
// Lookup the whole range to get 50% hits and 50% misses.
|
||||
let i = mapper(r % size);
|
||||
black_box(v.binary_search(&i).is_ok());
|
||||
})
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn binary_search_l1(b: &mut Bencher) {
|
||||
binary_search(b, Cache::L1, |i| i * 2);
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn binary_search_l2(b: &mut Bencher) {
|
||||
binary_search(b, Cache::L2, |i| i * 2);
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn binary_search_l3(b: &mut Bencher) {
|
||||
binary_search(b, Cache::L3, |i| i * 2);
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn binary_search_l1_with_dups(b: &mut Bencher) {
|
||||
binary_search(b, Cache::L1, |i| i / 16 * 16);
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn binary_search_l2_with_dups(b: &mut Bencher) {
|
||||
binary_search(b, Cache::L2, |i| i / 16 * 16);
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn binary_search_l3_with_dups(b: &mut Bencher) {
|
||||
binary_search(b, Cache::L3, |i| i / 16 * 16);
|
||||
}
|
||||
|
||||
macro_rules! rotate {
|
||||
($fn:ident, $n:expr, $mapper:expr) => {
|
||||
#[bench]
|
||||
fn $fn(b: &mut Bencher) {
|
||||
let mut x = (0usize..$n).map(&$mapper).collect::<Vec<_>>();
|
||||
b.iter(|| {
|
||||
for s in 0..x.len() {
|
||||
x[..].rotate_right(s);
|
||||
}
|
||||
black_box(x[0].clone())
|
||||
})
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
struct Rgb(u8, u8, u8);
|
||||
|
||||
rotate!(rotate_u8, 32, |i| i as u8);
|
||||
rotate!(rotate_rgb, 32, |i| Rgb(i as u8, (i as u8).wrapping_add(7), (i as u8).wrapping_add(42)));
|
||||
rotate!(rotate_usize, 32, |i| i);
|
||||
rotate!(rotate_16_usize_4, 16, |i| [i; 4]);
|
||||
rotate!(rotate_16_usize_5, 16, |i| [i; 5]);
|
||||
rotate!(rotate_64_usize_4, 64, |i| [i; 4]);
|
||||
rotate!(rotate_64_usize_5, 64, |i| [i; 5]);
|
||||
208
libgrust/rustc-lib/core/src/alloc/global.rs
Normal file
208
libgrust/rustc-lib/core/src/alloc/global.rs
Normal file
@@ -0,0 +1,208 @@
|
||||
use crate::alloc::Layout;
|
||||
use crate::cmp;
|
||||
use crate::ptr;
|
||||
|
||||
/// A memory allocator that can be registered as the standard library’s default
|
||||
/// through the `#[global_allocator]` attribute.
|
||||
///
|
||||
/// Some of the methods require that a memory block be *currently
|
||||
/// allocated* via an allocator. This means that:
|
||||
///
|
||||
/// * the starting address for that memory block was previously
|
||||
/// returned by a previous call to an allocation method
|
||||
/// such as `alloc`, and
|
||||
///
|
||||
/// * the memory block has not been subsequently deallocated, where
|
||||
/// blocks are deallocated either by being passed to a deallocation
|
||||
/// method such as `dealloc` or by being
|
||||
/// passed to a reallocation method that returns a non-null pointer.
|
||||
///
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::alloc::{GlobalAlloc, Layout, alloc};
|
||||
/// use std::ptr::null_mut;
|
||||
///
|
||||
/// struct MyAllocator;
|
||||
///
|
||||
/// unsafe impl GlobalAlloc for MyAllocator {
|
||||
/// unsafe fn alloc(&self, _layout: Layout) -> *mut u8 { null_mut() }
|
||||
/// unsafe fn dealloc(&self, _ptr: *mut u8, _layout: Layout) {}
|
||||
/// }
|
||||
///
|
||||
/// #[global_allocator]
|
||||
/// static A: MyAllocator = MyAllocator;
|
||||
///
|
||||
/// fn main() {
|
||||
/// unsafe {
|
||||
/// assert!(alloc(Layout::new::<u32>()).is_null())
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The `GlobalAlloc` trait is an `unsafe` trait for a number of reasons, and
|
||||
/// implementors must ensure that they adhere to these contracts:
|
||||
///
|
||||
/// * It's undefined behavior if global allocators unwind. This restriction may
|
||||
/// be lifted in the future, but currently a panic from any of these
|
||||
/// functions may lead to memory unsafety.
|
||||
///
|
||||
/// * `Layout` queries and calculations in general must be correct. Callers of
|
||||
/// this trait are allowed to rely on the contracts defined on each method,
|
||||
/// and implementors must ensure such contracts remain true.
|
||||
#[stable(feature = "global_alloc", since = "1.28.0")]
|
||||
pub unsafe trait GlobalAlloc {
|
||||
/// Allocate memory as described by the given `layout`.
|
||||
///
|
||||
/// Returns a pointer to newly-allocated memory,
|
||||
/// or null to indicate allocation failure.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// This function is unsafe because undefined behavior can result
|
||||
/// if the caller does not ensure that `layout` has non-zero size.
|
||||
///
|
||||
/// (Extension subtraits might provide more specific bounds on
|
||||
/// behavior, e.g., guarantee a sentinel address or a null pointer
|
||||
/// in response to a zero-size allocation request.)
|
||||
///
|
||||
/// The allocated block of memory may or may not be initialized.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// Returning a null pointer indicates that either memory is exhausted
|
||||
/// or `layout` does not meet this allocator's size or alignment constraints.
|
||||
///
|
||||
/// Implementations are encouraged to return null on memory
|
||||
/// exhaustion rather than aborting, but this is not
|
||||
/// a strict requirement. (Specifically: it is *legal* to
|
||||
/// implement this trait atop an underlying native allocation
|
||||
/// library that aborts on memory exhaustion.)
|
||||
///
|
||||
/// Clients wishing to abort computation in response to an
|
||||
/// allocation error are encouraged to call the [`handle_alloc_error`] function,
|
||||
/// rather than directly invoking `panic!` or similar.
|
||||
///
|
||||
/// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html
|
||||
#[stable(feature = "global_alloc", since = "1.28.0")]
|
||||
unsafe fn alloc(&self, layout: Layout) -> *mut u8;
|
||||
|
||||
/// Deallocate the block of memory at the given `ptr` pointer with the given `layout`.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// This function is unsafe because undefined behavior can result
|
||||
/// if the caller does not ensure all of the following:
|
||||
///
|
||||
/// * `ptr` must denote a block of memory currently allocated via
|
||||
/// this allocator,
|
||||
///
|
||||
/// * `layout` must be the same layout that was used
|
||||
/// to allocate that block of memory,
|
||||
#[stable(feature = "global_alloc", since = "1.28.0")]
|
||||
unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout);
|
||||
|
||||
/// Behaves like `alloc`, but also ensures that the contents
|
||||
/// are set to zero before being returned.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// This function is unsafe for the same reasons that `alloc` is.
|
||||
/// However the allocated block of memory is guaranteed to be initialized.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// Returning a null pointer indicates that either memory is exhausted
|
||||
/// or `layout` does not meet allocator's size or alignment constraints,
|
||||
/// just as in `alloc`.
|
||||
///
|
||||
/// Clients wishing to abort computation in response to an
|
||||
/// allocation error are encouraged to call the [`handle_alloc_error`] function,
|
||||
/// rather than directly invoking `panic!` or similar.
|
||||
///
|
||||
/// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html
|
||||
#[stable(feature = "global_alloc", since = "1.28.0")]
|
||||
unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 {
|
||||
let size = layout.size();
|
||||
// SAFETY: the safety contract for `alloc` must be upheld by the caller.
|
||||
let ptr = unsafe { self.alloc(layout) };
|
||||
if !ptr.is_null() {
|
||||
// SAFETY: as allocation succeeded, the region from `ptr`
|
||||
// of size `size` is guaranteed to be valid for writes.
|
||||
unsafe { ptr::write_bytes(ptr, 0, size) };
|
||||
}
|
||||
ptr
|
||||
}
|
||||
|
||||
/// Shrink or grow a block of memory to the given `new_size`.
|
||||
/// The block is described by the given `ptr` pointer and `layout`.
|
||||
///
|
||||
/// If this returns a non-null pointer, then ownership of the memory block
|
||||
/// referenced by `ptr` has been transferred to this allocator.
|
||||
/// The memory may or may not have been deallocated,
|
||||
/// and should be considered unusable (unless of course it was
|
||||
/// transferred back to the caller again via the return value of
|
||||
/// this method). The new memory block is allocated with `layout`, but
|
||||
/// with the `size` updated to `new_size`.
|
||||
///
|
||||
/// If this method returns null, then ownership of the memory
|
||||
/// block has not been transferred to this allocator, and the
|
||||
/// contents of the memory block are unaltered.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// This function is unsafe because undefined behavior can result
|
||||
/// if the caller does not ensure all of the following:
|
||||
///
|
||||
/// * `ptr` must be currently allocated via this allocator,
|
||||
///
|
||||
/// * `layout` must be the same layout that was used
|
||||
/// to allocate that block of memory,
|
||||
///
|
||||
/// * `new_size` must be greater than zero.
|
||||
///
|
||||
/// * `new_size`, when rounded up to the nearest multiple of `layout.align()`,
|
||||
/// must not overflow (i.e., the rounded value must be less than `usize::MAX`).
|
||||
///
|
||||
/// (Extension subtraits might provide more specific bounds on
|
||||
/// behavior, e.g., guarantee a sentinel address or a null pointer
|
||||
/// in response to a zero-size allocation request.)
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// Returns null if the new layout does not meet the size
|
||||
/// and alignment constraints of the allocator, or if reallocation
|
||||
/// otherwise fails.
|
||||
///
|
||||
/// Implementations are encouraged to return null on memory
|
||||
/// exhaustion rather than panicking or aborting, but this is not
|
||||
/// a strict requirement. (Specifically: it is *legal* to
|
||||
/// implement this trait atop an underlying native allocation
|
||||
/// library that aborts on memory exhaustion.)
|
||||
///
|
||||
/// Clients wishing to abort computation in response to a
|
||||
/// reallocation error are encouraged to call the [`handle_alloc_error`] function,
|
||||
/// rather than directly invoking `panic!` or similar.
|
||||
///
|
||||
/// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html
|
||||
#[stable(feature = "global_alloc", since = "1.28.0")]
|
||||
unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 {
|
||||
// SAFETY: the caller must ensure that the `new_size` does not overflow.
|
||||
// `layout.align()` comes from a `Layout` and is thus guaranteed to be valid.
|
||||
let new_layout = unsafe { Layout::from_size_align_unchecked(new_size, layout.align()) };
|
||||
// SAFETY: the caller must ensure that `new_layout` is greater than zero.
|
||||
let new_ptr = unsafe { self.alloc(new_layout) };
|
||||
if !new_ptr.is_null() {
|
||||
// SAFETY: the previously allocated block cannot overlap the newly allocated block.
|
||||
// The safety contract for `dealloc` must be upheld by the caller.
|
||||
unsafe {
|
||||
ptr::copy_nonoverlapping(ptr, new_ptr, cmp::min(layout.size(), new_size));
|
||||
self.dealloc(ptr, layout);
|
||||
}
|
||||
}
|
||||
new_ptr
|
||||
}
|
||||
}
|
||||
410
libgrust/rustc-lib/core/src/alloc/layout.rs
Normal file
410
libgrust/rustc-lib/core/src/alloc/layout.rs
Normal file
@@ -0,0 +1,410 @@
|
||||
use crate::cmp;
|
||||
use crate::fmt;
|
||||
use crate::mem;
|
||||
use crate::num::NonZeroUsize;
|
||||
use crate::ptr::NonNull;
|
||||
|
||||
const fn size_align<T>() -> (usize, usize) {
|
||||
(mem::size_of::<T>(), mem::align_of::<T>())
|
||||
}
|
||||
|
||||
/// Layout of a block of memory.
|
||||
///
|
||||
/// An instance of `Layout` describes a particular layout of memory.
|
||||
/// You build a `Layout` up as an input to give to an allocator.
|
||||
///
|
||||
/// All layouts have an associated size and a power-of-two alignment.
|
||||
///
|
||||
/// (Note that layouts are *not* required to have non-zero size,
|
||||
/// even though `GlobalAlloc` requires that all memory requests
|
||||
/// be non-zero in size. A caller must either ensure that conditions
|
||||
/// like this are met, use specific allocators with looser
|
||||
/// requirements, or use the more lenient `AllocRef` interface.)
|
||||
#[stable(feature = "alloc_layout", since = "1.28.0")]
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
#[lang = "alloc_layout"]
|
||||
pub struct Layout {
|
||||
// size of the requested block of memory, measured in bytes.
|
||||
size_: usize,
|
||||
|
||||
// alignment of the requested block of memory, measured in bytes.
|
||||
// we ensure that this is always a power-of-two, because API's
|
||||
// like `posix_memalign` require it and it is a reasonable
|
||||
// constraint to impose on Layout constructors.
|
||||
//
|
||||
// (However, we do not analogously require `align >= sizeof(void*)`,
|
||||
// even though that is *also* a requirement of `posix_memalign`.)
|
||||
align_: NonZeroUsize,
|
||||
}
|
||||
|
||||
impl Layout {
|
||||
/// Constructs a `Layout` from a given `size` and `align`,
|
||||
/// or returns `LayoutErr` if any of the following conditions
|
||||
/// are not met:
|
||||
///
|
||||
/// * `align` must not be zero,
|
||||
///
|
||||
/// * `align` must be a power of two,
|
||||
///
|
||||
/// * `size`, when rounded up to the nearest multiple of `align`,
|
||||
/// must not overflow (i.e., the rounded value must be less than
|
||||
/// or equal to `usize::MAX`).
|
||||
#[stable(feature = "alloc_layout", since = "1.28.0")]
|
||||
#[rustc_const_unstable(feature = "const_alloc_layout", issue = "67521")]
|
||||
#[inline]
|
||||
pub const fn from_size_align(size: usize, align: usize) -> Result<Self, LayoutErr> {
|
||||
if !align.is_power_of_two() {
|
||||
return Err(LayoutErr { private: () });
|
||||
}
|
||||
|
||||
// (power-of-two implies align != 0.)
|
||||
|
||||
// Rounded up size is:
|
||||
// size_rounded_up = (size + align - 1) & !(align - 1);
|
||||
//
|
||||
// We know from above that align != 0. If adding (align - 1)
|
||||
// does not overflow, then rounding up will be fine.
|
||||
//
|
||||
// Conversely, &-masking with !(align - 1) will subtract off
|
||||
// only low-order-bits. Thus if overflow occurs with the sum,
|
||||
// the &-mask cannot subtract enough to undo that overflow.
|
||||
//
|
||||
// Above implies that checking for summation overflow is both
|
||||
// necessary and sufficient.
|
||||
if size > usize::MAX - (align - 1) {
|
||||
return Err(LayoutErr { private: () });
|
||||
}
|
||||
|
||||
// SAFETY: the conditions for `from_size_align_unchecked` have been
|
||||
// checked above.
|
||||
unsafe { Ok(Layout::from_size_align_unchecked(size, align)) }
|
||||
}
|
||||
|
||||
/// Creates a layout, bypassing all checks.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// This function is unsafe as it does not verify the preconditions from
|
||||
/// [`Layout::from_size_align`].
|
||||
#[stable(feature = "alloc_layout", since = "1.28.0")]
|
||||
#[rustc_const_stable(feature = "alloc_layout", since = "1.28.0")]
|
||||
#[inline]
|
||||
pub const unsafe fn from_size_align_unchecked(size: usize, align: usize) -> Self {
|
||||
// SAFETY: the caller must ensure that `align` is greater than zero.
|
||||
Layout { size_: size, align_: unsafe { NonZeroUsize::new_unchecked(align) } }
|
||||
}
|
||||
|
||||
/// The minimum size in bytes for a memory block of this layout.
|
||||
#[stable(feature = "alloc_layout", since = "1.28.0")]
|
||||
#[rustc_const_unstable(feature = "const_alloc_layout", issue = "67521")]
|
||||
#[inline]
|
||||
pub const fn size(&self) -> usize {
|
||||
self.size_
|
||||
}
|
||||
|
||||
/// The minimum byte alignment for a memory block of this layout.
|
||||
#[stable(feature = "alloc_layout", since = "1.28.0")]
|
||||
#[rustc_const_unstable(feature = "const_alloc_layout", issue = "67521")]
|
||||
#[inline]
|
||||
pub const fn align(&self) -> usize {
|
||||
self.align_.get()
|
||||
}
|
||||
|
||||
/// Constructs a `Layout` suitable for holding a value of type `T`.
|
||||
#[stable(feature = "alloc_layout", since = "1.28.0")]
|
||||
#[rustc_const_stable(feature = "alloc_layout_const_new", since = "1.42.0")]
|
||||
#[inline]
|
||||
pub const fn new<T>() -> Self {
|
||||
let (size, align) = size_align::<T>();
|
||||
// SAFETY: the align is guaranteed by Rust to be a power of two and
|
||||
// the size+align combo is guaranteed to fit in our address space. As a
|
||||
// result use the unchecked constructor here to avoid inserting code
|
||||
// that panics if it isn't optimized well enough.
|
||||
unsafe { Layout::from_size_align_unchecked(size, align) }
|
||||
}
|
||||
|
||||
/// Produces layout describing a record that could be used to
|
||||
/// allocate backing structure for `T` (which could be a trait
|
||||
/// or other unsized type like a slice).
|
||||
#[stable(feature = "alloc_layout", since = "1.28.0")]
|
||||
#[inline]
|
||||
pub fn for_value<T: ?Sized>(t: &T) -> Self {
|
||||
let (size, align) = (mem::size_of_val(t), mem::align_of_val(t));
|
||||
debug_assert!(Layout::from_size_align(size, align).is_ok());
|
||||
// SAFETY: see rationale in `new` for why this is using the unsafe variant
|
||||
unsafe { Layout::from_size_align_unchecked(size, align) }
|
||||
}
|
||||
|
||||
/// Produces layout describing a record that could be used to
|
||||
/// allocate backing structure for `T` (which could be a trait
|
||||
/// or other unsized type like a slice).
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// This function is only safe to call if the following conditions hold:
|
||||
///
|
||||
/// - If `T` is `Sized`, this function is always safe to call.
|
||||
/// - If the unsized tail of `T` is:
|
||||
/// - a [slice], then the length of the slice tail must be an intialized
|
||||
/// integer, and the size of the *entire value*
|
||||
/// (dynamic tail length + statically sized prefix) must fit in `isize`.
|
||||
/// - a [trait object], then the vtable part of the pointer must point
|
||||
/// to a valid vtable for the type `T` acquired by an unsizing coersion,
|
||||
/// and the size of the *entire value*
|
||||
/// (dynamic tail length + statically sized prefix) must fit in `isize`.
|
||||
/// - an (unstable) [extern type], then this function is always safe to
|
||||
/// call, but may panic or otherwise return the wrong value, as the
|
||||
/// extern type's layout is not known. This is the same behavior as
|
||||
/// [`Layout::for_value`] on a reference to an extern type tail.
|
||||
/// - otherwise, it is conservatively not allowed to call this function.
|
||||
///
|
||||
/// [slice]: ../../std/primitive.slice.html
|
||||
/// [trait object]: ../../book/ch17-02-trait-objects.html
|
||||
/// [extern type]: ../../unstable-book/language-features/extern-types.html
|
||||
#[unstable(feature = "layout_for_ptr", issue = "69835")]
|
||||
pub unsafe fn for_value_raw<T: ?Sized>(t: *const T) -> Self {
|
||||
// SAFETY: we pass along the prerequisites of these functions to the caller
|
||||
let (size, align) = unsafe { (mem::size_of_val_raw(t), mem::align_of_val_raw(t)) };
|
||||
debug_assert!(Layout::from_size_align(size, align).is_ok());
|
||||
// SAFETY: see rationale in `new` for why this is using the unsafe variant
|
||||
unsafe { Layout::from_size_align_unchecked(size, align) }
|
||||
}
|
||||
|
||||
/// Creates a `NonNull` that is dangling, but well-aligned for this Layout.
|
||||
///
|
||||
/// Note that the pointer value may potentially represent a valid pointer,
|
||||
/// which means this must not be used as a "not yet initialized"
|
||||
/// sentinel value. Types that lazily allocate must track initialization by
|
||||
/// some other means.
|
||||
#[unstable(feature = "alloc_layout_extra", issue = "55724")]
|
||||
#[rustc_const_unstable(feature = "alloc_layout_extra", issue = "55724")]
|
||||
#[inline]
|
||||
pub const fn dangling(&self) -> NonNull<u8> {
|
||||
// SAFETY: align is guaranteed to be non-zero
|
||||
unsafe { NonNull::new_unchecked(self.align() as *mut u8) }
|
||||
}
|
||||
|
||||
/// Creates a layout describing the record that can hold a value
|
||||
/// of the same layout as `self`, but that also is aligned to
|
||||
/// alignment `align` (measured in bytes).
|
||||
///
|
||||
/// If `self` already meets the prescribed alignment, then returns
|
||||
/// `self`.
|
||||
///
|
||||
/// Note that this method does not add any padding to the overall
|
||||
/// size, regardless of whether the returned layout has a different
|
||||
/// alignment. In other words, if `K` has size 16, `K.align_to(32)`
|
||||
/// will *still* have size 16.
|
||||
///
|
||||
/// Returns an error if the combination of `self.size()` and the given
|
||||
/// `align` violates the conditions listed in [`Layout::from_size_align`].
|
||||
#[stable(feature = "alloc_layout_manipulation", since = "1.44.0")]
|
||||
#[inline]
|
||||
pub fn align_to(&self, align: usize) -> Result<Self, LayoutErr> {
|
||||
Layout::from_size_align(self.size(), cmp::max(self.align(), align))
|
||||
}
|
||||
|
||||
/// Returns the amount of padding we must insert after `self`
|
||||
/// to ensure that the following address will satisfy `align`
|
||||
/// (measured in bytes).
|
||||
///
|
||||
/// e.g., if `self.size()` is 9, then `self.padding_needed_for(4)`
|
||||
/// returns 3, because that is the minimum number of bytes of
|
||||
/// padding required to get a 4-aligned address (assuming that the
|
||||
/// corresponding memory block starts at a 4-aligned address).
|
||||
///
|
||||
/// The return value of this function has no meaning if `align` is
|
||||
/// not a power-of-two.
|
||||
///
|
||||
/// Note that the utility of the returned value requires `align`
|
||||
/// to be less than or equal to the alignment of the starting
|
||||
/// address for the whole allocated block of memory. One way to
|
||||
/// satisfy this constraint is to ensure `align <= self.align()`.
|
||||
#[unstable(feature = "alloc_layout_extra", issue = "55724")]
|
||||
#[rustc_const_unstable(feature = "const_alloc_layout", issue = "67521")]
|
||||
#[inline]
|
||||
pub const fn padding_needed_for(&self, align: usize) -> usize {
|
||||
let len = self.size();
|
||||
|
||||
// Rounded up value is:
|
||||
// len_rounded_up = (len + align - 1) & !(align - 1);
|
||||
// and then we return the padding difference: `len_rounded_up - len`.
|
||||
//
|
||||
// We use modular arithmetic throughout:
|
||||
//
|
||||
// 1. align is guaranteed to be > 0, so align - 1 is always
|
||||
// valid.
|
||||
//
|
||||
// 2. `len + align - 1` can overflow by at most `align - 1`,
|
||||
// so the &-mask with `!(align - 1)` will ensure that in the
|
||||
// case of overflow, `len_rounded_up` will itself be 0.
|
||||
// Thus the returned padding, when added to `len`, yields 0,
|
||||
// which trivially satisfies the alignment `align`.
|
||||
//
|
||||
// (Of course, attempts to allocate blocks of memory whose
|
||||
// size and padding overflow in the above manner should cause
|
||||
// the allocator to yield an error anyway.)
|
||||
|
||||
let len_rounded_up = len.wrapping_add(align).wrapping_sub(1) & !align.wrapping_sub(1);
|
||||
len_rounded_up.wrapping_sub(len)
|
||||
}
|
||||
|
||||
/// Creates a layout by rounding the size of this layout up to a multiple
|
||||
/// of the layout's alignment.
|
||||
///
|
||||
/// This is equivalent to adding the result of `padding_needed_for`
|
||||
/// to the layout's current size.
|
||||
#[stable(feature = "alloc_layout_manipulation", since = "1.44.0")]
|
||||
#[inline]
|
||||
pub fn pad_to_align(&self) -> Layout {
|
||||
let pad = self.padding_needed_for(self.align());
|
||||
// This cannot overflow. Quoting from the invariant of Layout:
|
||||
// > `size`, when rounded up to the nearest multiple of `align`,
|
||||
// > must not overflow (i.e., the rounded value must be less than
|
||||
// > `usize::MAX`)
|
||||
let new_size = self.size() + pad;
|
||||
|
||||
Layout::from_size_align(new_size, self.align()).unwrap()
|
||||
}
|
||||
|
||||
/// Creates a layout describing the record for `n` instances of
|
||||
/// `self`, with a suitable amount of padding between each to
|
||||
/// ensure that each instance is given its requested size and
|
||||
/// alignment. On success, returns `(k, offs)` where `k` is the
|
||||
/// layout of the array and `offs` is the distance between the start
|
||||
/// of each element in the array.
|
||||
///
|
||||
/// On arithmetic overflow, returns `LayoutErr`.
|
||||
#[unstable(feature = "alloc_layout_extra", issue = "55724")]
|
||||
#[inline]
|
||||
pub fn repeat(&self, n: usize) -> Result<(Self, usize), LayoutErr> {
|
||||
// This cannot overflow. Quoting from the invariant of Layout:
|
||||
// > `size`, when rounded up to the nearest multiple of `align`,
|
||||
// > must not overflow (i.e., the rounded value must be less than
|
||||
// > `usize::MAX`)
|
||||
let padded_size = self.size() + self.padding_needed_for(self.align());
|
||||
let alloc_size = padded_size.checked_mul(n).ok_or(LayoutErr { private: () })?;
|
||||
|
||||
// SAFETY: self.align is already known to be valid and alloc_size has been
|
||||
// padded already.
|
||||
unsafe { Ok((Layout::from_size_align_unchecked(alloc_size, self.align()), padded_size)) }
|
||||
}
|
||||
|
||||
/// Creates a layout describing the record for `self` followed by
|
||||
/// `next`, including any necessary padding to ensure that `next`
|
||||
/// will be properly aligned, but *no trailing padding*.
|
||||
///
|
||||
/// In order to match C representation layout `repr(C)`, you should
|
||||
/// call `pad_to_align` after extending the layout with all fields.
|
||||
/// (There is no way to match the default Rust representation
|
||||
/// layout `repr(Rust)`, as it is unspecified.)
|
||||
///
|
||||
/// Note that the alignment of the resulting layout will be the maximum of
|
||||
/// those of `self` and `next`, in order to ensure alignment of both parts.
|
||||
///
|
||||
/// Returns `Ok((k, offset))`, where `k` is layout of the concatenated
|
||||
/// record and `offset` is the relative location, in bytes, of the
|
||||
/// start of the `next` embedded within the concatenated record
|
||||
/// (assuming that the record itself starts at offset 0).
|
||||
///
|
||||
/// On arithmetic overflow, returns `LayoutErr`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// To calculate the layout of a `#[repr(C)]` structure and the offsets of
|
||||
/// the fields from its fields' layouts:
|
||||
///
|
||||
/// ```rust
|
||||
/// # use std::alloc::{Layout, LayoutErr};
|
||||
/// pub fn repr_c(fields: &[Layout]) -> Result<(Layout, Vec<usize>), LayoutErr> {
|
||||
/// let mut offsets = Vec::new();
|
||||
/// let mut layout = Layout::from_size_align(0, 1)?;
|
||||
/// for &field in fields {
|
||||
/// let (new_layout, offset) = layout.extend(field)?;
|
||||
/// layout = new_layout;
|
||||
/// offsets.push(offset);
|
||||
/// }
|
||||
/// // Remember to finalize with `pad_to_align`!
|
||||
/// Ok((layout.pad_to_align(), offsets))
|
||||
/// }
|
||||
/// # // test that it works
|
||||
/// # #[repr(C)] struct S { a: u64, b: u32, c: u16, d: u32 }
|
||||
/// # let s = Layout::new::<S>();
|
||||
/// # let u16 = Layout::new::<u16>();
|
||||
/// # let u32 = Layout::new::<u32>();
|
||||
/// # let u64 = Layout::new::<u64>();
|
||||
/// # assert_eq!(repr_c(&[u64, u32, u16, u32]), Ok((s, vec![0, 8, 12, 16])));
|
||||
/// ```
|
||||
#[stable(feature = "alloc_layout_manipulation", since = "1.44.0")]
|
||||
#[inline]
|
||||
pub fn extend(&self, next: Self) -> Result<(Self, usize), LayoutErr> {
|
||||
let new_align = cmp::max(self.align(), next.align());
|
||||
let pad = self.padding_needed_for(next.align());
|
||||
|
||||
let offset = self.size().checked_add(pad).ok_or(LayoutErr { private: () })?;
|
||||
let new_size = offset.checked_add(next.size()).ok_or(LayoutErr { private: () })?;
|
||||
|
||||
let layout = Layout::from_size_align(new_size, new_align)?;
|
||||
Ok((layout, offset))
|
||||
}
|
||||
|
||||
/// Creates a layout describing the record for `n` instances of
|
||||
/// `self`, with no padding between each instance.
|
||||
///
|
||||
/// Note that, unlike `repeat`, `repeat_packed` does not guarantee
|
||||
/// that the repeated instances of `self` will be properly
|
||||
/// aligned, even if a given instance of `self` is properly
|
||||
/// aligned. In other words, if the layout returned by
|
||||
/// `repeat_packed` is used to allocate an array, it is not
|
||||
/// guaranteed that all elements in the array will be properly
|
||||
/// aligned.
|
||||
///
|
||||
/// On arithmetic overflow, returns `LayoutErr`.
|
||||
#[unstable(feature = "alloc_layout_extra", issue = "55724")]
|
||||
#[inline]
|
||||
pub fn repeat_packed(&self, n: usize) -> Result<Self, LayoutErr> {
|
||||
let size = self.size().checked_mul(n).ok_or(LayoutErr { private: () })?;
|
||||
Layout::from_size_align(size, self.align())
|
||||
}
|
||||
|
||||
/// Creates a layout describing the record for `self` followed by
|
||||
/// `next` with no additional padding between the two. Since no
|
||||
/// padding is inserted, the alignment of `next` is irrelevant,
|
||||
/// and is not incorporated *at all* into the resulting layout.
|
||||
///
|
||||
/// On arithmetic overflow, returns `LayoutErr`.
|
||||
#[unstable(feature = "alloc_layout_extra", issue = "55724")]
|
||||
#[inline]
|
||||
pub fn extend_packed(&self, next: Self) -> Result<Self, LayoutErr> {
|
||||
let new_size = self.size().checked_add(next.size()).ok_or(LayoutErr { private: () })?;
|
||||
Layout::from_size_align(new_size, self.align())
|
||||
}
|
||||
|
||||
/// Creates a layout describing the record for a `[T; n]`.
|
||||
///
|
||||
/// On arithmetic overflow, returns `LayoutErr`.
|
||||
#[stable(feature = "alloc_layout_manipulation", since = "1.44.0")]
|
||||
#[inline]
|
||||
pub fn array<T>(n: usize) -> Result<Self, LayoutErr> {
|
||||
let (layout, offset) = Layout::new::<T>().repeat(n)?;
|
||||
debug_assert_eq!(offset, mem::size_of::<T>());
|
||||
Ok(layout.pad_to_align())
|
||||
}
|
||||
}
|
||||
|
||||
/// The parameters given to `Layout::from_size_align`
|
||||
/// or some other `Layout` constructor
|
||||
/// do not satisfy its documented constraints.
|
||||
#[stable(feature = "alloc_layout", since = "1.28.0")]
|
||||
#[derive(Clone, PartialEq, Eq, Debug)]
|
||||
pub struct LayoutErr {
|
||||
private: (),
|
||||
}
|
||||
|
||||
// (we need this for downstream impl of trait Error)
|
||||
#[stable(feature = "alloc_layout", since = "1.28.0")]
|
||||
impl fmt::Display for LayoutErr {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.write_str("invalid parameters to Layout::from_size_align")
|
||||
}
|
||||
}
|
||||
392
libgrust/rustc-lib/core/src/alloc/mod.rs
Normal file
392
libgrust/rustc-lib/core/src/alloc/mod.rs
Normal file
@@ -0,0 +1,392 @@
|
||||
//! Memory allocation APIs
|
||||
|
||||
#![stable(feature = "alloc_module", since = "1.28.0")]
|
||||
|
||||
mod global;
|
||||
mod layout;
|
||||
|
||||
#[stable(feature = "global_alloc", since = "1.28.0")]
|
||||
pub use self::global::GlobalAlloc;
|
||||
#[stable(feature = "alloc_layout", since = "1.28.0")]
|
||||
pub use self::layout::{Layout, LayoutErr};
|
||||
|
||||
use crate::fmt;
|
||||
use crate::ptr::{self, NonNull};
|
||||
|
||||
/// The `AllocError` error indicates an allocation failure
|
||||
/// that may be due to resource exhaustion or to
|
||||
/// something wrong when combining the given input arguments with this
|
||||
/// allocator.
|
||||
#[unstable(feature = "allocator_api", issue = "32838")]
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
||||
pub struct AllocError;
|
||||
|
||||
// (we need this for downstream impl of trait Error)
|
||||
#[unstable(feature = "allocator_api", issue = "32838")]
|
||||
impl fmt::Display for AllocError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.write_str("memory allocation failed")
|
||||
}
|
||||
}
|
||||
|
||||
/// An implementation of `AllocRef` can allocate, grow, shrink, and deallocate arbitrary blocks of
|
||||
/// data described via [`Layout`][].
|
||||
///
|
||||
/// `AllocRef` is designed to be implemented on ZSTs, references, or smart pointers because having
|
||||
/// an allocator like `MyAlloc([u8; N])` cannot be moved, without updating the pointers to the
|
||||
/// allocated memory.
|
||||
///
|
||||
/// Unlike [`GlobalAlloc`][], zero-sized allocations are allowed in `AllocRef`. If an underlying
|
||||
/// allocator does not support this (like jemalloc) or return a null pointer (such as
|
||||
/// `libc::malloc`), this must be caught by the implementation.
|
||||
///
|
||||
/// ### Currently allocated memory
|
||||
///
|
||||
/// Some of the methods require that a memory block be *currently allocated* via an allocator. This
|
||||
/// means that:
|
||||
///
|
||||
/// * the starting address for that memory block was previously returned by [`alloc`], [`grow`], or
|
||||
/// [`shrink`], and
|
||||
///
|
||||
/// * the memory block has not been subsequently deallocated, where blocks are either deallocated
|
||||
/// directly by being passed to [`dealloc`] or were changed by being passed to [`grow`] or
|
||||
/// [`shrink`] that returns `Ok`. If `grow` or `shrink` have returned `Err`, the passed pointer
|
||||
/// remains valid.
|
||||
///
|
||||
/// [`alloc`]: AllocRef::alloc
|
||||
/// [`grow`]: AllocRef::grow
|
||||
/// [`shrink`]: AllocRef::shrink
|
||||
/// [`dealloc`]: AllocRef::dealloc
|
||||
///
|
||||
/// ### Memory fitting
|
||||
///
|
||||
/// Some of the methods require that a layout *fit* a memory block. What it means for a layout to
|
||||
/// "fit" a memory block means (or equivalently, for a memory block to "fit" a layout) is that the
|
||||
/// following conditions must hold:
|
||||
///
|
||||
/// * The block must be allocated with the same alignment as [`layout.align()`], and
|
||||
///
|
||||
/// * The provided [`layout.size()`] must fall in the range `min ..= max`, where:
|
||||
/// - `min` is the size of the layout most recently used to allocate the block, and
|
||||
/// - `max` is the latest actual size returned from [`alloc`], [`grow`], or [`shrink`].
|
||||
///
|
||||
/// [`layout.align()`]: Layout::align
|
||||
/// [`layout.size()`]: Layout::size
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// * Memory blocks returned from an allocator must point to valid memory and retain their validity
|
||||
/// until the instance and all of its clones are dropped,
|
||||
///
|
||||
/// * cloning or moving the allocator must not invalidate memory blocks returned from this
|
||||
/// allocator. A cloned allocator must behave like the same allocator, and
|
||||
///
|
||||
/// * any pointer to a memory block which is [*currently allocated*] may be passed to any other
|
||||
/// method of the allocator.
|
||||
///
|
||||
/// [*currently allocated*]: #currently-allocated-memory
|
||||
#[unstable(feature = "allocator_api", issue = "32838")]
|
||||
pub unsafe trait AllocRef {
|
||||
/// Attempts to allocate a block of memory.
|
||||
///
|
||||
/// On success, returns a [`NonNull<[u8]>`][NonNull] meeting the size and alignment guarantees of `layout`.
|
||||
///
|
||||
/// The returned block may have a larger size than specified by `layout.size()`, and may or may
|
||||
/// not have its contents initialized.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// Returning `Err` indicates that either memory is exhausted or `layout` does not meet
|
||||
/// allocator's size or alignment constraints.
|
||||
///
|
||||
/// Implementations are encouraged to return `Err` on memory exhaustion rather than panicking or
|
||||
/// aborting, but this is not a strict requirement. (Specifically: it is *legal* to implement
|
||||
/// this trait atop an underlying native allocation library that aborts on memory exhaustion.)
|
||||
///
|
||||
/// Clients wishing to abort computation in response to an allocation error are encouraged to
|
||||
/// call the [`handle_alloc_error`] function, rather than directly invoking `panic!` or similar.
|
||||
///
|
||||
/// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html
|
||||
fn alloc(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError>;
|
||||
|
||||
/// Behaves like `alloc`, but also ensures that the returned memory is zero-initialized.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// Returning `Err` indicates that either memory is exhausted or `layout` does not meet
|
||||
/// allocator's size or alignment constraints.
|
||||
///
|
||||
/// Implementations are encouraged to return `Err` on memory exhaustion rather than panicking or
|
||||
/// aborting, but this is not a strict requirement. (Specifically: it is *legal* to implement
|
||||
/// this trait atop an underlying native allocation library that aborts on memory exhaustion.)
|
||||
///
|
||||
/// Clients wishing to abort computation in response to an allocation error are encouraged to
|
||||
/// call the [`handle_alloc_error`] function, rather than directly invoking `panic!` or similar.
|
||||
///
|
||||
/// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html
|
||||
fn alloc_zeroed(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
|
||||
let ptr = self.alloc(layout)?;
|
||||
// SAFETY: `alloc` returns a valid memory block
|
||||
unsafe { ptr.as_non_null_ptr().as_ptr().write_bytes(0, ptr.len()) }
|
||||
Ok(ptr)
|
||||
}
|
||||
|
||||
/// Deallocates the memory referenced by `ptr`.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// * `ptr` must denote a block of memory [*currently allocated*] via this allocator, and
|
||||
/// * `layout` must [*fit*] that block of memory.
|
||||
///
|
||||
/// [*currently allocated*]: #currently-allocated-memory
|
||||
/// [*fit*]: #memory-fitting
|
||||
unsafe fn dealloc(&self, ptr: NonNull<u8>, layout: Layout);
|
||||
|
||||
/// Attempts to extend the memory block.
|
||||
///
|
||||
/// Returns a new [`NonNull<[u8]>`][NonNull] containing a pointer and the actual size of the allocated
|
||||
/// memory. The pointer is suitable for holding data described by `new_layout`. To accomplish
|
||||
/// this, the allocator may extend the allocation referenced by `ptr` to fit the new layout.
|
||||
///
|
||||
/// If this returns `Ok`, then ownership of the memory block referenced by `ptr` has been
|
||||
/// transferred to this allocator. The memory may or may not have been freed, and should be
|
||||
/// considered unusable unless it was transferred back to the caller again via the return value
|
||||
/// of this method.
|
||||
///
|
||||
/// If this method returns `Err`, then ownership of the memory block has not been transferred to
|
||||
/// this allocator, and the contents of the memory block are unaltered.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// * `ptr` must denote a block of memory [*currently allocated*] via this allocator.
|
||||
/// * `old_layout` must [*fit*] that block of memory (The `new_layout` argument need not fit it.).
|
||||
/// * `new_layout.size()` must be greater than or equal to `old_layout.size()`.
|
||||
///
|
||||
/// [*currently allocated*]: #currently-allocated-memory
|
||||
/// [*fit*]: #memory-fitting
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// Returns `Err` if the new layout does not meet the allocator's size and alignment
|
||||
/// constraints of the allocator, or if growing otherwise fails.
|
||||
///
|
||||
/// Implementations are encouraged to return `Err` on memory exhaustion rather than panicking or
|
||||
/// aborting, but this is not a strict requirement. (Specifically: it is *legal* to implement
|
||||
/// this trait atop an underlying native allocation library that aborts on memory exhaustion.)
|
||||
///
|
||||
/// Clients wishing to abort computation in response to an allocation error are encouraged to
|
||||
/// call the [`handle_alloc_error`] function, rather than directly invoking `panic!` or similar.
|
||||
///
|
||||
/// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html
|
||||
unsafe fn grow(
|
||||
&self,
|
||||
ptr: NonNull<u8>,
|
||||
old_layout: Layout,
|
||||
new_layout: Layout,
|
||||
) -> Result<NonNull<[u8]>, AllocError> {
|
||||
debug_assert!(
|
||||
new_layout.size() >= old_layout.size(),
|
||||
"`new_layout.size()` must be greater than or equal to `old_layout.size()`"
|
||||
);
|
||||
|
||||
let new_ptr = self.alloc(new_layout)?;
|
||||
|
||||
// SAFETY: because `new_layout.size()` must be greater than or equal to
|
||||
// `old_layout.size()`, both the old and new memory allocation are valid for reads and
|
||||
// writes for `old_layout.size()` bytes. Also, because the old allocation wasn't yet
|
||||
// deallocated, it cannot overlap `new_ptr`. Thus, the call to `copy_nonoverlapping` is
|
||||
// safe. The safety contract for `dealloc` must be upheld by the caller.
|
||||
unsafe {
|
||||
ptr::copy_nonoverlapping(ptr.as_ptr(), new_ptr.as_mut_ptr(), old_layout.size());
|
||||
self.dealloc(ptr, old_layout);
|
||||
}
|
||||
|
||||
Ok(new_ptr)
|
||||
}
|
||||
|
||||
/// Behaves like `grow`, but also ensures that the new contents are set to zero before being
|
||||
/// returned.
|
||||
///
|
||||
/// The memory block will contain the following contents after a successful call to
|
||||
/// `grow_zeroed`:
|
||||
/// * Bytes `0..old_layout.size()` are preserved from the original allocation.
|
||||
/// * Bytes `old_layout.size()..old_size` will either be preserved or zeroed, depending on
|
||||
/// the allocator implementation. `old_size` refers to the size of the memory block prior
|
||||
/// to the `grow_zeroed` call, which may be larger than the size that was originally
|
||||
/// requested when it was allocated.
|
||||
/// * Bytes `old_size..new_size` are zeroed. `new_size` refers to the size of the memory
|
||||
/// block returned by the `grow_zeroed` call.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// * `ptr` must denote a block of memory [*currently allocated*] via this allocator.
|
||||
/// * `old_layout` must [*fit*] that block of memory (The `new_layout` argument need not fit it.).
|
||||
/// * `new_layout.size()` must be greater than or equal to `old_layout.size()`.
|
||||
///
|
||||
/// [*currently allocated*]: #currently-allocated-memory
|
||||
/// [*fit*]: #memory-fitting
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// Returns `Err` if the new layout does not meet the allocator's size and alignment
|
||||
/// constraints of the allocator, or if growing otherwise fails.
|
||||
///
|
||||
/// Implementations are encouraged to return `Err` on memory exhaustion rather than panicking or
|
||||
/// aborting, but this is not a strict requirement. (Specifically: it is *legal* to implement
|
||||
/// this trait atop an underlying native allocation library that aborts on memory exhaustion.)
|
||||
///
|
||||
/// Clients wishing to abort computation in response to an allocation error are encouraged to
|
||||
/// call the [`handle_alloc_error`] function, rather than directly invoking `panic!` or similar.
|
||||
///
|
||||
/// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html
|
||||
unsafe fn grow_zeroed(
|
||||
&self,
|
||||
ptr: NonNull<u8>,
|
||||
old_layout: Layout,
|
||||
new_layout: Layout,
|
||||
) -> Result<NonNull<[u8]>, AllocError> {
|
||||
debug_assert!(
|
||||
new_layout.size() >= old_layout.size(),
|
||||
"`new_layout.size()` must be greater than or equal to `old_layout.size()`"
|
||||
);
|
||||
|
||||
let new_ptr = self.alloc_zeroed(new_layout)?;
|
||||
|
||||
// SAFETY: because `new_layout.size()` must be greater than or equal to
|
||||
// `old_layout.size()`, both the old and new memory allocation are valid for reads and
|
||||
// writes for `old_layout.size()` bytes. Also, because the old allocation wasn't yet
|
||||
// deallocated, it cannot overlap `new_ptr`. Thus, the call to `copy_nonoverlapping` is
|
||||
// safe. The safety contract for `dealloc` must be upheld by the caller.
|
||||
unsafe {
|
||||
ptr::copy_nonoverlapping(ptr.as_ptr(), new_ptr.as_mut_ptr(), old_layout.size());
|
||||
self.dealloc(ptr, old_layout);
|
||||
}
|
||||
|
||||
Ok(new_ptr)
|
||||
}
|
||||
|
||||
/// Attempts to shrink the memory block.
|
||||
///
|
||||
/// Returns a new [`NonNull<[u8]>`][NonNull] containing a pointer and the actual size of the allocated
|
||||
/// memory. The pointer is suitable for holding data described by `new_layout`. To accomplish
|
||||
/// this, the allocator may shrink the allocation referenced by `ptr` to fit the new layout.
|
||||
///
|
||||
/// If this returns `Ok`, then ownership of the memory block referenced by `ptr` has been
|
||||
/// transferred to this allocator. The memory may or may not have been freed, and should be
|
||||
/// considered unusable unless it was transferred back to the caller again via the return value
|
||||
/// of this method.
|
||||
///
|
||||
/// If this method returns `Err`, then ownership of the memory block has not been transferred to
|
||||
/// this allocator, and the contents of the memory block are unaltered.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// * `ptr` must denote a block of memory [*currently allocated*] via this allocator.
|
||||
/// * `old_layout` must [*fit*] that block of memory (The `new_layout` argument need not fit it.).
|
||||
/// * `new_layout.size()` must be smaller than or equal to `old_layout.size()`.
|
||||
///
|
||||
/// [*currently allocated*]: #currently-allocated-memory
|
||||
/// [*fit*]: #memory-fitting
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// Returns `Err` if the new layout does not meet the allocator's size and alignment
|
||||
/// constraints of the allocator, or if shrinking otherwise fails.
|
||||
///
|
||||
/// Implementations are encouraged to return `Err` on memory exhaustion rather than panicking or
|
||||
/// aborting, but this is not a strict requirement. (Specifically: it is *legal* to implement
|
||||
/// this trait atop an underlying native allocation library that aborts on memory exhaustion.)
|
||||
///
|
||||
/// Clients wishing to abort computation in response to an allocation error are encouraged to
|
||||
/// call the [`handle_alloc_error`] function, rather than directly invoking `panic!` or similar.
|
||||
///
|
||||
/// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html
|
||||
unsafe fn shrink(
|
||||
&self,
|
||||
ptr: NonNull<u8>,
|
||||
old_layout: Layout,
|
||||
new_layout: Layout,
|
||||
) -> Result<NonNull<[u8]>, AllocError> {
|
||||
debug_assert!(
|
||||
new_layout.size() <= old_layout.size(),
|
||||
"`new_layout.size()` must be smaller than or equal to `old_layout.size()`"
|
||||
);
|
||||
|
||||
let new_ptr = self.alloc(new_layout)?;
|
||||
|
||||
// SAFETY: because `new_layout.size()` must be lower than or equal to
|
||||
// `old_layout.size()`, both the old and new memory allocation are valid for reads and
|
||||
// writes for `new_layout.size()` bytes. Also, because the old allocation wasn't yet
|
||||
// deallocated, it cannot overlap `new_ptr`. Thus, the call to `copy_nonoverlapping` is
|
||||
// safe. The safety contract for `dealloc` must be upheld by the caller.
|
||||
unsafe {
|
||||
ptr::copy_nonoverlapping(ptr.as_ptr(), new_ptr.as_mut_ptr(), new_layout.size());
|
||||
self.dealloc(ptr, old_layout);
|
||||
}
|
||||
|
||||
Ok(new_ptr)
|
||||
}
|
||||
|
||||
/// Creates a "by reference" adaptor for this instance of `AllocRef`.
|
||||
///
|
||||
/// The returned adaptor also implements `AllocRef` and will simply borrow this.
|
||||
#[inline(always)]
|
||||
fn by_ref(&self) -> &Self {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "allocator_api", issue = "32838")]
|
||||
unsafe impl<A> AllocRef for &A
|
||||
where
|
||||
A: AllocRef + ?Sized,
|
||||
{
|
||||
#[inline]
|
||||
fn alloc(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
|
||||
(**self).alloc(layout)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn alloc_zeroed(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
|
||||
(**self).alloc_zeroed(layout)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn dealloc(&self, ptr: NonNull<u8>, layout: Layout) {
|
||||
// SAFETY: the safety contract must be upheld by the caller
|
||||
unsafe { (**self).dealloc(ptr, layout) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn grow(
|
||||
&self,
|
||||
ptr: NonNull<u8>,
|
||||
old_layout: Layout,
|
||||
new_layout: Layout,
|
||||
) -> Result<NonNull<[u8]>, AllocError> {
|
||||
// SAFETY: the safety contract must be upheld by the caller
|
||||
unsafe { (**self).grow(ptr, old_layout, new_layout) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn grow_zeroed(
|
||||
&self,
|
||||
ptr: NonNull<u8>,
|
||||
old_layout: Layout,
|
||||
new_layout: Layout,
|
||||
) -> Result<NonNull<[u8]>, AllocError> {
|
||||
// SAFETY: the safety contract must be upheld by the caller
|
||||
unsafe { (**self).grow_zeroed(ptr, old_layout, new_layout) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn shrink(
|
||||
&self,
|
||||
ptr: NonNull<u8>,
|
||||
old_layout: Layout,
|
||||
new_layout: Layout,
|
||||
) -> Result<NonNull<[u8]>, AllocError> {
|
||||
// SAFETY: the safety contract must be upheld by the caller
|
||||
unsafe { (**self).shrink(ptr, old_layout, new_layout) }
|
||||
}
|
||||
}
|
||||
517
libgrust/rustc-lib/core/src/any.rs
Normal file
517
libgrust/rustc-lib/core/src/any.rs
Normal file
@@ -0,0 +1,517 @@
|
||||
//! This module implements the `Any` trait, which enables dynamic typing
|
||||
//! of any `'static` type through runtime reflection.
|
||||
//!
|
||||
//! `Any` itself can be used to get a `TypeId`, and has more features when used
|
||||
//! as a trait object. As `&dyn Any` (a borrowed trait object), it has the `is`
|
||||
//! and `downcast_ref` methods, to test if the contained value is of a given type,
|
||||
//! and to get a reference to the inner value as a type. As `&mut dyn Any`, there
|
||||
//! is also the `downcast_mut` method, for getting a mutable reference to the
|
||||
//! inner value. `Box<dyn Any>` adds the `downcast` method, which attempts to
|
||||
//! convert to a `Box<T>`. See the [`Box`] documentation for the full details.
|
||||
//!
|
||||
//! Note that `&dyn Any` is limited to testing whether a value is of a specified
|
||||
//! concrete type, and cannot be used to test whether a type implements a trait.
|
||||
//!
|
||||
//! [`Box`]: ../../std/boxed/struct.Box.html
|
||||
//!
|
||||
//! # Examples
|
||||
//!
|
||||
//! Consider a situation where we want to log out a value passed to a function.
|
||||
//! We know the value we're working on implements Debug, but we don't know its
|
||||
//! concrete type. We want to give special treatment to certain types: in this
|
||||
//! case printing out the length of String values prior to their value.
|
||||
//! We don't know the concrete type of our value at compile time, so we need to
|
||||
//! use runtime reflection instead.
|
||||
//!
|
||||
//! ```rust
|
||||
//! use std::fmt::Debug;
|
||||
//! use std::any::Any;
|
||||
//!
|
||||
//! // Logger function for any type that implements Debug.
|
||||
//! fn log<T: Any + Debug>(value: &T) {
|
||||
//! let value_any = value as &dyn Any;
|
||||
//!
|
||||
//! // Try to convert our value to a `String`. If successful, we want to
|
||||
//! // output the String`'s length as well as its value. If not, it's a
|
||||
//! // different type: just print it out unadorned.
|
||||
//! match value_any.downcast_ref::<String>() {
|
||||
//! Some(as_string) => {
|
||||
//! println!("String ({}): {}", as_string.len(), as_string);
|
||||
//! }
|
||||
//! None => {
|
||||
//! println!("{:?}", value);
|
||||
//! }
|
||||
//! }
|
||||
//! }
|
||||
//!
|
||||
//! // This function wants to log its parameter out prior to doing work with it.
|
||||
//! fn do_work<T: Any + Debug>(value: &T) {
|
||||
//! log(value);
|
||||
//! // ...do some other work
|
||||
//! }
|
||||
//!
|
||||
//! fn main() {
|
||||
//! let my_string = "Hello World".to_string();
|
||||
//! do_work(&my_string);
|
||||
//!
|
||||
//! let my_i8: i8 = 100;
|
||||
//! do_work(&my_i8);
|
||||
//! }
|
||||
//! ```
|
||||
|
||||
#![stable(feature = "rust1", since = "1.0.0")]
|
||||
|
||||
use crate::fmt;
|
||||
use crate::intrinsics;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Any trait
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// A trait to emulate dynamic typing.
|
||||
///
|
||||
/// Most types implement `Any`. However, any type which contains a non-`'static` reference does not.
|
||||
/// See the [module-level documentation][mod] for more details.
|
||||
///
|
||||
/// [mod]: crate::any
|
||||
// This trait is not unsafe, though we rely on the specifics of it's sole impl's
|
||||
// `type_id` function in unsafe code (e.g., `downcast`). Normally, that would be
|
||||
// a problem, but because the only impl of `Any` is a blanket implementation, no
|
||||
// other code can implement `Any`.
|
||||
//
|
||||
// We could plausibly make this trait unsafe -- it would not cause breakage,
|
||||
// since we control all the implementations -- but we choose not to as that's
|
||||
// both not really necessary and may confuse users about the distinction of
|
||||
// unsafe traits and unsafe methods (i.e., `type_id` would still be safe to call,
|
||||
// but we would likely want to indicate as such in documentation).
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub trait Any: 'static {
|
||||
/// Gets the `TypeId` of `self`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::any::{Any, TypeId};
|
||||
///
|
||||
/// fn is_string(s: &dyn Any) -> bool {
|
||||
/// TypeId::of::<String>() == s.type_id()
|
||||
/// }
|
||||
///
|
||||
/// assert_eq!(is_string(&0), false);
|
||||
/// assert_eq!(is_string(&"cookie monster".to_string()), true);
|
||||
/// ```
|
||||
#[stable(feature = "get_type_id", since = "1.34.0")]
|
||||
fn type_id(&self) -> TypeId;
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: 'static + ?Sized> Any for T {
|
||||
fn type_id(&self) -> TypeId {
|
||||
TypeId::of::<T>()
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Extension methods for Any trait objects.
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl fmt::Debug for dyn Any {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.pad("Any")
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure that the result of e.g., joining a thread can be printed and
|
||||
// hence used with `unwrap`. May eventually no longer be needed if
|
||||
// dispatch works with upcasting.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl fmt::Debug for dyn Any + Send {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.pad("Any")
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "any_send_sync_methods", since = "1.28.0")]
|
||||
impl fmt::Debug for dyn Any + Send + Sync {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.pad("Any")
|
||||
}
|
||||
}
|
||||
|
||||
impl dyn Any {
|
||||
/// Returns `true` if the boxed type is the same as `T`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::any::Any;
|
||||
///
|
||||
/// fn is_string(s: &dyn Any) {
|
||||
/// if s.is::<String>() {
|
||||
/// println!("It's a string!");
|
||||
/// } else {
|
||||
/// println!("Not a string...");
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// is_string(&0);
|
||||
/// is_string(&"cookie monster".to_string());
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[inline]
|
||||
pub fn is<T: Any>(&self) -> bool {
|
||||
// Get `TypeId` of the type this function is instantiated with.
|
||||
let t = TypeId::of::<T>();
|
||||
|
||||
// Get `TypeId` of the type in the trait object (`self`).
|
||||
let concrete = self.type_id();
|
||||
|
||||
// Compare both `TypeId`s on equality.
|
||||
t == concrete
|
||||
}
|
||||
|
||||
/// Returns some reference to the boxed value if it is of type `T`, or
|
||||
/// `None` if it isn't.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::any::Any;
|
||||
///
|
||||
/// fn print_if_string(s: &dyn Any) {
|
||||
/// if let Some(string) = s.downcast_ref::<String>() {
|
||||
/// println!("It's a string({}): '{}'", string.len(), string);
|
||||
/// } else {
|
||||
/// println!("Not a string...");
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// print_if_string(&0);
|
||||
/// print_if_string(&"cookie monster".to_string());
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[inline]
|
||||
pub fn downcast_ref<T: Any>(&self) -> Option<&T> {
|
||||
if self.is::<T>() {
|
||||
// SAFETY: just checked whether we are pointing to the correct type, and we can rely on
|
||||
// that check for memory safety because we have implemented Any for all types; no other
|
||||
// impls can exist as they would conflict with our impl.
|
||||
unsafe { Some(&*(self as *const dyn Any as *const T)) }
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns some mutable reference to the boxed value if it is of type `T`, or
|
||||
/// `None` if it isn't.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::any::Any;
|
||||
///
|
||||
/// fn modify_if_u32(s: &mut dyn Any) {
|
||||
/// if let Some(num) = s.downcast_mut::<u32>() {
|
||||
/// *num = 42;
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// let mut x = 10u32;
|
||||
/// let mut s = "starlord".to_string();
|
||||
///
|
||||
/// modify_if_u32(&mut x);
|
||||
/// modify_if_u32(&mut s);
|
||||
///
|
||||
/// assert_eq!(x, 42);
|
||||
/// assert_eq!(&s, "starlord");
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[inline]
|
||||
pub fn downcast_mut<T: Any>(&mut self) -> Option<&mut T> {
|
||||
if self.is::<T>() {
|
||||
// SAFETY: just checked whether we are pointing to the correct type, and we can rely on
|
||||
// that check for memory safety because we have implemented Any for all types; no other
|
||||
// impls can exist as they would conflict with our impl.
|
||||
unsafe { Some(&mut *(self as *mut dyn Any as *mut T)) }
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl dyn Any + Send {
|
||||
/// Forwards to the method defined on the type `Any`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::any::Any;
|
||||
///
|
||||
/// fn is_string(s: &(dyn Any + Send)) {
|
||||
/// if s.is::<String>() {
|
||||
/// println!("It's a string!");
|
||||
/// } else {
|
||||
/// println!("Not a string...");
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// is_string(&0);
|
||||
/// is_string(&"cookie monster".to_string());
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[inline]
|
||||
pub fn is<T: Any>(&self) -> bool {
|
||||
Any::is::<T>(self)
|
||||
}
|
||||
|
||||
/// Forwards to the method defined on the type `Any`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::any::Any;
|
||||
///
|
||||
/// fn print_if_string(s: &(dyn Any + Send)) {
|
||||
/// if let Some(string) = s.downcast_ref::<String>() {
|
||||
/// println!("It's a string({}): '{}'", string.len(), string);
|
||||
/// } else {
|
||||
/// println!("Not a string...");
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// print_if_string(&0);
|
||||
/// print_if_string(&"cookie monster".to_string());
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[inline]
|
||||
pub fn downcast_ref<T: Any>(&self) -> Option<&T> {
|
||||
Any::downcast_ref::<T>(self)
|
||||
}
|
||||
|
||||
/// Forwards to the method defined on the type `Any`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::any::Any;
|
||||
///
|
||||
/// fn modify_if_u32(s: &mut (dyn Any + Send)) {
|
||||
/// if let Some(num) = s.downcast_mut::<u32>() {
|
||||
/// *num = 42;
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// let mut x = 10u32;
|
||||
/// let mut s = "starlord".to_string();
|
||||
///
|
||||
/// modify_if_u32(&mut x);
|
||||
/// modify_if_u32(&mut s);
|
||||
///
|
||||
/// assert_eq!(x, 42);
|
||||
/// assert_eq!(&s, "starlord");
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[inline]
|
||||
pub fn downcast_mut<T: Any>(&mut self) -> Option<&mut T> {
|
||||
Any::downcast_mut::<T>(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl dyn Any + Send + Sync {
|
||||
/// Forwards to the method defined on the type `Any`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::any::Any;
|
||||
///
|
||||
/// fn is_string(s: &(dyn Any + Send + Sync)) {
|
||||
/// if s.is::<String>() {
|
||||
/// println!("It's a string!");
|
||||
/// } else {
|
||||
/// println!("Not a string...");
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// is_string(&0);
|
||||
/// is_string(&"cookie monster".to_string());
|
||||
/// ```
|
||||
#[stable(feature = "any_send_sync_methods", since = "1.28.0")]
|
||||
#[inline]
|
||||
pub fn is<T: Any>(&self) -> bool {
|
||||
Any::is::<T>(self)
|
||||
}
|
||||
|
||||
/// Forwards to the method defined on the type `Any`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::any::Any;
|
||||
///
|
||||
/// fn print_if_string(s: &(dyn Any + Send + Sync)) {
|
||||
/// if let Some(string) = s.downcast_ref::<String>() {
|
||||
/// println!("It's a string({}): '{}'", string.len(), string);
|
||||
/// } else {
|
||||
/// println!("Not a string...");
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// print_if_string(&0);
|
||||
/// print_if_string(&"cookie monster".to_string());
|
||||
/// ```
|
||||
#[stable(feature = "any_send_sync_methods", since = "1.28.0")]
|
||||
#[inline]
|
||||
pub fn downcast_ref<T: Any>(&self) -> Option<&T> {
|
||||
Any::downcast_ref::<T>(self)
|
||||
}
|
||||
|
||||
/// Forwards to the method defined on the type `Any`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::any::Any;
|
||||
///
|
||||
/// fn modify_if_u32(s: &mut (dyn Any + Send + Sync)) {
|
||||
/// if let Some(num) = s.downcast_mut::<u32>() {
|
||||
/// *num = 42;
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// let mut x = 10u32;
|
||||
/// let mut s = "starlord".to_string();
|
||||
///
|
||||
/// modify_if_u32(&mut x);
|
||||
/// modify_if_u32(&mut s);
|
||||
///
|
||||
/// assert_eq!(x, 42);
|
||||
/// assert_eq!(&s, "starlord");
|
||||
/// ```
|
||||
#[stable(feature = "any_send_sync_methods", since = "1.28.0")]
|
||||
#[inline]
|
||||
pub fn downcast_mut<T: Any>(&mut self) -> Option<&mut T> {
|
||||
Any::downcast_mut::<T>(self)
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// TypeID and its methods
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// A `TypeId` represents a globally unique identifier for a type.
|
||||
///
|
||||
/// Each `TypeId` is an opaque object which does not allow inspection of what's
|
||||
/// inside but does allow basic operations such as cloning, comparison,
|
||||
/// printing, and showing.
|
||||
///
|
||||
/// A `TypeId` is currently only available for types which ascribe to `'static`,
|
||||
/// but this limitation may be removed in the future.
|
||||
///
|
||||
/// While `TypeId` implements `Hash`, `PartialOrd`, and `Ord`, it is worth
|
||||
/// noting that the hashes and ordering will vary between Rust releases. Beware
|
||||
/// of relying on them inside of your code!
|
||||
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub struct TypeId {
|
||||
t: u64,
|
||||
}
|
||||
|
||||
impl TypeId {
|
||||
/// Returns the `TypeId` of the type this generic function has been
|
||||
/// instantiated with.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::any::{Any, TypeId};
|
||||
///
|
||||
/// fn is_string<T: ?Sized + Any>(_s: &T) -> bool {
|
||||
/// TypeId::of::<String>() == TypeId::of::<T>()
|
||||
/// }
|
||||
///
|
||||
/// assert_eq!(is_string(&0), false);
|
||||
/// assert_eq!(is_string(&"cookie monster".to_string()), true);
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_const_unstable(feature = "const_type_id", issue = "77125")]
|
||||
pub const fn of<T: ?Sized + 'static>() -> TypeId {
|
||||
TypeId { t: intrinsics::type_id::<T>() }
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the name of a type as a string slice.
|
||||
///
|
||||
/// # Note
|
||||
///
|
||||
/// This is intended for diagnostic use. The exact contents and format of the
|
||||
/// string returned are not specified, other than being a best-effort
|
||||
/// description of the type. For example, amongst the strings
|
||||
/// that `type_name::<Option<String>>()` might return are `"Option<String>"` and
|
||||
/// `"std::option::Option<std::string::String>"`.
|
||||
///
|
||||
/// The returned string must not be considered to be a unique identifier of a
|
||||
/// type as multiple types may map to the same type name. Similarly, there is no
|
||||
/// guarantee that all parts of a type will appear in the returned string: for
|
||||
/// example, lifetime specifiers are currently not included. In addition, the
|
||||
/// output may change between versions of the compiler.
|
||||
///
|
||||
/// The current implementation uses the same infrastructure as compiler
|
||||
/// diagnostics and debuginfo, but this is not guaranteed.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// assert_eq!(
|
||||
/// std::any::type_name::<Option<String>>(),
|
||||
/// "core::option::Option<alloc::string::String>",
|
||||
/// );
|
||||
/// ```
|
||||
#[stable(feature = "type_name", since = "1.38.0")]
|
||||
#[rustc_const_unstable(feature = "const_type_name", issue = "63084")]
|
||||
pub const fn type_name<T: ?Sized>() -> &'static str {
|
||||
intrinsics::type_name::<T>()
|
||||
}
|
||||
|
||||
/// Returns the name of the type of the pointed-to value as a string slice.
|
||||
/// This is the same as `type_name::<T>()`, but can be used where the type of a
|
||||
/// variable is not easily available.
|
||||
///
|
||||
/// # Note
|
||||
///
|
||||
/// This is intended for diagnostic use. The exact contents and format of the
|
||||
/// string are not specified, other than being a best-effort description of the
|
||||
/// type. For example, `type_name_of_val::<Option<String>>(None)` could return
|
||||
/// `"Option<String>"` or `"std::option::Option<std::string::String>"`, but not
|
||||
/// `"foobar"`. In addition, the output may change between versions of the
|
||||
/// compiler.
|
||||
///
|
||||
/// This function does not resolve trait objects,
|
||||
/// meaning that `type_name_of_val(&7u32 as &dyn Debug)`
|
||||
/// may return `"dyn Debug"`, but not `"u32"`.
|
||||
///
|
||||
/// The type name should not be considered a unique identifier of a type;
|
||||
/// multiple types may share the same type name.
|
||||
///
|
||||
/// The current implementation uses the same infrastructure as compiler
|
||||
/// diagnostics and debuginfo, but this is not guaranteed.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Prints the default integer and float types.
|
||||
///
|
||||
/// ```rust
|
||||
/// #![feature(type_name_of_val)]
|
||||
/// use std::any::type_name_of_val;
|
||||
///
|
||||
/// let x = 1;
|
||||
/// println!("{}", type_name_of_val(&x));
|
||||
/// let y = 1.0;
|
||||
/// println!("{}", type_name_of_val(&y));
|
||||
/// ```
|
||||
#[unstable(feature = "type_name_of_val", issue = "66359")]
|
||||
#[rustc_const_unstable(feature = "const_type_name", issue = "63084")]
|
||||
pub const fn type_name_of_val<T: ?Sized>(_val: &T) -> &'static str {
|
||||
type_name::<T>()
|
||||
}
|
||||
202
libgrust/rustc-lib/core/src/array/iter.rs
Normal file
202
libgrust/rustc-lib/core/src/array/iter.rs
Normal file
@@ -0,0 +1,202 @@
|
||||
//! Defines the `IntoIter` owned iterator for arrays.
|
||||
|
||||
use crate::{
|
||||
fmt,
|
||||
iter::{ExactSizeIterator, FusedIterator, TrustedLen},
|
||||
mem::{self, MaybeUninit},
|
||||
ops::Range,
|
||||
ptr,
|
||||
};
|
||||
|
||||
/// A by-value [array] iterator.
|
||||
///
|
||||
/// [array]: ../../std/primitive.array.html
|
||||
#[unstable(feature = "array_value_iter", issue = "65798")]
|
||||
pub struct IntoIter<T, const N: usize> {
|
||||
/// This is the array we are iterating over.
|
||||
///
|
||||
/// Elements with index `i` where `alive.start <= i < alive.end` have not
|
||||
/// been yielded yet and are valid array entries. Elements with indices `i
|
||||
/// < alive.start` or `i >= alive.end` have been yielded already and must
|
||||
/// not be accessed anymore! Those dead elements might even be in a
|
||||
/// completely uninitialized state!
|
||||
///
|
||||
/// So the invariants are:
|
||||
/// - `data[alive]` is alive (i.e. contains valid elements)
|
||||
/// - `data[..alive.start]` and `data[alive.end..]` are dead (i.e. the
|
||||
/// elements were already read and must not be touched anymore!)
|
||||
data: [MaybeUninit<T>; N],
|
||||
|
||||
/// The elements in `data` that have not been yielded yet.
|
||||
///
|
||||
/// Invariants:
|
||||
/// - `alive.start <= alive.end`
|
||||
/// - `alive.end <= N`
|
||||
alive: Range<usize>,
|
||||
}
|
||||
|
||||
impl<T, const N: usize> IntoIter<T, N> {
|
||||
/// Creates a new iterator over the given `array`.
|
||||
///
|
||||
/// *Note*: this method might never get stabilized and/or removed in the
|
||||
/// future as there will likely be another, preferred way of obtaining this
|
||||
/// iterator (either via `IntoIterator` for arrays or via another way).
|
||||
#[unstable(feature = "array_value_iter", issue = "65798")]
|
||||
pub fn new(array: [T; N]) -> Self {
|
||||
// SAFETY: The transmute here is actually safe. The docs of `MaybeUninit`
|
||||
// promise:
|
||||
//
|
||||
// > `MaybeUninit<T>` is guaranteed to have the same size and alignment
|
||||
// > as `T`.
|
||||
//
|
||||
// The docs even show a transmute from an array of `MaybeUninit<T>` to
|
||||
// an array of `T`.
|
||||
//
|
||||
// With that, this initialization satisfies the invariants.
|
||||
|
||||
// FIXME(LukasKalbertodt): actually use `mem::transmute` here, once it
|
||||
// works with const generics:
|
||||
// `mem::transmute::<[T; N], [MaybeUninit<T>; N]>(array)`
|
||||
//
|
||||
// Until then, we can use `mem::transmute_copy` to create a bitwise copy
|
||||
// as a different type, then forget `array` so that it is not dropped.
|
||||
unsafe {
|
||||
let iter = Self { data: mem::transmute_copy(&array), alive: 0..N };
|
||||
mem::forget(array);
|
||||
iter
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns an immutable slice of all elements that have not been yielded
|
||||
/// yet.
|
||||
fn as_slice(&self) -> &[T] {
|
||||
// SAFETY: We know that all elements within `alive` are properly initialized.
|
||||
unsafe {
|
||||
let slice = self.data.get_unchecked(self.alive.clone());
|
||||
MaybeUninit::slice_assume_init_ref(slice)
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a mutable slice of all elements that have not been yielded yet.
|
||||
fn as_mut_slice(&mut self) -> &mut [T] {
|
||||
// SAFETY: We know that all elements within `alive` are properly initialized.
|
||||
unsafe {
|
||||
let slice = self.data.get_unchecked_mut(self.alive.clone());
|
||||
MaybeUninit::slice_assume_init_mut(slice)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "array_value_iter_impls", since = "1.40.0")]
|
||||
impl<T, const N: usize> Iterator for IntoIter<T, N> {
|
||||
type Item = T;
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
// Get the next index from the front.
|
||||
//
|
||||
// Increasing `alive.start` by 1 maintains the invariant regarding
|
||||
// `alive`. However, due to this change, for a short time, the alive
|
||||
// zone is not `data[alive]` anymore, but `data[idx..alive.end]`.
|
||||
self.alive.next().map(|idx| {
|
||||
// Read the element from the array.
|
||||
// SAFETY: `idx` is an index into the former "alive" region of the
|
||||
// array. Reading this element means that `data[idx]` is regarded as
|
||||
// dead now (i.e. do not touch). As `idx` was the start of the
|
||||
// alive-zone, the alive zone is now `data[alive]` again, restoring
|
||||
// all invariants.
|
||||
unsafe { self.data.get_unchecked(idx).assume_init_read() }
|
||||
})
|
||||
}
|
||||
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
let len = self.len();
|
||||
(len, Some(len))
|
||||
}
|
||||
|
||||
fn count(self) -> usize {
|
||||
self.len()
|
||||
}
|
||||
|
||||
fn last(mut self) -> Option<Self::Item> {
|
||||
self.next_back()
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "array_value_iter_impls", since = "1.40.0")]
|
||||
impl<T, const N: usize> DoubleEndedIterator for IntoIter<T, N> {
|
||||
fn next_back(&mut self) -> Option<Self::Item> {
|
||||
// Get the next index from the back.
|
||||
//
|
||||
// Decreasing `alive.end` by 1 maintains the invariant regarding
|
||||
// `alive`. However, due to this change, for a short time, the alive
|
||||
// zone is not `data[alive]` anymore, but `data[alive.start..=idx]`.
|
||||
self.alive.next_back().map(|idx| {
|
||||
// Read the element from the array.
|
||||
// SAFETY: `idx` is an index into the former "alive" region of the
|
||||
// array. Reading this element means that `data[idx]` is regarded as
|
||||
// dead now (i.e. do not touch). As `idx` was the end of the
|
||||
// alive-zone, the alive zone is now `data[alive]` again, restoring
|
||||
// all invariants.
|
||||
unsafe { self.data.get_unchecked(idx).assume_init_read() }
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "array_value_iter_impls", since = "1.40.0")]
|
||||
impl<T, const N: usize> Drop for IntoIter<T, N> {
|
||||
fn drop(&mut self) {
|
||||
// SAFETY: This is safe: `as_mut_slice` returns exactly the sub-slice
|
||||
// of elements that have not been moved out yet and that remain
|
||||
// to be dropped.
|
||||
unsafe { ptr::drop_in_place(self.as_mut_slice()) }
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "array_value_iter_impls", since = "1.40.0")]
|
||||
impl<T, const N: usize> ExactSizeIterator for IntoIter<T, N> {
|
||||
fn len(&self) -> usize {
|
||||
// Will never underflow due to the invariant `alive.start <=
|
||||
// alive.end`.
|
||||
self.alive.end - self.alive.start
|
||||
}
|
||||
fn is_empty(&self) -> bool {
|
||||
self.alive.is_empty()
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "array_value_iter_impls", since = "1.40.0")]
|
||||
impl<T, const N: usize> FusedIterator for IntoIter<T, N> {}
|
||||
|
||||
// The iterator indeed reports the correct length. The number of "alive"
|
||||
// elements (that will still be yielded) is the length of the range `alive`.
|
||||
// This range is decremented in length in either `next` or `next_back`. It is
|
||||
// always decremented by 1 in those methods, but only if `Some(_)` is returned.
|
||||
#[stable(feature = "array_value_iter_impls", since = "1.40.0")]
|
||||
unsafe impl<T, const N: usize> TrustedLen for IntoIter<T, N> {}
|
||||
|
||||
#[stable(feature = "array_value_iter_impls", since = "1.40.0")]
|
||||
impl<T: Clone, const N: usize> Clone for IntoIter<T, N> {
|
||||
fn clone(&self) -> Self {
|
||||
// Note, we don't really need to match the exact same alive range, so
|
||||
// we can just clone into offset 0 regardless of where `self` is.
|
||||
let mut new = Self { data: MaybeUninit::uninit_array(), alive: 0..0 };
|
||||
|
||||
// Clone all alive elements.
|
||||
for (src, dst) in self.as_slice().iter().zip(&mut new.data) {
|
||||
// Write a clone into the new array, then update its alive range.
|
||||
// If cloning panics, we'll correctly drop the previous items.
|
||||
dst.write(src.clone());
|
||||
new.alive.end += 1;
|
||||
}
|
||||
|
||||
new
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "array_value_iter_impls", since = "1.40.0")]
|
||||
impl<T: fmt::Debug, const N: usize> fmt::Debug for IntoIter<T, N> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
// Only print the elements that were not yielded yet: we cannot
|
||||
// access the yielded elements anymore.
|
||||
f.debug_tuple("IntoIter").field(&self.as_slice()).finish()
|
||||
}
|
||||
}
|
||||
453
libgrust/rustc-lib/core/src/array/mod.rs
Normal file
453
libgrust/rustc-lib/core/src/array/mod.rs
Normal file
@@ -0,0 +1,453 @@
|
||||
//! Implementations of things like `Eq` for fixed-length arrays
|
||||
//! up to a certain length. Eventually, we should be able to generalize
|
||||
//! to all lengths.
|
||||
//!
|
||||
//! *[See also the array primitive type](../../std/primitive.array.html).*
|
||||
|
||||
#![stable(feature = "core_array", since = "1.36.0")]
|
||||
|
||||
use crate::borrow::{Borrow, BorrowMut};
|
||||
use crate::cmp::Ordering;
|
||||
use crate::convert::{Infallible, TryFrom};
|
||||
use crate::fmt;
|
||||
use crate::hash::{self, Hash};
|
||||
use crate::marker::Unsize;
|
||||
use crate::slice::{Iter, IterMut};
|
||||
|
||||
mod iter;
|
||||
|
||||
#[unstable(feature = "array_value_iter", issue = "65798")]
|
||||
pub use iter::IntoIter;
|
||||
|
||||
/// Converts a reference to `T` into a reference to an array of length 1 (without copying).
|
||||
#[unstable(feature = "array_from_ref", issue = "77101")]
|
||||
pub fn from_ref<T>(s: &T) -> &[T; 1] {
|
||||
// SAFETY: Converting `&T` to `&[T; 1]` is sound.
|
||||
unsafe { &*(s as *const T).cast::<[T; 1]>() }
|
||||
}
|
||||
|
||||
/// Converts a mutable reference to `T` into a mutable reference to an array of length 1 (without copying).
|
||||
#[unstable(feature = "array_from_ref", issue = "77101")]
|
||||
pub fn from_mut<T>(s: &mut T) -> &mut [T; 1] {
|
||||
// SAFETY: Converting `&mut T` to `&mut [T; 1]` is sound.
|
||||
unsafe { &mut *(s as *mut T).cast::<[T; 1]>() }
|
||||
}
|
||||
|
||||
/// Utility trait implemented only on arrays of fixed size
|
||||
///
|
||||
/// This trait can be used to implement other traits on fixed-size arrays
|
||||
/// without causing much metadata bloat.
|
||||
///
|
||||
/// The trait is marked unsafe in order to restrict implementors to fixed-size
|
||||
/// arrays. User of this trait can assume that implementors have the exact
|
||||
/// layout in memory of a fixed size array (for example, for unsafe
|
||||
/// initialization).
|
||||
///
|
||||
/// Note that the traits [`AsRef`] and [`AsMut`] provide similar methods for types that
|
||||
/// may not be fixed-size arrays. Implementors should prefer those traits
|
||||
/// instead.
|
||||
#[unstable(feature = "fixed_size_array", issue = "27778")]
|
||||
pub unsafe trait FixedSizeArray<T> {
|
||||
/// Converts the array to immutable slice
|
||||
#[unstable(feature = "fixed_size_array", issue = "27778")]
|
||||
fn as_slice(&self) -> &[T];
|
||||
/// Converts the array to mutable slice
|
||||
#[unstable(feature = "fixed_size_array", issue = "27778")]
|
||||
fn as_mut_slice(&mut self) -> &mut [T];
|
||||
}
|
||||
|
||||
#[unstable(feature = "fixed_size_array", issue = "27778")]
|
||||
unsafe impl<T, A: Unsize<[T]>> FixedSizeArray<T> for A {
|
||||
#[inline]
|
||||
fn as_slice(&self) -> &[T] {
|
||||
self
|
||||
}
|
||||
#[inline]
|
||||
fn as_mut_slice(&mut self) -> &mut [T] {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
/// The error type returned when a conversion from a slice to an array fails.
|
||||
#[stable(feature = "try_from", since = "1.34.0")]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct TryFromSliceError(());
|
||||
|
||||
#[stable(feature = "core_array", since = "1.36.0")]
|
||||
impl fmt::Display for TryFromSliceError {
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt::Display::fmt(self.__description(), f)
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFromSliceError {
|
||||
#[unstable(
|
||||
feature = "array_error_internals",
|
||||
reason = "available through Error trait and this method should not \
|
||||
be exposed publicly",
|
||||
issue = "none"
|
||||
)]
|
||||
#[inline]
|
||||
#[doc(hidden)]
|
||||
pub fn __description(&self) -> &str {
|
||||
"could not convert slice to array"
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "try_from_slice_error", since = "1.36.0")]
|
||||
impl From<Infallible> for TryFromSliceError {
|
||||
fn from(x: Infallible) -> TryFromSliceError {
|
||||
match x {}
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T, const N: usize> AsRef<[T]> for [T; N] {
|
||||
#[inline]
|
||||
fn as_ref(&self) -> &[T] {
|
||||
&self[..]
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T, const N: usize> AsMut<[T]> for [T; N] {
|
||||
#[inline]
|
||||
fn as_mut(&mut self) -> &mut [T] {
|
||||
&mut self[..]
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "array_borrow", since = "1.4.0")]
|
||||
impl<T, const N: usize> Borrow<[T]> for [T; N] {
|
||||
fn borrow(&self) -> &[T] {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "array_borrow", since = "1.4.0")]
|
||||
impl<T, const N: usize> BorrowMut<[T]> for [T; N] {
|
||||
fn borrow_mut(&mut self) -> &mut [T] {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "try_from", since = "1.34.0")]
|
||||
impl<T, const N: usize> TryFrom<&[T]> for [T; N]
|
||||
where
|
||||
T: Copy,
|
||||
{
|
||||
type Error = TryFromSliceError;
|
||||
|
||||
fn try_from(slice: &[T]) -> Result<[T; N], TryFromSliceError> {
|
||||
<&Self>::try_from(slice).map(|r| *r)
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "try_from", since = "1.34.0")]
|
||||
impl<'a, T, const N: usize> TryFrom<&'a [T]> for &'a [T; N] {
|
||||
type Error = TryFromSliceError;
|
||||
|
||||
fn try_from(slice: &[T]) -> Result<&[T; N], TryFromSliceError> {
|
||||
if slice.len() == N {
|
||||
let ptr = slice.as_ptr() as *const [T; N];
|
||||
// SAFETY: ok because we just checked that the length fits
|
||||
unsafe { Ok(&*ptr) }
|
||||
} else {
|
||||
Err(TryFromSliceError(()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "try_from", since = "1.34.0")]
|
||||
impl<'a, T, const N: usize> TryFrom<&'a mut [T]> for &'a mut [T; N] {
|
||||
type Error = TryFromSliceError;
|
||||
|
||||
fn try_from(slice: &mut [T]) -> Result<&mut [T; N], TryFromSliceError> {
|
||||
if slice.len() == N {
|
||||
let ptr = slice.as_mut_ptr() as *mut [T; N];
|
||||
// SAFETY: ok because we just checked that the length fits
|
||||
unsafe { Ok(&mut *ptr) }
|
||||
} else {
|
||||
Err(TryFromSliceError(()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: Hash, const N: usize> Hash for [T; N] {
|
||||
fn hash<H: hash::Hasher>(&self, state: &mut H) {
|
||||
Hash::hash(&self[..], state)
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: fmt::Debug, const N: usize> fmt::Debug for [T; N] {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt::Debug::fmt(&&self[..], f)
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<'a, T, const N: usize> IntoIterator for &'a [T; N] {
|
||||
type Item = &'a T;
|
||||
type IntoIter = Iter<'a, T>;
|
||||
|
||||
fn into_iter(self) -> Iter<'a, T> {
|
||||
self.iter()
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<'a, T, const N: usize> IntoIterator for &'a mut [T; N] {
|
||||
type Item = &'a mut T;
|
||||
type IntoIter = IterMut<'a, T>;
|
||||
|
||||
fn into_iter(self) -> IterMut<'a, T> {
|
||||
self.iter_mut()
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<A, B, const N: usize> PartialEq<[B; N]> for [A; N]
|
||||
where
|
||||
A: PartialEq<B>,
|
||||
{
|
||||
#[inline]
|
||||
fn eq(&self, other: &[B; N]) -> bool {
|
||||
self[..] == other[..]
|
||||
}
|
||||
#[inline]
|
||||
fn ne(&self, other: &[B; N]) -> bool {
|
||||
self[..] != other[..]
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<A, B, const N: usize> PartialEq<[B]> for [A; N]
|
||||
where
|
||||
A: PartialEq<B>,
|
||||
{
|
||||
#[inline]
|
||||
fn eq(&self, other: &[B]) -> bool {
|
||||
self[..] == other[..]
|
||||
}
|
||||
#[inline]
|
||||
fn ne(&self, other: &[B]) -> bool {
|
||||
self[..] != other[..]
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<A, B, const N: usize> PartialEq<[A; N]> for [B]
|
||||
where
|
||||
B: PartialEq<A>,
|
||||
{
|
||||
#[inline]
|
||||
fn eq(&self, other: &[A; N]) -> bool {
|
||||
self[..] == other[..]
|
||||
}
|
||||
#[inline]
|
||||
fn ne(&self, other: &[A; N]) -> bool {
|
||||
self[..] != other[..]
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<'b, A, B, const N: usize> PartialEq<&'b [B]> for [A; N]
|
||||
where
|
||||
A: PartialEq<B>,
|
||||
{
|
||||
#[inline]
|
||||
fn eq(&self, other: &&'b [B]) -> bool {
|
||||
self[..] == other[..]
|
||||
}
|
||||
#[inline]
|
||||
fn ne(&self, other: &&'b [B]) -> bool {
|
||||
self[..] != other[..]
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<'b, A, B, const N: usize> PartialEq<[A; N]> for &'b [B]
|
||||
where
|
||||
B: PartialEq<A>,
|
||||
{
|
||||
#[inline]
|
||||
fn eq(&self, other: &[A; N]) -> bool {
|
||||
self[..] == other[..]
|
||||
}
|
||||
#[inline]
|
||||
fn ne(&self, other: &[A; N]) -> bool {
|
||||
self[..] != other[..]
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<'b, A, B, const N: usize> PartialEq<&'b mut [B]> for [A; N]
|
||||
where
|
||||
A: PartialEq<B>,
|
||||
{
|
||||
#[inline]
|
||||
fn eq(&self, other: &&'b mut [B]) -> bool {
|
||||
self[..] == other[..]
|
||||
}
|
||||
#[inline]
|
||||
fn ne(&self, other: &&'b mut [B]) -> bool {
|
||||
self[..] != other[..]
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<'b, A, B, const N: usize> PartialEq<[A; N]> for &'b mut [B]
|
||||
where
|
||||
B: PartialEq<A>,
|
||||
{
|
||||
#[inline]
|
||||
fn eq(&self, other: &[A; N]) -> bool {
|
||||
self[..] == other[..]
|
||||
}
|
||||
#[inline]
|
||||
fn ne(&self, other: &[A; N]) -> bool {
|
||||
self[..] != other[..]
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE: some less important impls are omitted to reduce code bloat
|
||||
// __impl_slice_eq2! { [A; $N], &'b [B; $N] }
|
||||
// __impl_slice_eq2! { [A; $N], &'b mut [B; $N] }
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: Eq, const N: usize> Eq for [T; N] {}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: PartialOrd, const N: usize> PartialOrd for [T; N] {
|
||||
#[inline]
|
||||
fn partial_cmp(&self, other: &[T; N]) -> Option<Ordering> {
|
||||
PartialOrd::partial_cmp(&&self[..], &&other[..])
|
||||
}
|
||||
#[inline]
|
||||
fn lt(&self, other: &[T; N]) -> bool {
|
||||
PartialOrd::lt(&&self[..], &&other[..])
|
||||
}
|
||||
#[inline]
|
||||
fn le(&self, other: &[T; N]) -> bool {
|
||||
PartialOrd::le(&&self[..], &&other[..])
|
||||
}
|
||||
#[inline]
|
||||
fn ge(&self, other: &[T; N]) -> bool {
|
||||
PartialOrd::ge(&&self[..], &&other[..])
|
||||
}
|
||||
#[inline]
|
||||
fn gt(&self, other: &[T; N]) -> bool {
|
||||
PartialOrd::gt(&&self[..], &&other[..])
|
||||
}
|
||||
}
|
||||
|
||||
/// Implements comparison of arrays [lexicographically](Ord#lexicographical-comparison).
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: Ord, const N: usize> Ord for [T; N] {
|
||||
#[inline]
|
||||
fn cmp(&self, other: &[T; N]) -> Ordering {
|
||||
Ord::cmp(&&self[..], &&other[..])
|
||||
}
|
||||
}
|
||||
|
||||
// The Default impls cannot be done with const generics because `[T; 0]` doesn't
|
||||
// require Default to be implemented, and having different impl blocks for
|
||||
// different numbers isn't supported yet.
|
||||
|
||||
macro_rules! array_impl_default {
|
||||
{$n:expr, $t:ident $($ts:ident)*} => {
|
||||
#[stable(since = "1.4.0", feature = "array_default")]
|
||||
impl<T> Default for [T; $n] where T: Default {
|
||||
fn default() -> [T; $n] {
|
||||
[$t::default(), $($ts::default()),*]
|
||||
}
|
||||
}
|
||||
array_impl_default!{($n - 1), $($ts)*}
|
||||
};
|
||||
{$n:expr,} => {
|
||||
#[stable(since = "1.4.0", feature = "array_default")]
|
||||
impl<T> Default for [T; $n] {
|
||||
fn default() -> [T; $n] { [] }
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
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}
|
||||
|
||||
#[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::slice_as_mut_ptr(&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) }
|
||||
}
|
||||
|
||||
/// Returns a slice containing the entire array. Equivalent to `&s[..]`.
|
||||
#[unstable(feature = "array_methods", issue = "76118")]
|
||||
pub fn as_slice(&self) -> &[T] {
|
||||
self
|
||||
}
|
||||
|
||||
/// Returns a mutable slice containing the entire array. Equivalent to
|
||||
/// `&mut s[..]`.
|
||||
#[unstable(feature = "array_methods", issue = "76118")]
|
||||
pub fn as_mut_slice(&mut self) -> &mut [T] {
|
||||
self
|
||||
}
|
||||
}
|
||||
150
libgrust/rustc-lib/core/src/ascii.rs
Normal file
150
libgrust/rustc-lib/core/src/ascii.rs
Normal file
@@ -0,0 +1,150 @@
|
||||
//! Operations on ASCII strings and characters.
|
||||
//!
|
||||
//! Most string operations in Rust act on UTF-8 strings. However, at times it
|
||||
//! makes more sense to only consider the ASCII character set for a specific
|
||||
//! operation.
|
||||
//!
|
||||
//! The [`escape_default`] function provides an iterator over the bytes of an
|
||||
//! escaped version of the character given.
|
||||
|
||||
#![stable(feature = "core_ascii", since = "1.26.0")]
|
||||
|
||||
use crate::fmt;
|
||||
use crate::iter::FusedIterator;
|
||||
use crate::ops::Range;
|
||||
use crate::str::from_utf8_unchecked;
|
||||
|
||||
/// An iterator over the escaped version of a byte.
|
||||
///
|
||||
/// This `struct` is created by the [`escape_default`] function. See its
|
||||
/// documentation for more.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[derive(Clone)]
|
||||
pub struct EscapeDefault {
|
||||
range: Range<usize>,
|
||||
data: [u8; 4],
|
||||
}
|
||||
|
||||
/// Returns an iterator that produces an escaped version of a `u8`.
|
||||
///
|
||||
/// The default is chosen with a bias toward producing literals that are
|
||||
/// legal in a variety of languages, including C++11 and similar C-family
|
||||
/// languages. The exact rules are:
|
||||
///
|
||||
/// * Tab is escaped as `\t`.
|
||||
/// * Carriage return is escaped as `\r`.
|
||||
/// * Line feed is escaped as `\n`.
|
||||
/// * Single quote is escaped as `\'`.
|
||||
/// * Double quote is escaped as `\"`.
|
||||
/// * Backslash is escaped as `\\`.
|
||||
/// * Any character in the 'printable ASCII' range `0x20` .. `0x7e`
|
||||
/// inclusive is not escaped.
|
||||
/// * Any other chars are given hex escapes of the form '\xNN'.
|
||||
/// * Unicode escapes are never generated by this function.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::ascii;
|
||||
///
|
||||
/// let escaped = ascii::escape_default(b'0').next().unwrap();
|
||||
/// assert_eq!(b'0', escaped);
|
||||
///
|
||||
/// let mut escaped = ascii::escape_default(b'\t');
|
||||
///
|
||||
/// assert_eq!(b'\\', escaped.next().unwrap());
|
||||
/// assert_eq!(b't', escaped.next().unwrap());
|
||||
///
|
||||
/// let mut escaped = ascii::escape_default(b'\r');
|
||||
///
|
||||
/// assert_eq!(b'\\', escaped.next().unwrap());
|
||||
/// assert_eq!(b'r', escaped.next().unwrap());
|
||||
///
|
||||
/// let mut escaped = ascii::escape_default(b'\n');
|
||||
///
|
||||
/// assert_eq!(b'\\', escaped.next().unwrap());
|
||||
/// assert_eq!(b'n', escaped.next().unwrap());
|
||||
///
|
||||
/// let mut escaped = ascii::escape_default(b'\'');
|
||||
///
|
||||
/// assert_eq!(b'\\', escaped.next().unwrap());
|
||||
/// assert_eq!(b'\'', escaped.next().unwrap());
|
||||
///
|
||||
/// let mut escaped = ascii::escape_default(b'"');
|
||||
///
|
||||
/// assert_eq!(b'\\', escaped.next().unwrap());
|
||||
/// assert_eq!(b'"', escaped.next().unwrap());
|
||||
///
|
||||
/// let mut escaped = ascii::escape_default(b'\\');
|
||||
///
|
||||
/// assert_eq!(b'\\', escaped.next().unwrap());
|
||||
/// assert_eq!(b'\\', escaped.next().unwrap());
|
||||
///
|
||||
/// let mut escaped = ascii::escape_default(b'\x9d');
|
||||
///
|
||||
/// assert_eq!(b'\\', escaped.next().unwrap());
|
||||
/// assert_eq!(b'x', escaped.next().unwrap());
|
||||
/// assert_eq!(b'9', escaped.next().unwrap());
|
||||
/// assert_eq!(b'd', escaped.next().unwrap());
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn escape_default(c: u8) -> EscapeDefault {
|
||||
let (data, len) = match c {
|
||||
b'\t' => ([b'\\', b't', 0, 0], 2),
|
||||
b'\r' => ([b'\\', b'r', 0, 0], 2),
|
||||
b'\n' => ([b'\\', b'n', 0, 0], 2),
|
||||
b'\\' => ([b'\\', b'\\', 0, 0], 2),
|
||||
b'\'' => ([b'\\', b'\'', 0, 0], 2),
|
||||
b'"' => ([b'\\', b'"', 0, 0], 2),
|
||||
b'\x20'..=b'\x7e' => ([c, 0, 0, 0], 1),
|
||||
_ => ([b'\\', b'x', hexify(c >> 4), hexify(c & 0xf)], 4),
|
||||
};
|
||||
|
||||
return EscapeDefault { range: 0..len, data };
|
||||
|
||||
fn hexify(b: u8) -> u8 {
|
||||
match b {
|
||||
0..=9 => b'0' + b,
|
||||
_ => b'a' + b - 10,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl Iterator for EscapeDefault {
|
||||
type Item = u8;
|
||||
fn next(&mut self) -> Option<u8> {
|
||||
self.range.next().map(|i| self.data[i])
|
||||
}
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
self.range.size_hint()
|
||||
}
|
||||
fn last(mut self) -> Option<u8> {
|
||||
self.next_back()
|
||||
}
|
||||
}
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl DoubleEndedIterator for EscapeDefault {
|
||||
fn next_back(&mut self) -> Option<u8> {
|
||||
self.range.next_back().map(|i| self.data[i])
|
||||
}
|
||||
}
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl ExactSizeIterator for EscapeDefault {}
|
||||
#[stable(feature = "fused", since = "1.26.0")]
|
||||
impl FusedIterator for EscapeDefault {}
|
||||
|
||||
#[stable(feature = "ascii_escape_display", since = "1.39.0")]
|
||||
impl fmt::Display for EscapeDefault {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
// SAFETY: ok because `escape_default` created only valid utf-8 data
|
||||
f.write_str(unsafe { from_utf8_unchecked(&self.data[self.range.clone()]) })
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "std_debug", since = "1.16.0")]
|
||||
impl fmt::Debug for EscapeDefault {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.pad("EscapeDefault { .. }")
|
||||
}
|
||||
}
|
||||
36
libgrust/rustc-lib/core/src/bool.rs
Normal file
36
libgrust/rustc-lib/core/src/bool.rs
Normal file
@@ -0,0 +1,36 @@
|
||||
//! impl bool {}
|
||||
|
||||
#[lang = "bool"]
|
||||
impl bool {
|
||||
/// Returns `Some(t)` if the `bool` is `true`, or `None` otherwise.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(bool_to_option)]
|
||||
///
|
||||
/// assert_eq!(false.then_some(0), None);
|
||||
/// assert_eq!(true.then_some(0), Some(0));
|
||||
/// ```
|
||||
#[unstable(feature = "bool_to_option", issue = "64260")]
|
||||
#[inline]
|
||||
pub fn then_some<T>(self, t: T) -> Option<T> {
|
||||
if self { Some(t) } else { None }
|
||||
}
|
||||
|
||||
/// Returns `Some(f())` if the `bool` is `true`, or `None` otherwise.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(bool_to_option)]
|
||||
///
|
||||
/// assert_eq!(false.then(|| 0), None);
|
||||
/// assert_eq!(true.then(|| 0), Some(0));
|
||||
/// ```
|
||||
#[unstable(feature = "bool_to_option", issue = "64260")]
|
||||
#[inline]
|
||||
pub fn then<T, F: FnOnce() -> T>(self, f: F) -> Option<T> {
|
||||
if self { Some(f()) } else { None }
|
||||
}
|
||||
}
|
||||
242
libgrust/rustc-lib/core/src/borrow.rs
Normal file
242
libgrust/rustc-lib/core/src/borrow.rs
Normal file
@@ -0,0 +1,242 @@
|
||||
//! A module for working with borrowed data.
|
||||
|
||||
#![stable(feature = "rust1", since = "1.0.0")]
|
||||
|
||||
/// A trait for borrowing data.
|
||||
///
|
||||
/// In Rust, it is common to provide different representations of a type for
|
||||
/// different use cases. For instance, storage location and management for a
|
||||
/// value can be specifically chosen as appropriate for a particular use via
|
||||
/// pointer types such as [`Box<T>`] or [`Rc<T>`]. Beyond these generic
|
||||
/// wrappers that can be used with any type, some types provide optional
|
||||
/// facets providing potentially costly functionality. An example for such a
|
||||
/// type is [`String`] which adds the ability to extend a string to the basic
|
||||
/// [`str`]. This requires keeping additional information unnecessary for a
|
||||
/// simple, immutable string.
|
||||
///
|
||||
/// These types provide access to the underlying data through references
|
||||
/// to the type of that data. They are said to be ‘borrowed as’ that type.
|
||||
/// For instance, a [`Box<T>`] can be borrowed as `T` while a [`String`]
|
||||
/// can be borrowed as `str`.
|
||||
///
|
||||
/// Types express that they can be borrowed as some type `T` by implementing
|
||||
/// `Borrow<T>`, providing a reference to a `T` in the trait’s
|
||||
/// [`borrow`] method. A type is free to borrow as several different types.
|
||||
/// If it wishes to mutably borrow as the type – allowing the underlying data
|
||||
/// to be modified, it can additionally implement [`BorrowMut<T>`].
|
||||
///
|
||||
/// Further, when providing implementations for additional traits, it needs
|
||||
/// to be considered whether they should behave identical to those of the
|
||||
/// underlying type as a consequence of acting as a representation of that
|
||||
/// underlying type. Generic code typically uses `Borrow<T>` when it relies
|
||||
/// on the identical behavior of these additional trait implementations.
|
||||
/// These traits will likely appear as additional trait bounds.
|
||||
///
|
||||
/// In particular `Eq`, `Ord` and `Hash` must be equivalent for
|
||||
/// borrowed and owned values: `x.borrow() == y.borrow()` should give the
|
||||
/// same result as `x == y`.
|
||||
///
|
||||
/// If generic code merely needs to work for all types that can
|
||||
/// provide a reference to related type `T`, it is often better to use
|
||||
/// [`AsRef<T>`] as more types can safely implement it.
|
||||
///
|
||||
/// [`BorrowMut<T>`]: BorrowMut
|
||||
/// [`Box<T>`]: ../../std/boxed/struct.Box.html
|
||||
/// [`Mutex<T>`]: ../../std/sync/struct.Mutex.html
|
||||
/// [`Rc<T>`]: ../../std/rc/struct.Rc.html
|
||||
/// [`String`]: ../../std/string/struct.String.html
|
||||
/// [`borrow`]: Borrow::borrow
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// As a data collection, [`HashMap<K, V>`] owns both keys and values. If
|
||||
/// the key’s actual data is wrapped in a managing type of some kind, it
|
||||
/// should, however, still be possible to search for a value using a
|
||||
/// reference to the key’s data. For instance, if the key is a string, then
|
||||
/// it is likely stored with the hash map as a [`String`], while it should
|
||||
/// be possible to search using a [`&str`][`str`]. Thus, `insert` needs to
|
||||
/// operate on a `String` while `get` needs to be able to use a `&str`.
|
||||
///
|
||||
/// Slightly simplified, the relevant parts of `HashMap<K, V>` look like
|
||||
/// this:
|
||||
///
|
||||
/// ```
|
||||
/// use std::borrow::Borrow;
|
||||
/// use std::hash::Hash;
|
||||
///
|
||||
/// pub struct HashMap<K, V> {
|
||||
/// # marker: ::std::marker::PhantomData<(K, V)>,
|
||||
/// // fields omitted
|
||||
/// }
|
||||
///
|
||||
/// impl<K, V> HashMap<K, V> {
|
||||
/// pub fn insert(&self, key: K, value: V) -> Option<V>
|
||||
/// where K: Hash + Eq
|
||||
/// {
|
||||
/// # unimplemented!()
|
||||
/// // ...
|
||||
/// }
|
||||
///
|
||||
/// pub fn get<Q>(&self, k: &Q) -> Option<&V>
|
||||
/// where
|
||||
/// K: Borrow<Q>,
|
||||
/// Q: Hash + Eq + ?Sized
|
||||
/// {
|
||||
/// # unimplemented!()
|
||||
/// // ...
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// The entire hash map is generic over a key type `K`. Because these keys
|
||||
/// are stored with the hash map, this type has to own the key’s data.
|
||||
/// When inserting a key-value pair, the map is given such a `K` and needs
|
||||
/// to find the correct hash bucket and check if the key is already present
|
||||
/// based on that `K`. It therefore requires `K: Hash + Eq`.
|
||||
///
|
||||
/// When searching for a value in the map, however, having to provide a
|
||||
/// reference to a `K` as the key to search for would require to always
|
||||
/// create such an owned value. For string keys, this would mean a `String`
|
||||
/// value needs to be created just for the search for cases where only a
|
||||
/// `str` is available.
|
||||
///
|
||||
/// Instead, the `get` method is generic over the type of the underlying key
|
||||
/// data, called `Q` in the method signature above. It states that `K`
|
||||
/// borrows as a `Q` by requiring that `K: Borrow<Q>`. By additionally
|
||||
/// requiring `Q: Hash + Eq`, it signals the requirement that `K` and `Q`
|
||||
/// have implementations of the `Hash` and `Eq` traits that produce identical
|
||||
/// results.
|
||||
///
|
||||
/// The implementation of `get` relies in particular on identical
|
||||
/// implementations of `Hash` by determining the key’s hash bucket by calling
|
||||
/// `Hash::hash` on the `Q` value even though it inserted the key based on
|
||||
/// the hash value calculated from the `K` value.
|
||||
///
|
||||
/// As a consequence, the hash map breaks if a `K` wrapping a `Q` value
|
||||
/// produces a different hash than `Q`. For instance, imagine you have a
|
||||
/// type that wraps a string but compares ASCII letters ignoring their case:
|
||||
///
|
||||
/// ```
|
||||
/// pub struct CaseInsensitiveString(String);
|
||||
///
|
||||
/// impl PartialEq for CaseInsensitiveString {
|
||||
/// fn eq(&self, other: &Self) -> bool {
|
||||
/// self.0.eq_ignore_ascii_case(&other.0)
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// impl Eq for CaseInsensitiveString { }
|
||||
/// ```
|
||||
///
|
||||
/// Because two equal values need to produce the same hash value, the
|
||||
/// implementation of `Hash` needs to ignore ASCII case, too:
|
||||
///
|
||||
/// ```
|
||||
/// # use std::hash::{Hash, Hasher};
|
||||
/// # pub struct CaseInsensitiveString(String);
|
||||
/// impl Hash for CaseInsensitiveString {
|
||||
/// fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
/// for c in self.0.as_bytes() {
|
||||
/// c.to_ascii_lowercase().hash(state)
|
||||
/// }
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// Can `CaseInsensitiveString` implement `Borrow<str>`? It certainly can
|
||||
/// provide a reference to a string slice via its contained owned string.
|
||||
/// But because its `Hash` implementation differs, it behaves differently
|
||||
/// from `str` and therefore must not, in fact, implement `Borrow<str>`.
|
||||
/// If it wants to allow others access to the underlying `str`, it can do
|
||||
/// that via `AsRef<str>` which doesn’t carry any extra requirements.
|
||||
///
|
||||
/// [`Hash`]: crate::hash::Hash
|
||||
/// [`HashMap<K, V>`]: ../../std/collections/struct.HashMap.html
|
||||
/// [`String`]: ../../std/string/struct.String.html
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub trait Borrow<Borrowed: ?Sized> {
|
||||
/// Immutably borrows from an owned value.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::borrow::Borrow;
|
||||
///
|
||||
/// fn check<T: Borrow<str>>(s: T) {
|
||||
/// assert_eq!("Hello", s.borrow());
|
||||
/// }
|
||||
///
|
||||
/// let s = "Hello".to_string();
|
||||
///
|
||||
/// check(s);
|
||||
///
|
||||
/// let s = "Hello";
|
||||
///
|
||||
/// check(s);
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
fn borrow(&self) -> &Borrowed;
|
||||
}
|
||||
|
||||
/// A trait for mutably borrowing data.
|
||||
///
|
||||
/// As a companion to [`Borrow<T>`] this trait allows a type to borrow as
|
||||
/// an underlying type by providing a mutable reference. See [`Borrow<T>`]
|
||||
/// for more information on borrowing as another type.
|
||||
///
|
||||
/// [`Borrow<T>`]: Borrow
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub trait BorrowMut<Borrowed: ?Sized>: Borrow<Borrowed> {
|
||||
/// Mutably borrows from an owned value.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::borrow::BorrowMut;
|
||||
///
|
||||
/// fn check<T: BorrowMut<[i32]>>(mut v: T) {
|
||||
/// assert_eq!(&mut [1, 2, 3], v.borrow_mut());
|
||||
/// }
|
||||
///
|
||||
/// let v = vec![1, 2, 3];
|
||||
///
|
||||
/// check(v);
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
fn borrow_mut(&mut self) -> &mut Borrowed;
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: ?Sized> Borrow<T> for T {
|
||||
fn borrow(&self) -> &T {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: ?Sized> BorrowMut<T> for T {
|
||||
fn borrow_mut(&mut self) -> &mut T {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: ?Sized> Borrow<T> for &T {
|
||||
fn borrow(&self) -> &T {
|
||||
&**self
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: ?Sized> Borrow<T> for &mut T {
|
||||
fn borrow(&self) -> &T {
|
||||
&**self
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: ?Sized> BorrowMut<T> for &mut T {
|
||||
fn borrow_mut(&mut self) -> &mut T {
|
||||
&mut **self
|
||||
}
|
||||
}
|
||||
1800
libgrust/rustc-lib/core/src/cell.rs
Normal file
1800
libgrust/rustc-lib/core/src/cell.rs
Normal file
File diff suppressed because it is too large
Load Diff
290
libgrust/rustc-lib/core/src/char/convert.rs
Normal file
290
libgrust/rustc-lib/core/src/char/convert.rs
Normal file
@@ -0,0 +1,290 @@
|
||||
//! Character conversions.
|
||||
|
||||
use crate::convert::TryFrom;
|
||||
use crate::fmt;
|
||||
use crate::mem::transmute;
|
||||
use crate::str::FromStr;
|
||||
|
||||
use super::MAX;
|
||||
|
||||
/// Converts a `u32` to a `char`.
|
||||
///
|
||||
/// Note that all [`char`]s are valid [`u32`]s, and can be cast to one with
|
||||
/// `as`:
|
||||
///
|
||||
/// ```
|
||||
/// let c = '💯';
|
||||
/// let i = c as u32;
|
||||
///
|
||||
/// assert_eq!(128175, i);
|
||||
/// ```
|
||||
///
|
||||
/// However, the reverse is not true: not all valid [`u32`]s are valid
|
||||
/// [`char`]s. `from_u32()` will return `None` if the input is not a valid value
|
||||
/// for a [`char`].
|
||||
///
|
||||
/// For an unsafe version of this function which ignores these checks, see
|
||||
/// [`from_u32_unchecked`].
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// use std::char;
|
||||
///
|
||||
/// let c = char::from_u32(0x2764);
|
||||
///
|
||||
/// assert_eq!(Some('❤'), c);
|
||||
/// ```
|
||||
///
|
||||
/// Returning `None` when the input is not a valid [`char`]:
|
||||
///
|
||||
/// ```
|
||||
/// use std::char;
|
||||
///
|
||||
/// let c = char::from_u32(0x110000);
|
||||
///
|
||||
/// assert_eq!(None, c);
|
||||
/// ```
|
||||
#[inline]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn from_u32(i: u32) -> Option<char> {
|
||||
char::try_from(i).ok()
|
||||
}
|
||||
|
||||
/// Converts a `u32` to a `char`, ignoring validity.
|
||||
///
|
||||
/// Note that all [`char`]s are valid [`u32`]s, and can be cast to one with
|
||||
/// `as`:
|
||||
///
|
||||
/// ```
|
||||
/// let c = '💯';
|
||||
/// let i = c as u32;
|
||||
///
|
||||
/// assert_eq!(128175, i);
|
||||
/// ```
|
||||
///
|
||||
/// However, the reverse is not true: not all valid [`u32`]s are valid
|
||||
/// [`char`]s. `from_u32_unchecked()` will ignore this, and blindly cast to
|
||||
/// [`char`], possibly creating an invalid one.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// This function is unsafe, as it may construct invalid `char` values.
|
||||
///
|
||||
/// For a safe version of this function, see the [`from_u32`] function.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// use std::char;
|
||||
///
|
||||
/// let c = unsafe { char::from_u32_unchecked(0x2764) };
|
||||
///
|
||||
/// assert_eq!('❤', c);
|
||||
/// ```
|
||||
#[inline]
|
||||
#[stable(feature = "char_from_unchecked", since = "1.5.0")]
|
||||
pub unsafe fn from_u32_unchecked(i: u32) -> char {
|
||||
// SAFETY: the caller must guarantee that `i` is a valid char value.
|
||||
if cfg!(debug_assertions) { char::from_u32(i).unwrap() } else { unsafe { transmute(i) } }
|
||||
}
|
||||
|
||||
#[stable(feature = "char_convert", since = "1.13.0")]
|
||||
impl From<char> for u32 {
|
||||
/// Converts a [`char`] into a [`u32`].
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::mem;
|
||||
///
|
||||
/// let c = 'c';
|
||||
/// let u = u32::from(c);
|
||||
/// assert!(4 == mem::size_of_val(&u))
|
||||
/// ```
|
||||
#[inline]
|
||||
fn from(c: char) -> Self {
|
||||
c as u32
|
||||
}
|
||||
}
|
||||
|
||||
/// Maps a byte in 0x00..=0xFF to a `char` whose code point has the same value, in U+0000..=U+00FF.
|
||||
///
|
||||
/// Unicode is designed such that this effectively decodes bytes
|
||||
/// with the character encoding that IANA calls ISO-8859-1.
|
||||
/// This encoding is compatible with ASCII.
|
||||
///
|
||||
/// Note that this is different from ISO/IEC 8859-1 a.k.a. ISO 8859-1 (with one less hyphen),
|
||||
/// which leaves some "blanks", byte values that are not assigned to any character.
|
||||
/// ISO-8859-1 (the IANA one) assigns them to the C0 and C1 control codes.
|
||||
///
|
||||
/// Note that this is *also* different from Windows-1252 a.k.a. code page 1252,
|
||||
/// which is a superset ISO/IEC 8859-1 that assigns some (not all!) blanks
|
||||
/// to punctuation and various Latin characters.
|
||||
///
|
||||
/// To confuse things further, [on the Web](https://encoding.spec.whatwg.org/)
|
||||
/// `ascii`, `iso-8859-1`, and `windows-1252` are all aliases
|
||||
/// for a superset of Windows-1252 that fills the remaining blanks with corresponding
|
||||
/// C0 and C1 control codes.
|
||||
#[stable(feature = "char_convert", since = "1.13.0")]
|
||||
impl From<u8> for char {
|
||||
/// Converts a [`u8`] into a [`char`].
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::mem;
|
||||
///
|
||||
/// let u = 32 as u8;
|
||||
/// let c = char::from(u);
|
||||
/// assert!(4 == mem::size_of_val(&c))
|
||||
/// ```
|
||||
#[inline]
|
||||
fn from(i: u8) -> Self {
|
||||
i as char
|
||||
}
|
||||
}
|
||||
|
||||
/// An error which can be returned when parsing a char.
|
||||
#[stable(feature = "char_from_str", since = "1.20.0")]
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub struct ParseCharError {
|
||||
kind: CharErrorKind,
|
||||
}
|
||||
|
||||
impl ParseCharError {
|
||||
#[unstable(
|
||||
feature = "char_error_internals",
|
||||
reason = "this method should not be available publicly",
|
||||
issue = "none"
|
||||
)]
|
||||
#[doc(hidden)]
|
||||
pub fn __description(&self) -> &str {
|
||||
match self.kind {
|
||||
CharErrorKind::EmptyString => "cannot parse char from empty string",
|
||||
CharErrorKind::TooManyChars => "too many characters in string",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
enum CharErrorKind {
|
||||
EmptyString,
|
||||
TooManyChars,
|
||||
}
|
||||
|
||||
#[stable(feature = "char_from_str", since = "1.20.0")]
|
||||
impl fmt::Display for ParseCharError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
self.__description().fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "char_from_str", since = "1.20.0")]
|
||||
impl FromStr for char {
|
||||
type Err = ParseCharError;
|
||||
|
||||
#[inline]
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
let mut chars = s.chars();
|
||||
match (chars.next(), chars.next()) {
|
||||
(None, _) => Err(ParseCharError { kind: CharErrorKind::EmptyString }),
|
||||
(Some(c), None) => Ok(c),
|
||||
_ => Err(ParseCharError { kind: CharErrorKind::TooManyChars }),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "try_from", since = "1.34.0")]
|
||||
impl TryFrom<u32> for char {
|
||||
type Error = CharTryFromError;
|
||||
|
||||
#[inline]
|
||||
fn try_from(i: u32) -> Result<Self, Self::Error> {
|
||||
if (i > MAX as u32) || (i >= 0xD800 && i <= 0xDFFF) {
|
||||
Err(CharTryFromError(()))
|
||||
} else {
|
||||
// SAFETY: checked that it's a legal unicode value
|
||||
Ok(unsafe { transmute(i) })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The error type returned when a conversion from u32 to char fails.
|
||||
#[stable(feature = "try_from", since = "1.34.0")]
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
pub struct CharTryFromError(());
|
||||
|
||||
#[stable(feature = "try_from", since = "1.34.0")]
|
||||
impl fmt::Display for CharTryFromError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
"converted integer out of range for `char`".fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
/// Converts a digit in the given radix to a `char`.
|
||||
///
|
||||
/// A 'radix' here is sometimes also called a 'base'. A radix of two
|
||||
/// indicates a binary number, a radix of ten, decimal, and a radix of
|
||||
/// sixteen, hexadecimal, to give some common values. Arbitrary
|
||||
/// radices are supported.
|
||||
///
|
||||
/// `from_digit()` will return `None` if the input is not a digit in
|
||||
/// the given radix.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if given a radix larger than 36.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// use std::char;
|
||||
///
|
||||
/// let c = char::from_digit(4, 10);
|
||||
///
|
||||
/// assert_eq!(Some('4'), c);
|
||||
///
|
||||
/// // Decimal 11 is a single digit in base 16
|
||||
/// let c = char::from_digit(11, 16);
|
||||
///
|
||||
/// assert_eq!(Some('b'), c);
|
||||
/// ```
|
||||
///
|
||||
/// Returning `None` when the input is not a digit:
|
||||
///
|
||||
/// ```
|
||||
/// use std::char;
|
||||
///
|
||||
/// let c = char::from_digit(20, 10);
|
||||
///
|
||||
/// assert_eq!(None, c);
|
||||
/// ```
|
||||
///
|
||||
/// Passing a large radix, causing a panic:
|
||||
///
|
||||
/// ```should_panic
|
||||
/// use std::char;
|
||||
///
|
||||
/// // this panics
|
||||
/// let c = char::from_digit(1, 37);
|
||||
/// ```
|
||||
#[inline]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn from_digit(num: u32, radix: u32) -> Option<char> {
|
||||
if radix > 36 {
|
||||
panic!("from_digit: radix is too high (maximum 36)");
|
||||
}
|
||||
if num < radix {
|
||||
let num = num as u8;
|
||||
if num < 10 { Some((b'0' + num) as char) } else { Some((b'a' + num - 10) as char) }
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
135
libgrust/rustc-lib/core/src/char/decode.rs
Normal file
135
libgrust/rustc-lib/core/src/char/decode.rs
Normal file
@@ -0,0 +1,135 @@
|
||||
//! UTF-8 and UTF-16 decoding iterators
|
||||
|
||||
use crate::fmt;
|
||||
|
||||
use super::from_u32_unchecked;
|
||||
|
||||
/// An iterator that decodes UTF-16 encoded code points from an iterator of `u16`s.
|
||||
#[stable(feature = "decode_utf16", since = "1.9.0")]
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct DecodeUtf16<I>
|
||||
where
|
||||
I: Iterator<Item = u16>,
|
||||
{
|
||||
iter: I,
|
||||
buf: Option<u16>,
|
||||
}
|
||||
|
||||
/// An error that can be returned when decoding UTF-16 code points.
|
||||
#[stable(feature = "decode_utf16", since = "1.9.0")]
|
||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||
pub struct DecodeUtf16Error {
|
||||
code: u16,
|
||||
}
|
||||
|
||||
/// Creates an iterator over the UTF-16 encoded code points in `iter`,
|
||||
/// returning unpaired surrogates as `Err`s.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// use std::char::decode_utf16;
|
||||
///
|
||||
/// // 𝄞mus<invalid>ic<invalid>
|
||||
/// let v = [
|
||||
/// 0xD834, 0xDD1E, 0x006d, 0x0075, 0x0073, 0xDD1E, 0x0069, 0x0063, 0xD834,
|
||||
/// ];
|
||||
///
|
||||
/// assert_eq!(
|
||||
/// decode_utf16(v.iter().cloned())
|
||||
/// .map(|r| r.map_err(|e| e.unpaired_surrogate()))
|
||||
/// .collect::<Vec<_>>(),
|
||||
/// vec![
|
||||
/// Ok('𝄞'),
|
||||
/// Ok('m'), Ok('u'), Ok('s'),
|
||||
/// Err(0xDD1E),
|
||||
/// Ok('i'), Ok('c'),
|
||||
/// Err(0xD834)
|
||||
/// ]
|
||||
/// );
|
||||
/// ```
|
||||
///
|
||||
/// A lossy decoder can be obtained by replacing `Err` results with the replacement character:
|
||||
///
|
||||
/// ```
|
||||
/// use std::char::{decode_utf16, REPLACEMENT_CHARACTER};
|
||||
///
|
||||
/// // 𝄞mus<invalid>ic<invalid>
|
||||
/// let v = [
|
||||
/// 0xD834, 0xDD1E, 0x006d, 0x0075, 0x0073, 0xDD1E, 0x0069, 0x0063, 0xD834,
|
||||
/// ];
|
||||
///
|
||||
/// assert_eq!(
|
||||
/// decode_utf16(v.iter().cloned())
|
||||
/// .map(|r| r.unwrap_or(REPLACEMENT_CHARACTER))
|
||||
/// .collect::<String>(),
|
||||
/// "𝄞mus<75>ic<69>"
|
||||
/// );
|
||||
/// ```
|
||||
#[stable(feature = "decode_utf16", since = "1.9.0")]
|
||||
#[inline]
|
||||
pub fn decode_utf16<I: IntoIterator<Item = u16>>(iter: I) -> DecodeUtf16<I::IntoIter> {
|
||||
DecodeUtf16 { iter: iter.into_iter(), buf: None }
|
||||
}
|
||||
|
||||
#[stable(feature = "decode_utf16", since = "1.9.0")]
|
||||
impl<I: Iterator<Item = u16>> Iterator for DecodeUtf16<I> {
|
||||
type Item = Result<char, DecodeUtf16Error>;
|
||||
|
||||
fn next(&mut self) -> Option<Result<char, DecodeUtf16Error>> {
|
||||
let u = match self.buf.take() {
|
||||
Some(buf) => buf,
|
||||
None => self.iter.next()?,
|
||||
};
|
||||
|
||||
if u < 0xD800 || 0xDFFF < u {
|
||||
// SAFETY: not a surrogate
|
||||
Some(Ok(unsafe { from_u32_unchecked(u as u32) }))
|
||||
} else if u >= 0xDC00 {
|
||||
// a trailing surrogate
|
||||
Some(Err(DecodeUtf16Error { code: u }))
|
||||
} else {
|
||||
let u2 = match self.iter.next() {
|
||||
Some(u2) => u2,
|
||||
// eof
|
||||
None => return Some(Err(DecodeUtf16Error { code: u })),
|
||||
};
|
||||
if u2 < 0xDC00 || u2 > 0xDFFF {
|
||||
// not a trailing surrogate so we're not a valid
|
||||
// surrogate pair, so rewind to redecode u2 next time.
|
||||
self.buf = Some(u2);
|
||||
return Some(Err(DecodeUtf16Error { code: u }));
|
||||
}
|
||||
|
||||
// all ok, so lets decode it.
|
||||
let c = (((u - 0xD800) as u32) << 10 | (u2 - 0xDC00) as u32) + 0x1_0000;
|
||||
// SAFETY: we checked that it's a legal unicode value
|
||||
Some(Ok(unsafe { from_u32_unchecked(c) }))
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
let (low, high) = self.iter.size_hint();
|
||||
// we could be entirely valid surrogates (2 elements per
|
||||
// char), or entirely non-surrogates (1 element per char)
|
||||
(low / 2, high)
|
||||
}
|
||||
}
|
||||
|
||||
impl DecodeUtf16Error {
|
||||
/// Returns the unpaired surrogate which caused this error.
|
||||
#[stable(feature = "decode_utf16", since = "1.9.0")]
|
||||
pub fn unpaired_surrogate(&self) -> u16 {
|
||||
self.code
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "decode_utf16", since = "1.9.0")]
|
||||
impl fmt::Display for DecodeUtf16Error {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "unpaired surrogate found: {:x}", self.code)
|
||||
}
|
||||
}
|
||||
1657
libgrust/rustc-lib/core/src/char/methods.rs
Normal file
1657
libgrust/rustc-lib/core/src/char/methods.rs
Normal file
File diff suppressed because it is too large
Load Diff
511
libgrust/rustc-lib/core/src/char/mod.rs
Normal file
511
libgrust/rustc-lib/core/src/char/mod.rs
Normal file
@@ -0,0 +1,511 @@
|
||||
//! A character type.
|
||||
//!
|
||||
//! The `char` type represents a single character. More specifically, since
|
||||
//! 'character' isn't a well-defined concept in Unicode, `char` is a '[Unicode
|
||||
//! scalar value]', which is similar to, but not the same as, a '[Unicode code
|
||||
//! point]'.
|
||||
//!
|
||||
//! [Unicode scalar value]: http://www.unicode.org/glossary/#unicode_scalar_value
|
||||
//! [Unicode code point]: http://www.unicode.org/glossary/#code_point
|
||||
//!
|
||||
//! This module exists for technical reasons, the primary documentation for
|
||||
//! `char` is directly on [the `char` primitive type](../../std/primitive.char.html)
|
||||
//! itself.
|
||||
//!
|
||||
//! This module is the home of the iterator implementations for the iterators
|
||||
//! implemented on `char`, as well as some useful constants and conversion
|
||||
//! functions that convert various types to `char`.
|
||||
|
||||
#![allow(non_snake_case)]
|
||||
#![stable(feature = "core_char", since = "1.2.0")]
|
||||
|
||||
mod convert;
|
||||
mod decode;
|
||||
mod methods;
|
||||
|
||||
// stable re-exports
|
||||
#[stable(feature = "char_from_unchecked", since = "1.5.0")]
|
||||
pub use self::convert::from_u32_unchecked;
|
||||
#[stable(feature = "try_from", since = "1.34.0")]
|
||||
pub use self::convert::CharTryFromError;
|
||||
#[stable(feature = "char_from_str", since = "1.20.0")]
|
||||
pub use self::convert::ParseCharError;
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use self::convert::{from_digit, from_u32};
|
||||
#[stable(feature = "decode_utf16", since = "1.9.0")]
|
||||
pub use self::decode::{decode_utf16, DecodeUtf16, DecodeUtf16Error};
|
||||
#[stable(feature = "unicode_version", since = "1.45.0")]
|
||||
pub use crate::unicode::UNICODE_VERSION;
|
||||
|
||||
// perma-unstable re-exports
|
||||
#[unstable(feature = "char_internals", reason = "exposed only for libstd", issue = "none")]
|
||||
pub use self::methods::encode_utf16_raw;
|
||||
#[unstable(feature = "char_internals", reason = "exposed only for libstd", issue = "none")]
|
||||
pub use self::methods::encode_utf8_raw;
|
||||
|
||||
use crate::fmt::{self, Write};
|
||||
use crate::iter::FusedIterator;
|
||||
|
||||
// UTF-8 ranges and tags for encoding characters
|
||||
const TAG_CONT: u8 = 0b1000_0000;
|
||||
const TAG_TWO_B: u8 = 0b1100_0000;
|
||||
const TAG_THREE_B: u8 = 0b1110_0000;
|
||||
const TAG_FOUR_B: u8 = 0b1111_0000;
|
||||
const MAX_ONE_B: u32 = 0x80;
|
||||
const MAX_TWO_B: u32 = 0x800;
|
||||
const MAX_THREE_B: u32 = 0x10000;
|
||||
|
||||
/*
|
||||
Lu Uppercase_Letter an uppercase letter
|
||||
Ll Lowercase_Letter a lowercase letter
|
||||
Lt Titlecase_Letter a digraphic character, with first part uppercase
|
||||
Lm Modifier_Letter a modifier letter
|
||||
Lo Other_Letter other letters, including syllables and ideographs
|
||||
Mn Nonspacing_Mark a nonspacing combining mark (zero advance width)
|
||||
Mc Spacing_Mark a spacing combining mark (positive advance width)
|
||||
Me Enclosing_Mark an enclosing combining mark
|
||||
Nd Decimal_Number a decimal digit
|
||||
Nl Letter_Number a letterlike numeric character
|
||||
No Other_Number a numeric character of other type
|
||||
Pc Connector_Punctuation a connecting punctuation mark, like a tie
|
||||
Pd Dash_Punctuation a dash or hyphen punctuation mark
|
||||
Ps Open_Punctuation an opening punctuation mark (of a pair)
|
||||
Pe Close_Punctuation a closing punctuation mark (of a pair)
|
||||
Pi Initial_Punctuation an initial quotation mark
|
||||
Pf Final_Punctuation a final quotation mark
|
||||
Po Other_Punctuation a punctuation mark of other type
|
||||
Sm Math_Symbol a symbol of primarily mathematical use
|
||||
Sc Currency_Symbol a currency sign
|
||||
Sk Modifier_Symbol a non-letterlike modifier symbol
|
||||
So Other_Symbol a symbol of other type
|
||||
Zs Space_Separator a space character (of various non-zero widths)
|
||||
Zl Line_Separator U+2028 LINE SEPARATOR only
|
||||
Zp Paragraph_Separator U+2029 PARAGRAPH SEPARATOR only
|
||||
Cc Control a C0 or C1 control code
|
||||
Cf Format a format control character
|
||||
Cs Surrogate a surrogate code point
|
||||
Co Private_Use a private-use character
|
||||
Cn Unassigned a reserved unassigned code point or a noncharacter
|
||||
*/
|
||||
|
||||
/// The highest valid code point a `char` can have.
|
||||
///
|
||||
/// A [`char`] is a [Unicode Scalar Value], which means that it is a [Code
|
||||
/// Point], but only ones within a certain range. `MAX` is the highest valid
|
||||
/// code point that's a valid [Unicode Scalar Value].
|
||||
///
|
||||
/// [Unicode Scalar Value]: http://www.unicode.org/glossary/#unicode_scalar_value
|
||||
/// [Code Point]: http://www.unicode.org/glossary/#code_point
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub const MAX: char = char::MAX;
|
||||
|
||||
/// `U+FFFD REPLACEMENT CHARACTER` (<28>) is used in Unicode to represent a
|
||||
/// decoding error.
|
||||
///
|
||||
/// It can occur, for example, when giving ill-formed UTF-8 bytes to
|
||||
/// [`String::from_utf8_lossy`](../../std/string/struct.String.html#method.from_utf8_lossy).
|
||||
#[stable(feature = "decode_utf16", since = "1.9.0")]
|
||||
pub const REPLACEMENT_CHARACTER: char = char::REPLACEMENT_CHARACTER;
|
||||
|
||||
/// Returns an iterator that yields the hexadecimal Unicode escape of a
|
||||
/// character, as `char`s.
|
||||
///
|
||||
/// This `struct` is created by the [`escape_unicode`] method on [`char`]. See
|
||||
/// its documentation for more.
|
||||
///
|
||||
/// [`escape_unicode`]: char::escape_unicode
|
||||
#[derive(Clone, Debug)]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub struct EscapeUnicode {
|
||||
c: char,
|
||||
state: EscapeUnicodeState,
|
||||
|
||||
// The index of the next hex digit to be printed (0 if none),
|
||||
// i.e., the number of remaining hex digits to be printed;
|
||||
// increasing from the least significant digit: 0x543210
|
||||
hex_digit_idx: usize,
|
||||
}
|
||||
|
||||
// The enum values are ordered so that their representation is the
|
||||
// same as the remaining length (besides the hexadecimal digits). This
|
||||
// likely makes `len()` a single load from memory) and inline-worth.
|
||||
#[derive(Clone, Debug)]
|
||||
enum EscapeUnicodeState {
|
||||
Done,
|
||||
RightBrace,
|
||||
Value,
|
||||
LeftBrace,
|
||||
Type,
|
||||
Backslash,
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl Iterator for EscapeUnicode {
|
||||
type Item = char;
|
||||
|
||||
fn next(&mut self) -> Option<char> {
|
||||
match self.state {
|
||||
EscapeUnicodeState::Backslash => {
|
||||
self.state = EscapeUnicodeState::Type;
|
||||
Some('\\')
|
||||
}
|
||||
EscapeUnicodeState::Type => {
|
||||
self.state = EscapeUnicodeState::LeftBrace;
|
||||
Some('u')
|
||||
}
|
||||
EscapeUnicodeState::LeftBrace => {
|
||||
self.state = EscapeUnicodeState::Value;
|
||||
Some('{')
|
||||
}
|
||||
EscapeUnicodeState::Value => {
|
||||
let hex_digit = ((self.c as u32) >> (self.hex_digit_idx * 4)) & 0xf;
|
||||
let c = from_digit(hex_digit, 16).unwrap();
|
||||
if self.hex_digit_idx == 0 {
|
||||
self.state = EscapeUnicodeState::RightBrace;
|
||||
} else {
|
||||
self.hex_digit_idx -= 1;
|
||||
}
|
||||
Some(c)
|
||||
}
|
||||
EscapeUnicodeState::RightBrace => {
|
||||
self.state = EscapeUnicodeState::Done;
|
||||
Some('}')
|
||||
}
|
||||
EscapeUnicodeState::Done => None,
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
let n = self.len();
|
||||
(n, Some(n))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn count(self) -> usize {
|
||||
self.len()
|
||||
}
|
||||
|
||||
fn last(self) -> Option<char> {
|
||||
match self.state {
|
||||
EscapeUnicodeState::Done => None,
|
||||
|
||||
EscapeUnicodeState::RightBrace
|
||||
| EscapeUnicodeState::Value
|
||||
| EscapeUnicodeState::LeftBrace
|
||||
| EscapeUnicodeState::Type
|
||||
| EscapeUnicodeState::Backslash => Some('}'),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "exact_size_escape", since = "1.11.0")]
|
||||
impl ExactSizeIterator for EscapeUnicode {
|
||||
#[inline]
|
||||
fn len(&self) -> usize {
|
||||
// The match is a single memory access with no branching
|
||||
self.hex_digit_idx
|
||||
+ match self.state {
|
||||
EscapeUnicodeState::Done => 0,
|
||||
EscapeUnicodeState::RightBrace => 1,
|
||||
EscapeUnicodeState::Value => 2,
|
||||
EscapeUnicodeState::LeftBrace => 3,
|
||||
EscapeUnicodeState::Type => 4,
|
||||
EscapeUnicodeState::Backslash => 5,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "fused", since = "1.26.0")]
|
||||
impl FusedIterator for EscapeUnicode {}
|
||||
|
||||
#[stable(feature = "char_struct_display", since = "1.16.0")]
|
||||
impl fmt::Display for EscapeUnicode {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
for c in self.clone() {
|
||||
f.write_char(c)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// An iterator that yields the literal escape code of a `char`.
|
||||
///
|
||||
/// This `struct` is created by the [`escape_default`] method on [`char`]. See
|
||||
/// its documentation for more.
|
||||
///
|
||||
/// [`escape_default`]: char::escape_default
|
||||
#[derive(Clone, Debug)]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub struct EscapeDefault {
|
||||
state: EscapeDefaultState,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
enum EscapeDefaultState {
|
||||
Done,
|
||||
Char(char),
|
||||
Backslash(char),
|
||||
Unicode(EscapeUnicode),
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl Iterator for EscapeDefault {
|
||||
type Item = char;
|
||||
|
||||
fn next(&mut self) -> Option<char> {
|
||||
match self.state {
|
||||
EscapeDefaultState::Backslash(c) => {
|
||||
self.state = EscapeDefaultState::Char(c);
|
||||
Some('\\')
|
||||
}
|
||||
EscapeDefaultState::Char(c) => {
|
||||
self.state = EscapeDefaultState::Done;
|
||||
Some(c)
|
||||
}
|
||||
EscapeDefaultState::Done => None,
|
||||
EscapeDefaultState::Unicode(ref mut iter) => iter.next(),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
let n = self.len();
|
||||
(n, Some(n))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn count(self) -> usize {
|
||||
self.len()
|
||||
}
|
||||
|
||||
fn nth(&mut self, n: usize) -> Option<char> {
|
||||
match self.state {
|
||||
EscapeDefaultState::Backslash(c) if n == 0 => {
|
||||
self.state = EscapeDefaultState::Char(c);
|
||||
Some('\\')
|
||||
}
|
||||
EscapeDefaultState::Backslash(c) if n == 1 => {
|
||||
self.state = EscapeDefaultState::Done;
|
||||
Some(c)
|
||||
}
|
||||
EscapeDefaultState::Backslash(_) => {
|
||||
self.state = EscapeDefaultState::Done;
|
||||
None
|
||||
}
|
||||
EscapeDefaultState::Char(c) => {
|
||||
self.state = EscapeDefaultState::Done;
|
||||
|
||||
if n == 0 { Some(c) } else { None }
|
||||
}
|
||||
EscapeDefaultState::Done => None,
|
||||
EscapeDefaultState::Unicode(ref mut i) => i.nth(n),
|
||||
}
|
||||
}
|
||||
|
||||
fn last(self) -> Option<char> {
|
||||
match self.state {
|
||||
EscapeDefaultState::Unicode(iter) => iter.last(),
|
||||
EscapeDefaultState::Done => None,
|
||||
EscapeDefaultState::Backslash(c) | EscapeDefaultState::Char(c) => Some(c),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "exact_size_escape", since = "1.11.0")]
|
||||
impl ExactSizeIterator for EscapeDefault {
|
||||
fn len(&self) -> usize {
|
||||
match self.state {
|
||||
EscapeDefaultState::Done => 0,
|
||||
EscapeDefaultState::Char(_) => 1,
|
||||
EscapeDefaultState::Backslash(_) => 2,
|
||||
EscapeDefaultState::Unicode(ref iter) => iter.len(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "fused", since = "1.26.0")]
|
||||
impl FusedIterator for EscapeDefault {}
|
||||
|
||||
#[stable(feature = "char_struct_display", since = "1.16.0")]
|
||||
impl fmt::Display for EscapeDefault {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
for c in self.clone() {
|
||||
f.write_char(c)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// An iterator that yields the literal escape code of a `char`.
|
||||
///
|
||||
/// This `struct` is created by the [`escape_debug`] method on [`char`]. See its
|
||||
/// documentation for more.
|
||||
///
|
||||
/// [`escape_debug`]: char::escape_debug
|
||||
#[stable(feature = "char_escape_debug", since = "1.20.0")]
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct EscapeDebug(EscapeDefault);
|
||||
|
||||
#[stable(feature = "char_escape_debug", since = "1.20.0")]
|
||||
impl Iterator for EscapeDebug {
|
||||
type Item = char;
|
||||
fn next(&mut self) -> Option<char> {
|
||||
self.0.next()
|
||||
}
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
self.0.size_hint()
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "char_escape_debug", since = "1.20.0")]
|
||||
impl ExactSizeIterator for EscapeDebug {}
|
||||
|
||||
#[stable(feature = "fused", since = "1.26.0")]
|
||||
impl FusedIterator for EscapeDebug {}
|
||||
|
||||
#[stable(feature = "char_escape_debug", since = "1.20.0")]
|
||||
impl fmt::Display for EscapeDebug {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt::Display::fmt(&self.0, f)
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns an iterator that yields the lowercase equivalent of a `char`.
|
||||
///
|
||||
/// This `struct` is created by the [`to_lowercase`] method on [`char`]. See
|
||||
/// its documentation for more.
|
||||
///
|
||||
/// [`to_lowercase`]: char::to_lowercase
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ToLowercase(CaseMappingIter);
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl Iterator for ToLowercase {
|
||||
type Item = char;
|
||||
fn next(&mut self) -> Option<char> {
|
||||
self.0.next()
|
||||
}
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
self.0.size_hint()
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "fused", since = "1.26.0")]
|
||||
impl FusedIterator for ToLowercase {}
|
||||
|
||||
#[stable(feature = "exact_size_case_mapping_iter", since = "1.35.0")]
|
||||
impl ExactSizeIterator for ToLowercase {}
|
||||
|
||||
/// Returns an iterator that yields the uppercase equivalent of a `char`.
|
||||
///
|
||||
/// This `struct` is created by the [`to_uppercase`] method on [`char`]. See
|
||||
/// its documentation for more.
|
||||
///
|
||||
/// [`to_uppercase`]: char::to_uppercase
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ToUppercase(CaseMappingIter);
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl Iterator for ToUppercase {
|
||||
type Item = char;
|
||||
fn next(&mut self) -> Option<char> {
|
||||
self.0.next()
|
||||
}
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
self.0.size_hint()
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "fused", since = "1.26.0")]
|
||||
impl FusedIterator for ToUppercase {}
|
||||
|
||||
#[stable(feature = "exact_size_case_mapping_iter", since = "1.35.0")]
|
||||
impl ExactSizeIterator for ToUppercase {}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
enum CaseMappingIter {
|
||||
Three(char, char, char),
|
||||
Two(char, char),
|
||||
One(char),
|
||||
Zero,
|
||||
}
|
||||
|
||||
impl CaseMappingIter {
|
||||
fn new(chars: [char; 3]) -> CaseMappingIter {
|
||||
if chars[2] == '\0' {
|
||||
if chars[1] == '\0' {
|
||||
CaseMappingIter::One(chars[0]) // Including if chars[0] == '\0'
|
||||
} else {
|
||||
CaseMappingIter::Two(chars[0], chars[1])
|
||||
}
|
||||
} else {
|
||||
CaseMappingIter::Three(chars[0], chars[1], chars[2])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Iterator for CaseMappingIter {
|
||||
type Item = char;
|
||||
fn next(&mut self) -> Option<char> {
|
||||
match *self {
|
||||
CaseMappingIter::Three(a, b, c) => {
|
||||
*self = CaseMappingIter::Two(b, c);
|
||||
Some(a)
|
||||
}
|
||||
CaseMappingIter::Two(b, c) => {
|
||||
*self = CaseMappingIter::One(c);
|
||||
Some(b)
|
||||
}
|
||||
CaseMappingIter::One(c) => {
|
||||
*self = CaseMappingIter::Zero;
|
||||
Some(c)
|
||||
}
|
||||
CaseMappingIter::Zero => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
let size = match self {
|
||||
CaseMappingIter::Three(..) => 3,
|
||||
CaseMappingIter::Two(..) => 2,
|
||||
CaseMappingIter::One(_) => 1,
|
||||
CaseMappingIter::Zero => 0,
|
||||
};
|
||||
(size, Some(size))
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for CaseMappingIter {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match *self {
|
||||
CaseMappingIter::Three(a, b, c) => {
|
||||
f.write_char(a)?;
|
||||
f.write_char(b)?;
|
||||
f.write_char(c)
|
||||
}
|
||||
CaseMappingIter::Two(b, c) => {
|
||||
f.write_char(b)?;
|
||||
f.write_char(c)
|
||||
}
|
||||
CaseMappingIter::One(c) => f.write_char(c),
|
||||
CaseMappingIter::Zero => Ok(()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "char_struct_display", since = "1.16.0")]
|
||||
impl fmt::Display for ToLowercase {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt::Display::fmt(&self.0, f)
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "char_struct_display", since = "1.16.0")]
|
||||
impl fmt::Display for ToUppercase {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt::Display::fmt(&self.0, f)
|
||||
}
|
||||
}
|
||||
232
libgrust/rustc-lib/core/src/clone.rs
Normal file
232
libgrust/rustc-lib/core/src/clone.rs
Normal file
@@ -0,0 +1,232 @@
|
||||
//! The `Clone` trait for types that cannot be 'implicitly copied'.
|
||||
//!
|
||||
//! In Rust, some simple types are "implicitly copyable" and when you
|
||||
//! assign them or pass them as arguments, the receiver will get a copy,
|
||||
//! leaving the original value in place. These types do not require
|
||||
//! allocation to copy and do not have finalizers (i.e., they do not
|
||||
//! contain owned boxes or implement [`Drop`]), so the compiler considers
|
||||
//! them cheap and safe to copy. For other types copies must be made
|
||||
//! explicitly, by convention implementing the [`Clone`] trait and calling
|
||||
//! the [`clone`] method.
|
||||
//!
|
||||
//! [`clone`]: Clone::clone
|
||||
//!
|
||||
//! Basic usage example:
|
||||
//!
|
||||
//! ```
|
||||
//! let s = String::new(); // String type implements Clone
|
||||
//! let copy = s.clone(); // so we can clone it
|
||||
//! ```
|
||||
//!
|
||||
//! To easily implement the Clone trait, you can also use
|
||||
//! `#[derive(Clone)]`. Example:
|
||||
//!
|
||||
//! ```
|
||||
//! #[derive(Clone)] // we add the Clone trait to Morpheus struct
|
||||
//! struct Morpheus {
|
||||
//! blue_pill: f32,
|
||||
//! red_pill: i64,
|
||||
//! }
|
||||
//!
|
||||
//! fn main() {
|
||||
//! let f = Morpheus { blue_pill: 0.0, red_pill: 0 };
|
||||
//! let copy = f.clone(); // and now we can clone it!
|
||||
//! }
|
||||
//! ```
|
||||
|
||||
#![stable(feature = "rust1", since = "1.0.0")]
|
||||
|
||||
/// A common trait for the ability to explicitly duplicate an object.
|
||||
///
|
||||
/// Differs from [`Copy`] in that [`Copy`] is implicit and extremely inexpensive, while
|
||||
/// `Clone` is always explicit and may or may not be expensive. In order to enforce
|
||||
/// these characteristics, Rust does not allow you to reimplement [`Copy`], but you
|
||||
/// may reimplement `Clone` and run arbitrary code.
|
||||
///
|
||||
/// Since `Clone` is more general than [`Copy`], you can automatically make anything
|
||||
/// [`Copy`] be `Clone` as well.
|
||||
///
|
||||
/// ## Derivable
|
||||
///
|
||||
/// This trait can be used with `#[derive]` if all fields are `Clone`. The `derive`d
|
||||
/// implementation of [`Clone`] calls [`clone`] on each field.
|
||||
///
|
||||
/// [`clone`]: Clone::clone
|
||||
///
|
||||
/// For a generic struct, `#[derive]` implements `Clone` conditionally by adding bound `Clone` on
|
||||
/// generic parameters.
|
||||
///
|
||||
/// ```
|
||||
/// // `derive` implements Clone for Reading<T> when T is Clone.
|
||||
/// #[derive(Clone)]
|
||||
/// struct Reading<T> {
|
||||
/// frequency: T,
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// ## How can I implement `Clone`?
|
||||
///
|
||||
/// Types that are [`Copy`] should have a trivial implementation of `Clone`. More formally:
|
||||
/// if `T: Copy`, `x: T`, and `y: &T`, then `let x = y.clone();` is equivalent to `let x = *y;`.
|
||||
/// Manual implementations should be careful to uphold this invariant; however, unsafe code
|
||||
/// must not rely on it to ensure memory safety.
|
||||
///
|
||||
/// An example is a generic struct holding a function pointer. In this case, the
|
||||
/// implementation of `Clone` cannot be `derive`d, but can be implemented as:
|
||||
///
|
||||
/// ```
|
||||
/// struct Generate<T>(fn() -> T);
|
||||
///
|
||||
/// impl<T> Copy for Generate<T> {}
|
||||
///
|
||||
/// impl<T> Clone for Generate<T> {
|
||||
/// fn clone(&self) -> Self {
|
||||
/// *self
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// ## Additional implementors
|
||||
///
|
||||
/// In addition to the [implementors listed below][impls],
|
||||
/// the following types also implement `Clone`:
|
||||
///
|
||||
/// * Function item types (i.e., the distinct types defined for each function)
|
||||
/// * Function pointer types (e.g., `fn() -> i32`)
|
||||
/// * Array types, for all sizes, if the item type also implements `Clone` (e.g., `[i32; 123456]`)
|
||||
/// * Tuple types, if each component also implements `Clone` (e.g., `()`, `(i32, bool)`)
|
||||
/// * Closure types, if they capture no value from the environment
|
||||
/// or if all such captured values implement `Clone` themselves.
|
||||
/// Note that variables captured by shared reference always implement `Clone`
|
||||
/// (even if the referent doesn't),
|
||||
/// while variables captured by mutable reference never implement `Clone`.
|
||||
///
|
||||
/// [impls]: #implementors
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[lang = "clone"]
|
||||
pub trait Clone: Sized {
|
||||
/// Returns a copy of the value.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// let hello = "Hello"; // &str implements Clone
|
||||
///
|
||||
/// assert_eq!("Hello", hello.clone());
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[must_use = "cloning is often expensive and is not expected to have side effects"]
|
||||
fn clone(&self) -> Self;
|
||||
|
||||
/// Performs copy-assignment from `source`.
|
||||
///
|
||||
/// `a.clone_from(&b)` is equivalent to `a = b.clone()` in functionality,
|
||||
/// but can be overridden to reuse the resources of `a` to avoid unnecessary
|
||||
/// allocations.
|
||||
#[inline]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
fn clone_from(&mut self, source: &Self) {
|
||||
*self = source.clone()
|
||||
}
|
||||
}
|
||||
|
||||
/// Derive macro generating an impl of the trait `Clone`.
|
||||
#[rustc_builtin_macro]
|
||||
#[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
|
||||
#[allow_internal_unstable(core_intrinsics, derive_clone_copy)]
|
||||
pub macro Clone($item:item) {
|
||||
/* compiler built-in */
|
||||
}
|
||||
|
||||
// FIXME(aburka): these structs are used solely by #[derive] to
|
||||
// assert that every component of a type implements Clone or Copy.
|
||||
//
|
||||
// These structs should never appear in user code.
|
||||
#[doc(hidden)]
|
||||
#[allow(missing_debug_implementations)]
|
||||
#[unstable(
|
||||
feature = "derive_clone_copy",
|
||||
reason = "deriving hack, should not be public",
|
||||
issue = "none"
|
||||
)]
|
||||
pub struct AssertParamIsClone<T: Clone + ?Sized> {
|
||||
_field: crate::marker::PhantomData<T>,
|
||||
}
|
||||
#[doc(hidden)]
|
||||
#[allow(missing_debug_implementations)]
|
||||
#[unstable(
|
||||
feature = "derive_clone_copy",
|
||||
reason = "deriving hack, should not be public",
|
||||
issue = "none"
|
||||
)]
|
||||
pub struct AssertParamIsCopy<T: Copy + ?Sized> {
|
||||
_field: crate::marker::PhantomData<T>,
|
||||
}
|
||||
|
||||
/// Implementations of `Clone` for primitive types.
|
||||
///
|
||||
/// Implementations that cannot be described in Rust
|
||||
/// are implemented in `traits::SelectionContext::copy_clone_conditions()`
|
||||
/// in `rustc_trait_selection`.
|
||||
mod impls {
|
||||
|
||||
use super::Clone;
|
||||
|
||||
macro_rules! impl_clone {
|
||||
($($t:ty)*) => {
|
||||
$(
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl Clone for $t {
|
||||
#[inline]
|
||||
fn clone(&self) -> Self {
|
||||
*self
|
||||
}
|
||||
}
|
||||
)*
|
||||
}
|
||||
}
|
||||
|
||||
impl_clone! {
|
||||
usize u8 u16 u32 u64 u128
|
||||
isize i8 i16 i32 i64 i128
|
||||
f32 f64
|
||||
bool char
|
||||
}
|
||||
|
||||
#[unstable(feature = "never_type", issue = "35121")]
|
||||
impl Clone for ! {
|
||||
#[inline]
|
||||
fn clone(&self) -> Self {
|
||||
*self
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: ?Sized> Clone for *const T {
|
||||
#[inline]
|
||||
fn clone(&self) -> Self {
|
||||
*self
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: ?Sized> Clone for *mut T {
|
||||
#[inline]
|
||||
fn clone(&self) -> Self {
|
||||
*self
|
||||
}
|
||||
}
|
||||
|
||||
/// Shared references can be cloned, but mutable references *cannot*!
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: ?Sized> Clone for &T {
|
||||
#[inline]
|
||||
fn clone(&self) -> Self {
|
||||
*self
|
||||
}
|
||||
}
|
||||
|
||||
/// Shared references can be cloned, but mutable references *cannot*!
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: ?Sized> !Clone for &mut T {}
|
||||
}
|
||||
1355
libgrust/rustc-lib/core/src/cmp.rs
Normal file
1355
libgrust/rustc-lib/core/src/cmp.rs
Normal file
File diff suppressed because it is too large
Load Diff
738
libgrust/rustc-lib/core/src/convert/mod.rs
Normal file
738
libgrust/rustc-lib/core/src/convert/mod.rs
Normal file
@@ -0,0 +1,738 @@
|
||||
//! Traits for conversions between types.
|
||||
//!
|
||||
//! The traits in this module provide a way to convert from one type to another type.
|
||||
//! Each trait serves a different purpose:
|
||||
//!
|
||||
//! - Implement the [`AsRef`] trait for cheap reference-to-reference conversions
|
||||
//! - Implement the [`AsMut`] trait for cheap mutable-to-mutable conversions
|
||||
//! - Implement the [`From`] trait for consuming value-to-value conversions
|
||||
//! - Implement the [`Into`] trait for consuming value-to-value conversions to types
|
||||
//! outside the current crate
|
||||
//! - The [`TryFrom`] and [`TryInto`] traits behave like [`From`] and [`Into`],
|
||||
//! but should be implemented when the conversion can fail.
|
||||
//!
|
||||
//! The traits in this module are often used as trait bounds for generic functions such that to
|
||||
//! arguments of multiple types are supported. See the documentation of each trait for examples.
|
||||
//!
|
||||
//! As a library author, you should always prefer implementing [`From<T>`][`From`] or
|
||||
//! [`TryFrom<T>`][`TryFrom`] rather than [`Into<U>`][`Into`] or [`TryInto<U>`][`TryInto`],
|
||||
//! as [`From`] and [`TryFrom`] provide greater flexibility and offer
|
||||
//! equivalent [`Into`] or [`TryInto`] implementations for free, thanks to a
|
||||
//! blanket implementation in the standard library. When targeting a version prior to Rust 1.41, it
|
||||
//! may be necessary to implement [`Into`] or [`TryInto`] directly when converting to a type
|
||||
//! outside the current crate.
|
||||
//!
|
||||
//! # Generic Implementations
|
||||
//!
|
||||
//! - [`AsRef`] and [`AsMut`] auto-dereference if the inner type is a reference
|
||||
//! - [`From`]`<U> for T` implies [`Into`]`<T> for U`
|
||||
//! - [`TryFrom`]`<U> for T` implies [`TryInto`]`<T> for U`
|
||||
//! - [`From`] and [`Into`] are reflexive, which means that all types can
|
||||
//! `into` themselves and `from` themselves
|
||||
//!
|
||||
//! See each trait for usage examples.
|
||||
|
||||
#![stable(feature = "rust1", since = "1.0.0")]
|
||||
|
||||
use crate::fmt;
|
||||
use crate::hash::{Hash, Hasher};
|
||||
|
||||
mod num;
|
||||
|
||||
#[unstable(feature = "convert_float_to_int", issue = "67057")]
|
||||
pub use num::FloatToInt;
|
||||
|
||||
/// The identity function.
|
||||
///
|
||||
/// Two things are important to note about this function:
|
||||
///
|
||||
/// - It is not always equivalent to a closure like `|x| x`, since the
|
||||
/// closure may coerce `x` into a different type.
|
||||
///
|
||||
/// - It moves the input `x` passed to the function.
|
||||
///
|
||||
/// While it might seem strange to have a function that just returns back the
|
||||
/// input, there are some interesting uses.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Using `identity` to do nothing in a sequence of other, interesting,
|
||||
/// functions:
|
||||
///
|
||||
/// ```rust
|
||||
/// use std::convert::identity;
|
||||
///
|
||||
/// fn manipulation(x: u32) -> u32 {
|
||||
/// // Let's pretend that adding one is an interesting function.
|
||||
/// x + 1
|
||||
/// }
|
||||
///
|
||||
/// let _arr = &[identity, manipulation];
|
||||
/// ```
|
||||
///
|
||||
/// Using `identity` as a "do nothing" base case in a conditional:
|
||||
///
|
||||
/// ```rust
|
||||
/// use std::convert::identity;
|
||||
///
|
||||
/// # let condition = true;
|
||||
/// #
|
||||
/// # fn manipulation(x: u32) -> u32 { x + 1 }
|
||||
/// #
|
||||
/// let do_stuff = if condition { manipulation } else { identity };
|
||||
///
|
||||
/// // Do more interesting stuff...
|
||||
///
|
||||
/// let _results = do_stuff(42);
|
||||
/// ```
|
||||
///
|
||||
/// Using `identity` to keep the `Some` variants of an iterator of `Option<T>`:
|
||||
///
|
||||
/// ```rust
|
||||
/// use std::convert::identity;
|
||||
///
|
||||
/// let iter = vec![Some(1), None, Some(3)].into_iter();
|
||||
/// let filtered = iter.filter_map(identity).collect::<Vec<_>>();
|
||||
/// assert_eq!(vec![1, 3], filtered);
|
||||
/// ```
|
||||
#[stable(feature = "convert_id", since = "1.33.0")]
|
||||
#[rustc_const_stable(feature = "const_identity", since = "1.33.0")]
|
||||
#[inline]
|
||||
pub const fn identity<T>(x: T) -> T {
|
||||
x
|
||||
}
|
||||
|
||||
/// Used to do a cheap reference-to-reference conversion.
|
||||
///
|
||||
/// This trait is similar to [`AsMut`] which is used for converting between mutable references.
|
||||
/// If you need to do a costly conversion it is better to implement [`From`] with type
|
||||
/// `&T` or write a custom function.
|
||||
///
|
||||
/// `AsRef` has the same signature as [`Borrow`], but [`Borrow`] is different in few aspects:
|
||||
///
|
||||
/// - Unlike `AsRef`, [`Borrow`] has a blanket impl for any `T`, and can be used to accept either
|
||||
/// a reference or a value.
|
||||
/// - [`Borrow`] also requires that [`Hash`], [`Eq`] and [`Ord`] for borrowed value are
|
||||
/// equivalent to those of the owned value. For this reason, if you want to
|
||||
/// borrow only a single field of a struct you can implement `AsRef`, but not [`Borrow`].
|
||||
///
|
||||
/// **Note: This trait must not fail**. If the conversion can fail, use a
|
||||
/// dedicated method which returns an [`Option<T>`] or a [`Result<T, E>`].
|
||||
///
|
||||
/// # Generic Implementations
|
||||
///
|
||||
/// - `AsRef` auto-dereferences if the inner type is a reference or a mutable
|
||||
/// reference (e.g.: `foo.as_ref()` will work the same if `foo` has type
|
||||
/// `&mut Foo` or `&&mut Foo`)
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// By using trait bounds we can accept arguments of different types as long as they can be
|
||||
/// converted to the specified type `T`.
|
||||
///
|
||||
/// For example: By creating a generic function that takes an `AsRef<str>` we express that we
|
||||
/// want to accept all references that can be converted to [`&str`] as an argument.
|
||||
/// Since both [`String`] and [`&str`] implement `AsRef<str>` we can accept both as input argument.
|
||||
///
|
||||
/// [`&str`]: primitive@str
|
||||
/// [`Option<T>`]: Option
|
||||
/// [`Result<T, E>`]: Result
|
||||
/// [`Borrow`]: crate::borrow::Borrow
|
||||
/// [`Eq`]: crate::cmp::Eq
|
||||
/// [`Ord`]: crate::cmp::Ord
|
||||
/// [`String`]: ../../std/string/struct.String.html
|
||||
///
|
||||
/// ```
|
||||
/// fn is_hello<T: AsRef<str>>(s: T) {
|
||||
/// assert_eq!("hello", s.as_ref());
|
||||
/// }
|
||||
///
|
||||
/// let s = "hello";
|
||||
/// is_hello(s);
|
||||
///
|
||||
/// let s = "hello".to_string();
|
||||
/// is_hello(s);
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub trait AsRef<T: ?Sized> {
|
||||
/// Performs the conversion.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
fn as_ref(&self) -> &T;
|
||||
}
|
||||
|
||||
/// Used to do a cheap mutable-to-mutable reference conversion.
|
||||
///
|
||||
/// This trait is similar to [`AsRef`] but used for converting between mutable
|
||||
/// references. If you need to do a costly conversion it is better to
|
||||
/// implement [`From`] with type `&mut T` or write a custom function.
|
||||
///
|
||||
/// **Note: This trait must not fail**. If the conversion can fail, use a
|
||||
/// dedicated method which returns an [`Option<T>`] or a [`Result<T, E>`].
|
||||
///
|
||||
/// [`Option<T>`]: Option
|
||||
/// [`Result<T, E>`]: Result
|
||||
///
|
||||
/// # Generic Implementations
|
||||
///
|
||||
/// - `AsMut` auto-dereferences if the inner type is a mutable reference
|
||||
/// (e.g.: `foo.as_mut()` will work the same if `foo` has type `&mut Foo`
|
||||
/// or `&mut &mut Foo`)
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Using `AsMut` as trait bound for a generic function we can accept all mutable references
|
||||
/// that can be converted to type `&mut T`. Because [`Box<T>`] implements `AsMut<T>` we can
|
||||
/// write a function `add_one` that takes all arguments that can be converted to `&mut u64`.
|
||||
/// Because [`Box<T>`] implements `AsMut<T>`, `add_one` accepts arguments of type
|
||||
/// `&mut Box<u64>` as well:
|
||||
///
|
||||
/// ```
|
||||
/// fn add_one<T: AsMut<u64>>(num: &mut T) {
|
||||
/// *num.as_mut() += 1;
|
||||
/// }
|
||||
///
|
||||
/// let mut boxed_num = Box::new(0);
|
||||
/// add_one(&mut boxed_num);
|
||||
/// assert_eq!(*boxed_num, 1);
|
||||
/// ```
|
||||
///
|
||||
/// [`Box<T>`]: ../../std/boxed/struct.Box.html
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub trait AsMut<T: ?Sized> {
|
||||
/// Performs the conversion.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
fn as_mut(&mut self) -> &mut T;
|
||||
}
|
||||
|
||||
/// A value-to-value conversion that consumes the input value. The
|
||||
/// opposite of [`From`].
|
||||
///
|
||||
/// One should avoid implementing [`Into`] and implement [`From`] instead.
|
||||
/// Implementing [`From`] automatically provides one with an implementation of [`Into`]
|
||||
/// thanks to the blanket implementation in the standard library.
|
||||
///
|
||||
/// Prefer using [`Into`] over [`From`] when specifying trait bounds on a generic function
|
||||
/// to ensure that types that only implement [`Into`] can be used as well.
|
||||
///
|
||||
/// **Note: This trait must not fail**. If the conversion can fail, use [`TryInto`].
|
||||
///
|
||||
/// # Generic Implementations
|
||||
///
|
||||
/// - [`From`]`<T> for U` implies `Into<U> for T`
|
||||
/// - [`Into`] is reflexive, which means that `Into<T> for T` is implemented
|
||||
///
|
||||
/// # Implementing [`Into`] for conversions to external types in old versions of Rust
|
||||
///
|
||||
/// Prior to Rust 1.41, if the destination type was not part of the current crate
|
||||
/// then you couldn't implement [`From`] directly.
|
||||
/// For example, take this code:
|
||||
///
|
||||
/// ```
|
||||
/// struct Wrapper<T>(Vec<T>);
|
||||
/// impl<T> From<Wrapper<T>> for Vec<T> {
|
||||
/// fn from(w: Wrapper<T>) -> Vec<T> {
|
||||
/// w.0
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
/// This will fail to compile in older versions of the language because Rust's orphaning rules
|
||||
/// used to be a little bit more strict. To bypass this, you could implement [`Into`] directly:
|
||||
///
|
||||
/// ```
|
||||
/// struct Wrapper<T>(Vec<T>);
|
||||
/// impl<T> Into<Vec<T>> for Wrapper<T> {
|
||||
/// fn into(self) -> Vec<T> {
|
||||
/// self.0
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// It is important to understand that [`Into`] does not provide a [`From`] implementation
|
||||
/// (as [`From`] does with [`Into`]). Therefore, you should always try to implement [`From`]
|
||||
/// and then fall back to [`Into`] if [`From`] can't be implemented.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// [`String`] implements [`Into`]`<`[`Vec`]`<`[`u8`]`>>`:
|
||||
///
|
||||
/// In order to express that we want a generic function to take all arguments that can be
|
||||
/// converted to a specified type `T`, we can use a trait bound of [`Into`]`<T>`.
|
||||
/// For example: The function `is_hello` takes all arguments that can be converted into a
|
||||
/// [`Vec`]`<`[`u8`]`>`.
|
||||
///
|
||||
/// ```
|
||||
/// fn is_hello<T: Into<Vec<u8>>>(s: T) {
|
||||
/// let bytes = b"hello".to_vec();
|
||||
/// assert_eq!(bytes, s.into());
|
||||
/// }
|
||||
///
|
||||
/// let s = "hello".to_string();
|
||||
/// is_hello(s);
|
||||
/// ```
|
||||
///
|
||||
/// [`Option<T>`]: Option
|
||||
/// [`Result<T, E>`]: Result
|
||||
/// [`String`]: ../../std/string/struct.String.html
|
||||
/// [`Vec`]: ../../std/vec/struct.Vec.html
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub trait Into<T>: Sized {
|
||||
/// Performs the conversion.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
fn into(self) -> T;
|
||||
}
|
||||
|
||||
/// Used to do value-to-value conversions while consuming the input value. It is the reciprocal of
|
||||
/// [`Into`].
|
||||
///
|
||||
/// One should always prefer implementing `From` over [`Into`]
|
||||
/// because implementing `From` automatically provides one with an implementation of [`Into`]
|
||||
/// thanks to the blanket implementation in the standard library.
|
||||
///
|
||||
/// Only implement [`Into`] when targeting a version prior to Rust 1.41 and converting to a type
|
||||
/// outside the current crate.
|
||||
/// `From` was not able to do these types of conversions in earlier versions because of Rust's
|
||||
/// orphaning rules.
|
||||
/// See [`Into`] for more details.
|
||||
///
|
||||
/// Prefer using [`Into`] over using `From` when specifying trait bounds on a generic function.
|
||||
/// This way, types that directly implement [`Into`] can be used as arguments as well.
|
||||
///
|
||||
/// The `From` is also very useful when performing error handling. When constructing a function
|
||||
/// that is capable of failing, the return type will generally be of the form `Result<T, E>`.
|
||||
/// The `From` trait simplifies error handling by allowing a function to return a single error type
|
||||
/// that encapsulate multiple error types. See the "Examples" section and [the book][book] for more
|
||||
/// details.
|
||||
///
|
||||
/// **Note: This trait must not fail**. If the conversion can fail, use [`TryFrom`].
|
||||
///
|
||||
/// # Generic Implementations
|
||||
///
|
||||
/// - `From<T> for U` implies [`Into`]`<U> for T`
|
||||
/// - `From` is reflexive, which means that `From<T> for T` is implemented
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// [`String`] implements `From<&str>`:
|
||||
///
|
||||
/// An explicit conversion from a `&str` to a String is done as follows:
|
||||
///
|
||||
/// ```
|
||||
/// let string = "hello".to_string();
|
||||
/// let other_string = String::from("hello");
|
||||
///
|
||||
/// assert_eq!(string, other_string);
|
||||
/// ```
|
||||
///
|
||||
/// While performing error handling it is often useful to implement `From` for your own error type.
|
||||
/// By converting underlying error types to our own custom error type that encapsulates the
|
||||
/// underlying error type, we can return a single error type without losing information on the
|
||||
/// underlying cause. The '?' operator automatically converts the underlying error type to our
|
||||
/// custom error type by calling `Into<CliError>::into` which is automatically provided when
|
||||
/// implementing `From`. The compiler then infers which implementation of `Into` should be used.
|
||||
///
|
||||
/// ```
|
||||
/// use std::fs;
|
||||
/// use std::io;
|
||||
/// use std::num;
|
||||
///
|
||||
/// enum CliError {
|
||||
/// IoError(io::Error),
|
||||
/// ParseError(num::ParseIntError),
|
||||
/// }
|
||||
///
|
||||
/// impl From<io::Error> for CliError {
|
||||
/// fn from(error: io::Error) -> Self {
|
||||
/// CliError::IoError(error)
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// impl From<num::ParseIntError> for CliError {
|
||||
/// fn from(error: num::ParseIntError) -> Self {
|
||||
/// CliError::ParseError(error)
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// fn open_and_parse_file(file_name: &str) -> Result<i32, CliError> {
|
||||
/// let mut contents = fs::read_to_string(&file_name)?;
|
||||
/// let num: i32 = contents.trim().parse()?;
|
||||
/// Ok(num)
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// [`Option<T>`]: Option
|
||||
/// [`Result<T, E>`]: Result
|
||||
/// [`String`]: ../../std/string/struct.String.html
|
||||
/// [`from`]: From::from
|
||||
/// [book]: ../../book/ch09-00-error-handling.html
|
||||
#[rustc_diagnostic_item = "from_trait"]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_on_unimplemented(on(
|
||||
all(_Self = "&str", T = "std::string::String"),
|
||||
note = "to coerce a `{T}` into a `{Self}`, use `&*` as a prefix",
|
||||
))]
|
||||
pub trait From<T>: Sized {
|
||||
/// Performs the conversion.
|
||||
#[lang = "from"]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
fn from(_: T) -> Self;
|
||||
}
|
||||
|
||||
/// An attempted conversion that consumes `self`, which may or may not be
|
||||
/// expensive.
|
||||
///
|
||||
/// Library authors should usually not directly implement this trait,
|
||||
/// but should prefer implementing the [`TryFrom`] trait, which offers
|
||||
/// greater flexibility and provides an equivalent `TryInto`
|
||||
/// implementation for free, thanks to a blanket implementation in the
|
||||
/// standard library. For more information on this, see the
|
||||
/// documentation for [`Into`].
|
||||
///
|
||||
/// # Implementing `TryInto`
|
||||
///
|
||||
/// This suffers the same restrictions and reasoning as implementing
|
||||
/// [`Into`], see there for details.
|
||||
#[stable(feature = "try_from", since = "1.34.0")]
|
||||
pub trait TryInto<T>: Sized {
|
||||
/// The type returned in the event of a conversion error.
|
||||
#[stable(feature = "try_from", since = "1.34.0")]
|
||||
type Error;
|
||||
|
||||
/// Performs the conversion.
|
||||
#[stable(feature = "try_from", since = "1.34.0")]
|
||||
fn try_into(self) -> Result<T, Self::Error>;
|
||||
}
|
||||
|
||||
/// Simple and safe type conversions that may fail in a controlled
|
||||
/// way under some circumstances. It is the reciprocal of [`TryInto`].
|
||||
///
|
||||
/// This is useful when you are doing a type conversion that may
|
||||
/// trivially succeed but may also need special handling.
|
||||
/// For example, there is no way to convert an [`i64`] into an [`i32`]
|
||||
/// using the [`From`] trait, because an [`i64`] may contain a value
|
||||
/// that an [`i32`] cannot represent and so the conversion would lose data.
|
||||
/// This might be handled by truncating the [`i64`] to an [`i32`] (essentially
|
||||
/// giving the [`i64`]'s value modulo [`i32::MAX`]) or by simply returning
|
||||
/// [`i32::MAX`], or by some other method. The [`From`] trait is intended
|
||||
/// for perfect conversions, so the `TryFrom` trait informs the
|
||||
/// programmer when a type conversion could go bad and lets them
|
||||
/// decide how to handle it.
|
||||
///
|
||||
/// # Generic Implementations
|
||||
///
|
||||
/// - `TryFrom<T> for U` implies [`TryInto`]`<U> for T`
|
||||
/// - [`try_from`] is reflexive, which means that `TryFrom<T> for T`
|
||||
/// is implemented and cannot fail -- the associated `Error` type for
|
||||
/// calling `T::try_from()` on a value of type `T` is [`Infallible`].
|
||||
/// When the [`!`] type is stabilized [`Infallible`] and [`!`] will be
|
||||
/// equivalent.
|
||||
///
|
||||
/// `TryFrom<T>` can be implemented as follows:
|
||||
///
|
||||
/// ```
|
||||
/// use std::convert::TryFrom;
|
||||
///
|
||||
/// struct GreaterThanZero(i32);
|
||||
///
|
||||
/// impl TryFrom<i32> for GreaterThanZero {
|
||||
/// type Error = &'static str;
|
||||
///
|
||||
/// fn try_from(value: i32) -> Result<Self, Self::Error> {
|
||||
/// if value <= 0 {
|
||||
/// Err("GreaterThanZero only accepts value superior than zero!")
|
||||
/// } else {
|
||||
/// Ok(GreaterThanZero(value))
|
||||
/// }
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// As described, [`i32`] implements `TryFrom<`[`i64`]`>`:
|
||||
///
|
||||
/// ```
|
||||
/// use std::convert::TryFrom;
|
||||
///
|
||||
/// let big_number = 1_000_000_000_000i64;
|
||||
/// // Silently truncates `big_number`, requires detecting
|
||||
/// // and handling the truncation after the fact.
|
||||
/// let smaller_number = big_number as i32;
|
||||
/// assert_eq!(smaller_number, -727379968);
|
||||
///
|
||||
/// // Returns an error because `big_number` is too big to
|
||||
/// // fit in an `i32`.
|
||||
/// let try_smaller_number = i32::try_from(big_number);
|
||||
/// assert!(try_smaller_number.is_err());
|
||||
///
|
||||
/// // Returns `Ok(3)`.
|
||||
/// let try_successful_smaller_number = i32::try_from(3);
|
||||
/// assert!(try_successful_smaller_number.is_ok());
|
||||
/// ```
|
||||
///
|
||||
/// [`i32::MAX`]: crate::i32::MAX
|
||||
/// [`try_from`]: TryFrom::try_from
|
||||
/// [`!`]: ../../std/primitive.never.html
|
||||
#[stable(feature = "try_from", since = "1.34.0")]
|
||||
pub trait TryFrom<T>: Sized {
|
||||
/// The type returned in the event of a conversion error.
|
||||
#[stable(feature = "try_from", since = "1.34.0")]
|
||||
type Error;
|
||||
|
||||
/// Performs the conversion.
|
||||
#[stable(feature = "try_from", since = "1.34.0")]
|
||||
fn try_from(value: T) -> Result<Self, Self::Error>;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// GENERIC IMPLS
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// As lifts over &
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: ?Sized, U: ?Sized> AsRef<U> for &T
|
||||
where
|
||||
T: AsRef<U>,
|
||||
{
|
||||
fn as_ref(&self) -> &U {
|
||||
<T as AsRef<U>>::as_ref(*self)
|
||||
}
|
||||
}
|
||||
|
||||
// As lifts over &mut
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: ?Sized, U: ?Sized> AsRef<U> for &mut T
|
||||
where
|
||||
T: AsRef<U>,
|
||||
{
|
||||
fn as_ref(&self) -> &U {
|
||||
<T as AsRef<U>>::as_ref(*self)
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME (#45742): replace the above impls for &/&mut with the following more general one:
|
||||
// // As lifts over Deref
|
||||
// impl<D: ?Sized + Deref<Target: AsRef<U>>, U: ?Sized> AsRef<U> for D {
|
||||
// fn as_ref(&self) -> &U {
|
||||
// self.deref().as_ref()
|
||||
// }
|
||||
// }
|
||||
|
||||
// AsMut lifts over &mut
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: ?Sized, U: ?Sized> AsMut<U> for &mut T
|
||||
where
|
||||
T: AsMut<U>,
|
||||
{
|
||||
fn as_mut(&mut self) -> &mut U {
|
||||
(*self).as_mut()
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME (#45742): replace the above impl for &mut with the following more general one:
|
||||
// // AsMut lifts over DerefMut
|
||||
// impl<D: ?Sized + Deref<Target: AsMut<U>>, U: ?Sized> AsMut<U> for D {
|
||||
// fn as_mut(&mut self) -> &mut U {
|
||||
// self.deref_mut().as_mut()
|
||||
// }
|
||||
// }
|
||||
|
||||
// From implies Into
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T, U> Into<U> for T
|
||||
where
|
||||
U: From<T>,
|
||||
{
|
||||
fn into(self) -> U {
|
||||
U::from(self)
|
||||
}
|
||||
}
|
||||
|
||||
// From (and thus Into) is reflexive
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T> From<T> for T {
|
||||
fn from(t: T) -> T {
|
||||
t
|
||||
}
|
||||
}
|
||||
|
||||
/// **Stability note:** This impl does not yet exist, but we are
|
||||
/// "reserving space" to add it in the future. See
|
||||
/// [rust-lang/rust#64715][#64715] for details.
|
||||
///
|
||||
/// [#64715]: https://github.com/rust-lang/rust/issues/64715
|
||||
#[stable(feature = "convert_infallible", since = "1.34.0")]
|
||||
#[allow(unused_attributes)] // FIXME(#58633): do a principled fix instead.
|
||||
#[rustc_reservation_impl = "permitting this impl would forbid us from adding \
|
||||
`impl<T> From<!> for T` later; see rust-lang/rust#64715 for details"]
|
||||
impl<T> From<!> for T {
|
||||
fn from(t: !) -> T {
|
||||
t
|
||||
}
|
||||
}
|
||||
|
||||
// TryFrom implies TryInto
|
||||
#[stable(feature = "try_from", since = "1.34.0")]
|
||||
impl<T, U> TryInto<U> for T
|
||||
where
|
||||
U: TryFrom<T>,
|
||||
{
|
||||
type Error = U::Error;
|
||||
|
||||
fn try_into(self) -> Result<U, U::Error> {
|
||||
U::try_from(self)
|
||||
}
|
||||
}
|
||||
|
||||
// Infallible conversions are semantically equivalent to fallible conversions
|
||||
// with an uninhabited error type.
|
||||
#[stable(feature = "try_from", since = "1.34.0")]
|
||||
impl<T, U> TryFrom<U> for T
|
||||
where
|
||||
U: Into<T>,
|
||||
{
|
||||
type Error = Infallible;
|
||||
|
||||
fn try_from(value: U) -> Result<Self, Self::Error> {
|
||||
Ok(U::into(value))
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// CONCRETE IMPLS
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T> AsRef<[T]> for [T] {
|
||||
fn as_ref(&self) -> &[T] {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T> AsMut<[T]> for [T] {
|
||||
fn as_mut(&mut self) -> &mut [T] {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl AsRef<str> for str {
|
||||
#[inline]
|
||||
fn as_ref(&self) -> &str {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// THE NO-ERROR ERROR TYPE
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// The error type for errors that can never happen.
|
||||
///
|
||||
/// Since this enum has no variant, a value of this type can never actually exist.
|
||||
/// This can be useful for generic APIs that use [`Result`] and parameterize the error type,
|
||||
/// to indicate that the result is always [`Ok`].
|
||||
///
|
||||
/// For example, the [`TryFrom`] trait (conversion that returns a [`Result`])
|
||||
/// has a blanket implementation for all types where a reverse [`Into`] implementation exists.
|
||||
///
|
||||
/// ```ignore (illustrates std code, duplicating the impl in a doctest would be an error)
|
||||
/// impl<T, U> TryFrom<U> for T where U: Into<T> {
|
||||
/// type Error = Infallible;
|
||||
///
|
||||
/// fn try_from(value: U) -> Result<Self, Infallible> {
|
||||
/// Ok(U::into(value)) // Never returns `Err`
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// # Future compatibility
|
||||
///
|
||||
/// This enum has the same role as [the `!` “never” type][never],
|
||||
/// which is unstable in this version of Rust.
|
||||
/// When `!` is stabilized, we plan to make `Infallible` a type alias to it:
|
||||
///
|
||||
/// ```ignore (illustrates future std change)
|
||||
/// pub type Infallible = !;
|
||||
/// ```
|
||||
///
|
||||
/// … and eventually deprecate `Infallible`.
|
||||
///
|
||||
/// However there is one case where `!` syntax can be used
|
||||
/// before `!` is stabilized as a full-fledged type: in the position of a function’s return type.
|
||||
/// Specifically, it is possible implementations for two different function pointer types:
|
||||
///
|
||||
/// ```
|
||||
/// trait MyTrait {}
|
||||
/// impl MyTrait for fn() -> ! {}
|
||||
/// impl MyTrait for fn() -> std::convert::Infallible {}
|
||||
/// ```
|
||||
///
|
||||
/// With `Infallible` being an enum, this code is valid.
|
||||
/// However when `Infallible` becomes an alias for the never type,
|
||||
/// the two `impl`s will start to overlap
|
||||
/// and therefore will be disallowed by the language’s trait coherence rules.
|
||||
///
|
||||
/// [never]: ../../std/primitive.never.html
|
||||
#[stable(feature = "convert_infallible", since = "1.34.0")]
|
||||
#[derive(Copy)]
|
||||
pub enum Infallible {}
|
||||
|
||||
#[stable(feature = "convert_infallible", since = "1.34.0")]
|
||||
impl Clone for Infallible {
|
||||
fn clone(&self) -> Infallible {
|
||||
match *self {}
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "convert_infallible", since = "1.34.0")]
|
||||
impl fmt::Debug for Infallible {
|
||||
fn fmt(&self, _: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match *self {}
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "convert_infallible", since = "1.34.0")]
|
||||
impl fmt::Display for Infallible {
|
||||
fn fmt(&self, _: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match *self {}
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "convert_infallible", since = "1.34.0")]
|
||||
impl PartialEq for Infallible {
|
||||
fn eq(&self, _: &Infallible) -> bool {
|
||||
match *self {}
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "convert_infallible", since = "1.34.0")]
|
||||
impl Eq for Infallible {}
|
||||
|
||||
#[stable(feature = "convert_infallible", since = "1.34.0")]
|
||||
impl PartialOrd for Infallible {
|
||||
fn partial_cmp(&self, _other: &Self) -> Option<crate::cmp::Ordering> {
|
||||
match *self {}
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "convert_infallible", since = "1.34.0")]
|
||||
impl Ord for Infallible {
|
||||
fn cmp(&self, _other: &Self) -> crate::cmp::Ordering {
|
||||
match *self {}
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "convert_infallible", since = "1.34.0")]
|
||||
impl From<!> for Infallible {
|
||||
fn from(x: !) -> Self {
|
||||
x
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "convert_infallible_hash", since = "1.44.0")]
|
||||
impl Hash for Infallible {
|
||||
fn hash<H: Hasher>(&self, _: &mut H) {
|
||||
match *self {}
|
||||
}
|
||||
}
|
||||
533
libgrust/rustc-lib/core/src/convert/num.rs
Normal file
533
libgrust/rustc-lib/core/src/convert/num.rs
Normal file
@@ -0,0 +1,533 @@
|
||||
use super::{From, TryFrom};
|
||||
use crate::num::TryFromIntError;
|
||||
|
||||
mod private {
|
||||
/// This trait being unreachable from outside the crate
|
||||
/// prevents other implementations of the `FloatToInt` trait,
|
||||
/// which allows potentially adding more trait methods after the trait is `#[stable]`.
|
||||
#[unstable(feature = "convert_float_to_int", issue = "67057")]
|
||||
pub trait Sealed {}
|
||||
}
|
||||
|
||||
/// Supporting trait for inherent methods of `f32` and `f64` such as `round_unchecked_to`.
|
||||
/// Typically doesn’t need to be used directly.
|
||||
#[unstable(feature = "convert_float_to_int", issue = "67057")]
|
||||
pub trait FloatToInt<Int>: private::Sealed + Sized {
|
||||
#[unstable(feature = "convert_float_to_int", issue = "67057")]
|
||||
#[doc(hidden)]
|
||||
unsafe fn to_int_unchecked(self) -> Int;
|
||||
}
|
||||
|
||||
macro_rules! impl_float_to_int {
|
||||
( $Float: ident => $( $Int: ident )+ ) => {
|
||||
#[unstable(feature = "convert_float_to_int", issue = "67057")]
|
||||
impl private::Sealed for $Float {}
|
||||
$(
|
||||
#[unstable(feature = "convert_float_to_int", issue = "67057")]
|
||||
impl FloatToInt<$Int> for $Float {
|
||||
#[doc(hidden)]
|
||||
#[inline]
|
||||
unsafe fn to_int_unchecked(self) -> $Int {
|
||||
// SAFETY: the safety contract must be upheld by the caller.
|
||||
unsafe { crate::intrinsics::float_to_int_unchecked(self) }
|
||||
}
|
||||
}
|
||||
)+
|
||||
}
|
||||
}
|
||||
|
||||
impl_float_to_int!(f32 => u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize);
|
||||
impl_float_to_int!(f64 => u8 u16 u32 u64 u128 usize i8 i16 i32 i64 i128 isize);
|
||||
|
||||
// Conversion traits for primitive integer and float types
|
||||
// Conversions T -> T are covered by a blanket impl and therefore excluded
|
||||
// Some conversions from and to usize/isize are not implemented due to portability concerns
|
||||
macro_rules! impl_from {
|
||||
($Small: ty, $Large: ty, #[$attr:meta], $doc: expr) => {
|
||||
#[$attr]
|
||||
#[doc = $doc]
|
||||
impl From<$Small> for $Large {
|
||||
#[inline]
|
||||
fn from(small: $Small) -> Self {
|
||||
small as Self
|
||||
}
|
||||
}
|
||||
};
|
||||
($Small: ty, $Large: ty, #[$attr:meta]) => {
|
||||
impl_from!($Small,
|
||||
$Large,
|
||||
#[$attr],
|
||||
concat!("Converts `",
|
||||
stringify!($Small),
|
||||
"` to `",
|
||||
stringify!($Large),
|
||||
"` losslessly."));
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! impl_from_bool {
|
||||
($target: ty, #[$attr:meta]) => {
|
||||
impl_from!(bool, $target, #[$attr], concat!("Converts a `bool` to a `",
|
||||
stringify!($target), "`. The resulting value is `0` for `false` and `1` for `true`
|
||||
values.
|
||||
|
||||
# Examples
|
||||
|
||||
```
|
||||
assert_eq!(", stringify!($target), "::from(true), 1);
|
||||
assert_eq!(", stringify!($target), "::from(false), 0);
|
||||
```"));
|
||||
};
|
||||
}
|
||||
|
||||
// Bool -> Any
|
||||
impl_from_bool! { u8, #[stable(feature = "from_bool", since = "1.28.0")] }
|
||||
impl_from_bool! { u16, #[stable(feature = "from_bool", since = "1.28.0")] }
|
||||
impl_from_bool! { u32, #[stable(feature = "from_bool", since = "1.28.0")] }
|
||||
impl_from_bool! { u64, #[stable(feature = "from_bool", since = "1.28.0")] }
|
||||
impl_from_bool! { u128, #[stable(feature = "from_bool", since = "1.28.0")] }
|
||||
impl_from_bool! { usize, #[stable(feature = "from_bool", since = "1.28.0")] }
|
||||
impl_from_bool! { i8, #[stable(feature = "from_bool", since = "1.28.0")] }
|
||||
impl_from_bool! { i16, #[stable(feature = "from_bool", since = "1.28.0")] }
|
||||
impl_from_bool! { i32, #[stable(feature = "from_bool", since = "1.28.0")] }
|
||||
impl_from_bool! { i64, #[stable(feature = "from_bool", since = "1.28.0")] }
|
||||
impl_from_bool! { i128, #[stable(feature = "from_bool", since = "1.28.0")] }
|
||||
impl_from_bool! { isize, #[stable(feature = "from_bool", since = "1.28.0")] }
|
||||
|
||||
// Unsigned -> Unsigned
|
||||
impl_from! { u8, u16, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
|
||||
impl_from! { u8, u32, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
|
||||
impl_from! { u8, u64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
|
||||
impl_from! { u8, u128, #[stable(feature = "i128", since = "1.26.0")] }
|
||||
impl_from! { u8, usize, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
|
||||
impl_from! { u16, u32, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
|
||||
impl_from! { u16, u64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
|
||||
impl_from! { u16, u128, #[stable(feature = "i128", since = "1.26.0")] }
|
||||
impl_from! { u32, u64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
|
||||
impl_from! { u32, u128, #[stable(feature = "i128", since = "1.26.0")] }
|
||||
impl_from! { u64, u128, #[stable(feature = "i128", since = "1.26.0")] }
|
||||
|
||||
// Signed -> Signed
|
||||
impl_from! { i8, i16, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
|
||||
impl_from! { i8, i32, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
|
||||
impl_from! { i8, i64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
|
||||
impl_from! { i8, i128, #[stable(feature = "i128", since = "1.26.0")] }
|
||||
impl_from! { i8, isize, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
|
||||
impl_from! { i16, i32, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
|
||||
impl_from! { i16, i64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
|
||||
impl_from! { i16, i128, #[stable(feature = "i128", since = "1.26.0")] }
|
||||
impl_from! { i32, i64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
|
||||
impl_from! { i32, i128, #[stable(feature = "i128", since = "1.26.0")] }
|
||||
impl_from! { i64, i128, #[stable(feature = "i128", since = "1.26.0")] }
|
||||
|
||||
// Unsigned -> Signed
|
||||
impl_from! { u8, i16, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
|
||||
impl_from! { u8, i32, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
|
||||
impl_from! { u8, i64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
|
||||
impl_from! { u8, i128, #[stable(feature = "i128", since = "1.26.0")] }
|
||||
impl_from! { u16, i32, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
|
||||
impl_from! { u16, i64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
|
||||
impl_from! { u16, i128, #[stable(feature = "i128", since = "1.26.0")] }
|
||||
impl_from! { u32, i64, #[stable(feature = "lossless_int_conv", since = "1.5.0")] }
|
||||
impl_from! { u32, i128, #[stable(feature = "i128", since = "1.26.0")] }
|
||||
impl_from! { u64, i128, #[stable(feature = "i128", since = "1.26.0")] }
|
||||
|
||||
// The C99 standard defines bounds on INTPTR_MIN, INTPTR_MAX, and UINTPTR_MAX
|
||||
// which imply that pointer-sized integers must be at least 16 bits:
|
||||
// https://port70.net/~nsz/c/c99/n1256.html#7.18.2.4
|
||||
impl_from! { u16, usize, #[stable(feature = "lossless_iusize_conv", since = "1.26.0")] }
|
||||
impl_from! { u8, isize, #[stable(feature = "lossless_iusize_conv", since = "1.26.0")] }
|
||||
impl_from! { i16, isize, #[stable(feature = "lossless_iusize_conv", since = "1.26.0")] }
|
||||
|
||||
// RISC-V defines the possibility of a 128-bit address space (RV128).
|
||||
|
||||
// CHERI proposes 256-bit “capabilities”. Unclear if this would be relevant to usize/isize.
|
||||
// https://www.cl.cam.ac.uk/research/security/ctsrd/pdfs/20171017a-cheri-poster.pdf
|
||||
// http://www.csl.sri.com/users/neumann/2012resolve-cheri.pdf
|
||||
|
||||
// Note: integers can only be represented with full precision in a float if
|
||||
// they fit in the significand, which is 24 bits in f32 and 53 bits in f64.
|
||||
// Lossy float conversions are not implemented at this time.
|
||||
|
||||
// Signed -> Float
|
||||
impl_from! { i8, f32, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
|
||||
impl_from! { i8, f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
|
||||
impl_from! { i16, f32, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
|
||||
impl_from! { i16, f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
|
||||
impl_from! { i32, f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
|
||||
|
||||
// Unsigned -> Float
|
||||
impl_from! { u8, f32, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
|
||||
impl_from! { u8, f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
|
||||
impl_from! { u16, f32, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
|
||||
impl_from! { u16, f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
|
||||
impl_from! { u32, f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
|
||||
|
||||
// Float -> Float
|
||||
impl_from! { f32, f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")] }
|
||||
|
||||
// no possible bounds violation
|
||||
macro_rules! try_from_unbounded {
|
||||
($source:ty, $($target:ty),*) => {$(
|
||||
#[stable(feature = "try_from", since = "1.34.0")]
|
||||
impl TryFrom<$source> for $target {
|
||||
type Error = TryFromIntError;
|
||||
|
||||
/// Try to create the target number type from a source
|
||||
/// number type. This returns an error if the source value
|
||||
/// is outside of the range of the target type.
|
||||
#[inline]
|
||||
fn try_from(value: $source) -> Result<Self, Self::Error> {
|
||||
Ok(value as Self)
|
||||
}
|
||||
}
|
||||
)*}
|
||||
}
|
||||
|
||||
// only negative bounds
|
||||
macro_rules! try_from_lower_bounded {
|
||||
($source:ty, $($target:ty),*) => {$(
|
||||
#[stable(feature = "try_from", since = "1.34.0")]
|
||||
impl TryFrom<$source> for $target {
|
||||
type Error = TryFromIntError;
|
||||
|
||||
/// Try to create the target number type from a source
|
||||
/// number type. This returns an error if the source value
|
||||
/// is outside of the range of the target type.
|
||||
#[inline]
|
||||
fn try_from(u: $source) -> Result<Self, Self::Error> {
|
||||
if u >= 0 {
|
||||
Ok(u as Self)
|
||||
} else {
|
||||
Err(TryFromIntError(()))
|
||||
}
|
||||
}
|
||||
}
|
||||
)*}
|
||||
}
|
||||
|
||||
// unsigned to signed (only positive bound)
|
||||
macro_rules! try_from_upper_bounded {
|
||||
($source:ty, $($target:ty),*) => {$(
|
||||
#[stable(feature = "try_from", since = "1.34.0")]
|
||||
impl TryFrom<$source> for $target {
|
||||
type Error = TryFromIntError;
|
||||
|
||||
/// Try to create the target number type from a source
|
||||
/// number type. This returns an error if the source value
|
||||
/// is outside of the range of the target type.
|
||||
#[inline]
|
||||
fn try_from(u: $source) -> Result<Self, Self::Error> {
|
||||
if u > (Self::MAX as $source) {
|
||||
Err(TryFromIntError(()))
|
||||
} else {
|
||||
Ok(u as Self)
|
||||
}
|
||||
}
|
||||
}
|
||||
)*}
|
||||
}
|
||||
|
||||
// all other cases
|
||||
macro_rules! try_from_both_bounded {
|
||||
($source:ty, $($target:ty),*) => {$(
|
||||
#[stable(feature = "try_from", since = "1.34.0")]
|
||||
impl TryFrom<$source> for $target {
|
||||
type Error = TryFromIntError;
|
||||
|
||||
/// Try to create the target number type from a source
|
||||
/// number type. This returns an error if the source value
|
||||
/// is outside of the range of the target type.
|
||||
#[inline]
|
||||
fn try_from(u: $source) -> Result<Self, Self::Error> {
|
||||
let min = Self::MIN as $source;
|
||||
let max = Self::MAX as $source;
|
||||
if u < min || u > max {
|
||||
Err(TryFromIntError(()))
|
||||
} else {
|
||||
Ok(u as Self)
|
||||
}
|
||||
}
|
||||
}
|
||||
)*}
|
||||
}
|
||||
|
||||
macro_rules! rev {
|
||||
($mac:ident, $source:ty, $($target:ty),*) => {$(
|
||||
$mac!($target, $source);
|
||||
)*}
|
||||
}
|
||||
|
||||
// intra-sign conversions
|
||||
try_from_upper_bounded!(u16, u8);
|
||||
try_from_upper_bounded!(u32, u16, u8);
|
||||
try_from_upper_bounded!(u64, u32, u16, u8);
|
||||
try_from_upper_bounded!(u128, u64, u32, u16, u8);
|
||||
|
||||
try_from_both_bounded!(i16, i8);
|
||||
try_from_both_bounded!(i32, i16, i8);
|
||||
try_from_both_bounded!(i64, i32, i16, i8);
|
||||
try_from_both_bounded!(i128, i64, i32, i16, i8);
|
||||
|
||||
// unsigned-to-signed
|
||||
try_from_upper_bounded!(u8, i8);
|
||||
try_from_upper_bounded!(u16, i8, i16);
|
||||
try_from_upper_bounded!(u32, i8, i16, i32);
|
||||
try_from_upper_bounded!(u64, i8, i16, i32, i64);
|
||||
try_from_upper_bounded!(u128, i8, i16, i32, i64, i128);
|
||||
|
||||
// signed-to-unsigned
|
||||
try_from_lower_bounded!(i8, u8, u16, u32, u64, u128);
|
||||
try_from_lower_bounded!(i16, u16, u32, u64, u128);
|
||||
try_from_lower_bounded!(i32, u32, u64, u128);
|
||||
try_from_lower_bounded!(i64, u64, u128);
|
||||
try_from_lower_bounded!(i128, u128);
|
||||
try_from_both_bounded!(i16, u8);
|
||||
try_from_both_bounded!(i32, u16, u8);
|
||||
try_from_both_bounded!(i64, u32, u16, u8);
|
||||
try_from_both_bounded!(i128, u64, u32, u16, u8);
|
||||
|
||||
// usize/isize
|
||||
try_from_upper_bounded!(usize, isize);
|
||||
try_from_lower_bounded!(isize, usize);
|
||||
|
||||
#[cfg(target_pointer_width = "16")]
|
||||
mod ptr_try_from_impls {
|
||||
use super::TryFromIntError;
|
||||
use crate::convert::TryFrom;
|
||||
|
||||
try_from_upper_bounded!(usize, u8);
|
||||
try_from_unbounded!(usize, u16, u32, u64, u128);
|
||||
try_from_upper_bounded!(usize, i8, i16);
|
||||
try_from_unbounded!(usize, i32, i64, i128);
|
||||
|
||||
try_from_both_bounded!(isize, u8);
|
||||
try_from_lower_bounded!(isize, u16, u32, u64, u128);
|
||||
try_from_both_bounded!(isize, i8);
|
||||
try_from_unbounded!(isize, i16, i32, i64, i128);
|
||||
|
||||
rev!(try_from_upper_bounded, usize, u32, u64, u128);
|
||||
rev!(try_from_lower_bounded, usize, i8, i16);
|
||||
rev!(try_from_both_bounded, usize, i32, i64, i128);
|
||||
|
||||
rev!(try_from_upper_bounded, isize, u16, u32, u64, u128);
|
||||
rev!(try_from_both_bounded, isize, i32, i64, i128);
|
||||
}
|
||||
|
||||
#[cfg(target_pointer_width = "32")]
|
||||
mod ptr_try_from_impls {
|
||||
use super::TryFromIntError;
|
||||
use crate::convert::TryFrom;
|
||||
|
||||
try_from_upper_bounded!(usize, u8, u16);
|
||||
try_from_unbounded!(usize, u32, u64, u128);
|
||||
try_from_upper_bounded!(usize, i8, i16, i32);
|
||||
try_from_unbounded!(usize, i64, i128);
|
||||
|
||||
try_from_both_bounded!(isize, u8, u16);
|
||||
try_from_lower_bounded!(isize, u32, u64, u128);
|
||||
try_from_both_bounded!(isize, i8, i16);
|
||||
try_from_unbounded!(isize, i32, i64, i128);
|
||||
|
||||
rev!(try_from_unbounded, usize, u32);
|
||||
rev!(try_from_upper_bounded, usize, u64, u128);
|
||||
rev!(try_from_lower_bounded, usize, i8, i16, i32);
|
||||
rev!(try_from_both_bounded, usize, i64, i128);
|
||||
|
||||
rev!(try_from_unbounded, isize, u16);
|
||||
rev!(try_from_upper_bounded, isize, u32, u64, u128);
|
||||
rev!(try_from_unbounded, isize, i32);
|
||||
rev!(try_from_both_bounded, isize, i64, i128);
|
||||
}
|
||||
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
mod ptr_try_from_impls {
|
||||
use super::TryFromIntError;
|
||||
use crate::convert::TryFrom;
|
||||
|
||||
try_from_upper_bounded!(usize, u8, u16, u32);
|
||||
try_from_unbounded!(usize, u64, u128);
|
||||
try_from_upper_bounded!(usize, i8, i16, i32, i64);
|
||||
try_from_unbounded!(usize, i128);
|
||||
|
||||
try_from_both_bounded!(isize, u8, u16, u32);
|
||||
try_from_lower_bounded!(isize, u64, u128);
|
||||
try_from_both_bounded!(isize, i8, i16, i32);
|
||||
try_from_unbounded!(isize, i64, i128);
|
||||
|
||||
rev!(try_from_unbounded, usize, u32, u64);
|
||||
rev!(try_from_upper_bounded, usize, u128);
|
||||
rev!(try_from_lower_bounded, usize, i8, i16, i32, i64);
|
||||
rev!(try_from_both_bounded, usize, i128);
|
||||
|
||||
rev!(try_from_unbounded, isize, u16, u32);
|
||||
rev!(try_from_upper_bounded, isize, u64, u128);
|
||||
rev!(try_from_unbounded, isize, i32, i64);
|
||||
rev!(try_from_both_bounded, isize, i128);
|
||||
}
|
||||
|
||||
// Conversion traits for non-zero integer types
|
||||
use crate::num::NonZeroI128;
|
||||
use crate::num::NonZeroI16;
|
||||
use crate::num::NonZeroI32;
|
||||
use crate::num::NonZeroI64;
|
||||
use crate::num::NonZeroI8;
|
||||
use crate::num::NonZeroIsize;
|
||||
use crate::num::NonZeroU128;
|
||||
use crate::num::NonZeroU16;
|
||||
use crate::num::NonZeroU32;
|
||||
use crate::num::NonZeroU64;
|
||||
use crate::num::NonZeroU8;
|
||||
use crate::num::NonZeroUsize;
|
||||
|
||||
macro_rules! nzint_impl_from {
|
||||
($Small: ty, $Large: ty, #[$attr:meta], $doc: expr) => {
|
||||
#[$attr]
|
||||
#[doc = $doc]
|
||||
impl From<$Small> for $Large {
|
||||
#[inline]
|
||||
fn from(small: $Small) -> Self {
|
||||
// SAFETY: input type guarantees the value is non-zero
|
||||
unsafe {
|
||||
Self::new_unchecked(small.get().into())
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
($Small: ty, $Large: ty, #[$attr:meta]) => {
|
||||
nzint_impl_from!($Small,
|
||||
$Large,
|
||||
#[$attr],
|
||||
concat!("Converts `",
|
||||
stringify!($Small),
|
||||
"` to `",
|
||||
stringify!($Large),
|
||||
"` losslessly."));
|
||||
}
|
||||
}
|
||||
|
||||
// Non-zero Unsigned -> Non-zero Unsigned
|
||||
nzint_impl_from! { NonZeroU8, NonZeroU16, #[stable(feature = "nz_int_conv", since = "1.41.0")] }
|
||||
nzint_impl_from! { NonZeroU8, NonZeroU32, #[stable(feature = "nz_int_conv", since = "1.41.0")] }
|
||||
nzint_impl_from! { NonZeroU8, NonZeroU64, #[stable(feature = "nz_int_conv", since = "1.41.0")] }
|
||||
nzint_impl_from! { NonZeroU8, NonZeroU128, #[stable(feature = "nz_int_conv", since = "1.41.0")] }
|
||||
nzint_impl_from! { NonZeroU8, NonZeroUsize, #[stable(feature = "nz_int_conv", since = "1.41.0")] }
|
||||
nzint_impl_from! { NonZeroU16, NonZeroU32, #[stable(feature = "nz_int_conv", since = "1.41.0")] }
|
||||
nzint_impl_from! { NonZeroU16, NonZeroU64, #[stable(feature = "nz_int_conv", since = "1.41.0")] }
|
||||
nzint_impl_from! { NonZeroU16, NonZeroU128, #[stable(feature = "nz_int_conv", since = "1.41.0")] }
|
||||
nzint_impl_from! { NonZeroU16, NonZeroUsize, #[stable(feature = "nz_int_conv", since = "1.41.0")] }
|
||||
nzint_impl_from! { NonZeroU32, NonZeroU64, #[stable(feature = "nz_int_conv", since = "1.41.0")] }
|
||||
nzint_impl_from! { NonZeroU32, NonZeroU128, #[stable(feature = "nz_int_conv", since = "1.41.0")] }
|
||||
nzint_impl_from! { NonZeroU64, NonZeroU128, #[stable(feature = "nz_int_conv", since = "1.41.0")] }
|
||||
|
||||
// Non-zero Signed -> Non-zero Signed
|
||||
nzint_impl_from! { NonZeroI8, NonZeroI16, #[stable(feature = "nz_int_conv", since = "1.41.0")] }
|
||||
nzint_impl_from! { NonZeroI8, NonZeroI32, #[stable(feature = "nz_int_conv", since = "1.41.0")] }
|
||||
nzint_impl_from! { NonZeroI8, NonZeroI64, #[stable(feature = "nz_int_conv", since = "1.41.0")] }
|
||||
nzint_impl_from! { NonZeroI8, NonZeroI128, #[stable(feature = "nz_int_conv", since = "1.41.0")] }
|
||||
nzint_impl_from! { NonZeroI8, NonZeroIsize, #[stable(feature = "nz_int_conv", since = "1.41.0")] }
|
||||
nzint_impl_from! { NonZeroI16, NonZeroI32, #[stable(feature = "nz_int_conv", since = "1.41.0")] }
|
||||
nzint_impl_from! { NonZeroI16, NonZeroI64, #[stable(feature = "nz_int_conv", since = "1.41.0")] }
|
||||
nzint_impl_from! { NonZeroI16, NonZeroI128, #[stable(feature = "nz_int_conv", since = "1.41.0")] }
|
||||
nzint_impl_from! { NonZeroI16, NonZeroIsize, #[stable(feature = "nz_int_conv", since = "1.41.0")] }
|
||||
nzint_impl_from! { NonZeroI32, NonZeroI64, #[stable(feature = "nz_int_conv", since = "1.41.0")] }
|
||||
nzint_impl_from! { NonZeroI32, NonZeroI128, #[stable(feature = "nz_int_conv", since = "1.41.0")] }
|
||||
nzint_impl_from! { NonZeroI64, NonZeroI128, #[stable(feature = "nz_int_conv", since = "1.41.0")] }
|
||||
|
||||
// NonZero UnSigned -> Non-zero Signed
|
||||
nzint_impl_from! { NonZeroU8, NonZeroI16, #[stable(feature = "nz_int_conv", since = "1.41.0")] }
|
||||
nzint_impl_from! { NonZeroU8, NonZeroI32, #[stable(feature = "nz_int_conv", since = "1.41.0")] }
|
||||
nzint_impl_from! { NonZeroU8, NonZeroI64, #[stable(feature = "nz_int_conv", since = "1.41.0")] }
|
||||
nzint_impl_from! { NonZeroU8, NonZeroI128, #[stable(feature = "nz_int_conv", since = "1.41.0")] }
|
||||
nzint_impl_from! { NonZeroU8, NonZeroIsize, #[stable(feature = "nz_int_conv", since = "1.41.0")] }
|
||||
nzint_impl_from! { NonZeroU16, NonZeroI32, #[stable(feature = "nz_int_conv", since = "1.41.0")] }
|
||||
nzint_impl_from! { NonZeroU16, NonZeroI64, #[stable(feature = "nz_int_conv", since = "1.41.0")] }
|
||||
nzint_impl_from! { NonZeroU16, NonZeroI128, #[stable(feature = "nz_int_conv", since = "1.41.0")] }
|
||||
nzint_impl_from! { NonZeroU32, NonZeroI64, #[stable(feature = "nz_int_conv", since = "1.41.0")] }
|
||||
nzint_impl_from! { NonZeroU32, NonZeroI128, #[stable(feature = "nz_int_conv", since = "1.41.0")] }
|
||||
nzint_impl_from! { NonZeroU64, NonZeroI128, #[stable(feature = "nz_int_conv", since = "1.41.0")] }
|
||||
|
||||
macro_rules! nzint_impl_try_from_int {
|
||||
($Int: ty, $NonZeroInt: ty, #[$attr:meta], $doc: expr) => {
|
||||
#[$attr]
|
||||
#[doc = $doc]
|
||||
impl TryFrom<$Int> for $NonZeroInt {
|
||||
type Error = TryFromIntError;
|
||||
|
||||
#[inline]
|
||||
fn try_from(value: $Int) -> Result<Self, Self::Error> {
|
||||
Self::new(value).ok_or(TryFromIntError(()))
|
||||
}
|
||||
}
|
||||
};
|
||||
($Int: ty, $NonZeroInt: ty, #[$attr:meta]) => {
|
||||
nzint_impl_try_from_int!($Int,
|
||||
$NonZeroInt,
|
||||
#[$attr],
|
||||
concat!("Attempts to convert `",
|
||||
stringify!($Int),
|
||||
"` to `",
|
||||
stringify!($NonZeroInt),
|
||||
"`."));
|
||||
}
|
||||
}
|
||||
|
||||
// Int -> Non-zero Int
|
||||
nzint_impl_try_from_int! { u8, NonZeroU8, #[stable(feature = "nzint_try_from_int_conv", since = "1.46.0")] }
|
||||
nzint_impl_try_from_int! { u16, NonZeroU16, #[stable(feature = "nzint_try_from_int_conv", since = "1.46.0")] }
|
||||
nzint_impl_try_from_int! { u32, NonZeroU32, #[stable(feature = "nzint_try_from_int_conv", since = "1.46.0")] }
|
||||
nzint_impl_try_from_int! { u64, NonZeroU64, #[stable(feature = "nzint_try_from_int_conv", since = "1.46.0")] }
|
||||
nzint_impl_try_from_int! { u128, NonZeroU128, #[stable(feature = "nzint_try_from_int_conv", since = "1.46.0")] }
|
||||
nzint_impl_try_from_int! { usize, NonZeroUsize, #[stable(feature = "nzint_try_from_int_conv", since = "1.46.0")] }
|
||||
nzint_impl_try_from_int! { i8, NonZeroI8, #[stable(feature = "nzint_try_from_int_conv", since = "1.46.0")] }
|
||||
nzint_impl_try_from_int! { i16, NonZeroI16, #[stable(feature = "nzint_try_from_int_conv", since = "1.46.0")] }
|
||||
nzint_impl_try_from_int! { i32, NonZeroI32, #[stable(feature = "nzint_try_from_int_conv", since = "1.46.0")] }
|
||||
nzint_impl_try_from_int! { i64, NonZeroI64, #[stable(feature = "nzint_try_from_int_conv", since = "1.46.0")] }
|
||||
nzint_impl_try_from_int! { i128, NonZeroI128, #[stable(feature = "nzint_try_from_int_conv", since = "1.46.0")] }
|
||||
nzint_impl_try_from_int! { isize, NonZeroIsize, #[stable(feature = "nzint_try_from_int_conv", since = "1.46.0")] }
|
||||
|
||||
macro_rules! nzint_impl_try_from_nzint {
|
||||
($From:ty => $To:ty, $doc: expr) => {
|
||||
#[stable(feature = "nzint_try_from_nzint_conv", since = "1.49.0")]
|
||||
#[doc = $doc]
|
||||
impl TryFrom<$From> for $To {
|
||||
type Error = TryFromIntError;
|
||||
|
||||
#[inline]
|
||||
fn try_from(value: $From) -> Result<Self, Self::Error> {
|
||||
TryFrom::try_from(value.get()).map(|v| {
|
||||
// SAFETY: $From is a NonZero type, so v is not zero.
|
||||
unsafe { Self::new_unchecked(v) }
|
||||
})
|
||||
}
|
||||
}
|
||||
};
|
||||
($To:ty: $($From: ty),*) => {$(
|
||||
nzint_impl_try_from_nzint!(
|
||||
$From => $To,
|
||||
concat!(
|
||||
"Attempts to convert `",
|
||||
stringify!($From),
|
||||
"` to `",
|
||||
stringify!($To),
|
||||
"`.",
|
||||
)
|
||||
);
|
||||
)*};
|
||||
}
|
||||
|
||||
// Non-zero int -> non-zero unsigned int
|
||||
nzint_impl_try_from_nzint! { NonZeroU8: NonZeroI8, NonZeroU16, NonZeroI16, NonZeroU32, NonZeroI32, NonZeroU64, NonZeroI64, NonZeroU128, NonZeroI128, NonZeroUsize, NonZeroIsize }
|
||||
nzint_impl_try_from_nzint! { NonZeroU16: NonZeroI8, NonZeroI16, NonZeroU32, NonZeroI32, NonZeroU64, NonZeroI64, NonZeroU128, NonZeroI128, NonZeroUsize, NonZeroIsize }
|
||||
nzint_impl_try_from_nzint! { NonZeroU32: NonZeroI8, NonZeroI16, NonZeroI32, NonZeroU64, NonZeroI64, NonZeroU128, NonZeroI128, NonZeroUsize, NonZeroIsize }
|
||||
nzint_impl_try_from_nzint! { NonZeroU64: NonZeroI8, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroU128, NonZeroI128, NonZeroUsize, NonZeroIsize }
|
||||
nzint_impl_try_from_nzint! { NonZeroU128: NonZeroI8, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI128, NonZeroUsize, NonZeroIsize }
|
||||
nzint_impl_try_from_nzint! { NonZeroUsize: NonZeroI8, NonZeroI16, NonZeroU32, NonZeroI32, NonZeroU64, NonZeroI64, NonZeroU128, NonZeroI128, NonZeroIsize }
|
||||
|
||||
// Non-zero int -> non-zero signed int
|
||||
nzint_impl_try_from_nzint! { NonZeroI8: NonZeroU8, NonZeroU16, NonZeroI16, NonZeroU32, NonZeroI32, NonZeroU64, NonZeroI64, NonZeroU128, NonZeroI128, NonZeroUsize, NonZeroIsize }
|
||||
nzint_impl_try_from_nzint! { NonZeroI16: NonZeroU16, NonZeroU32, NonZeroI32, NonZeroU64, NonZeroI64, NonZeroU128, NonZeroI128, NonZeroUsize, NonZeroIsize }
|
||||
nzint_impl_try_from_nzint! { NonZeroI32: NonZeroU32, NonZeroU64, NonZeroI64, NonZeroU128, NonZeroI128, NonZeroUsize, NonZeroIsize }
|
||||
nzint_impl_try_from_nzint! { NonZeroI64: NonZeroU64, NonZeroU128, NonZeroI128, NonZeroUsize, NonZeroIsize }
|
||||
nzint_impl_try_from_nzint! { NonZeroI128: NonZeroU128, NonZeroUsize, NonZeroIsize }
|
||||
nzint_impl_try_from_nzint! { NonZeroIsize: NonZeroU16, NonZeroU32, NonZeroI32, NonZeroU64, NonZeroI64, NonZeroU128, NonZeroI128, NonZeroUsize }
|
||||
200
libgrust/rustc-lib/core/src/default.rs
Normal file
200
libgrust/rustc-lib/core/src/default.rs
Normal file
@@ -0,0 +1,200 @@
|
||||
//! The `Default` trait for types which may have meaningful default values.
|
||||
|
||||
#![stable(feature = "rust1", since = "1.0.0")]
|
||||
|
||||
/// A trait for giving a type a useful default value.
|
||||
///
|
||||
/// Sometimes, you want to fall back to some kind of default value, and
|
||||
/// don't particularly care what it is. This comes up often with `struct`s
|
||||
/// that define a set of options:
|
||||
///
|
||||
/// ```
|
||||
/// # #[allow(dead_code)]
|
||||
/// struct SomeOptions {
|
||||
/// foo: i32,
|
||||
/// bar: f32,
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// How can we define some default values? You can use `Default`:
|
||||
///
|
||||
/// ```
|
||||
/// # #[allow(dead_code)]
|
||||
/// #[derive(Default)]
|
||||
/// struct SomeOptions {
|
||||
/// foo: i32,
|
||||
/// bar: f32,
|
||||
/// }
|
||||
///
|
||||
/// fn main() {
|
||||
/// let options: SomeOptions = Default::default();
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// Now, you get all of the default values. Rust implements `Default` for various primitives types.
|
||||
///
|
||||
/// If you want to override a particular option, but still retain the other defaults:
|
||||
///
|
||||
/// ```
|
||||
/// # #[allow(dead_code)]
|
||||
/// # #[derive(Default)]
|
||||
/// # struct SomeOptions {
|
||||
/// # foo: i32,
|
||||
/// # bar: f32,
|
||||
/// # }
|
||||
/// fn main() {
|
||||
/// let options = SomeOptions { foo: 42, ..Default::default() };
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// ## Derivable
|
||||
///
|
||||
/// This trait can be used with `#[derive]` if all of the type's fields implement
|
||||
/// `Default`. When `derive`d, it will use the default value for each field's type.
|
||||
///
|
||||
/// ## How can I implement `Default`?
|
||||
///
|
||||
/// Provide an implementation for the `default()` method that returns the value of
|
||||
/// your type that should be the default:
|
||||
///
|
||||
/// ```
|
||||
/// # #![allow(dead_code)]
|
||||
/// enum Kind {
|
||||
/// A,
|
||||
/// B,
|
||||
/// C,
|
||||
/// }
|
||||
///
|
||||
/// impl Default for Kind {
|
||||
/// fn default() -> Self { Kind::A }
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// # #[allow(dead_code)]
|
||||
/// #[derive(Default)]
|
||||
/// struct SomeOptions {
|
||||
/// foo: i32,
|
||||
/// bar: f32,
|
||||
/// }
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub trait Default: Sized {
|
||||
/// Returns the "default value" for a type.
|
||||
///
|
||||
/// Default values are often some kind of initial value, identity value, or anything else that
|
||||
/// may make sense as a default.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Using built-in default values:
|
||||
///
|
||||
/// ```
|
||||
/// let i: i8 = Default::default();
|
||||
/// let (x, y): (Option<String>, f64) = Default::default();
|
||||
/// let (a, b, (c, d)): (i32, u32, (bool, bool)) = Default::default();
|
||||
/// ```
|
||||
///
|
||||
/// Making your own:
|
||||
///
|
||||
/// ```
|
||||
/// # #[allow(dead_code)]
|
||||
/// enum Kind {
|
||||
/// A,
|
||||
/// B,
|
||||
/// C,
|
||||
/// }
|
||||
///
|
||||
/// impl Default for Kind {
|
||||
/// fn default() -> Self { Kind::A }
|
||||
/// }
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
fn default() -> Self;
|
||||
}
|
||||
|
||||
/// Return the default value of a type according to the `Default` trait.
|
||||
///
|
||||
/// The type to return is inferred from context; this is equivalent to
|
||||
/// `Default::default()` but shorter to type.
|
||||
///
|
||||
/// For example:
|
||||
/// ```
|
||||
/// #![feature(default_free_fn)]
|
||||
///
|
||||
/// use std::default::default;
|
||||
///
|
||||
/// #[derive(Default)]
|
||||
/// struct AppConfig {
|
||||
/// foo: FooConfig,
|
||||
/// bar: BarConfig,
|
||||
/// }
|
||||
///
|
||||
/// #[derive(Default)]
|
||||
/// struct FooConfig {
|
||||
/// foo: i32,
|
||||
/// }
|
||||
///
|
||||
/// #[derive(Default)]
|
||||
/// struct BarConfig {
|
||||
/// bar: f32,
|
||||
/// baz: u8,
|
||||
/// }
|
||||
///
|
||||
/// fn main() {
|
||||
/// let options = AppConfig {
|
||||
/// foo: default(),
|
||||
/// bar: BarConfig {
|
||||
/// bar: 10.1,
|
||||
/// ..default()
|
||||
/// },
|
||||
/// };
|
||||
/// }
|
||||
/// ```
|
||||
#[unstable(feature = "default_free_fn", issue = "73014")]
|
||||
#[inline]
|
||||
pub fn default<T: Default>() -> T {
|
||||
Default::default()
|
||||
}
|
||||
|
||||
/// Derive macro generating an impl of the trait `Default`.
|
||||
#[rustc_builtin_macro]
|
||||
#[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
|
||||
#[allow_internal_unstable(core_intrinsics)]
|
||||
pub macro Default($item:item) {
|
||||
/* compiler built-in */
|
||||
}
|
||||
|
||||
macro_rules! default_impl {
|
||||
($t:ty, $v:expr, $doc:tt) => {
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl Default for $t {
|
||||
#[inline]
|
||||
#[doc = $doc]
|
||||
fn default() -> $t { $v }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
default_impl! { (), (), "Returns the default value of `()`" }
|
||||
default_impl! { bool, false, "Returns the default value of `false`" }
|
||||
default_impl! { char, '\x00', "Returns the default value of `\\x00`" }
|
||||
|
||||
default_impl! { usize, 0, "Returns the default value of `0`" }
|
||||
default_impl! { u8, 0, "Returns the default value of `0`" }
|
||||
default_impl! { u16, 0, "Returns the default value of `0`" }
|
||||
default_impl! { u32, 0, "Returns the default value of `0`" }
|
||||
default_impl! { u64, 0, "Returns the default value of `0`" }
|
||||
default_impl! { u128, 0, "Returns the default value of `0`" }
|
||||
|
||||
default_impl! { isize, 0, "Returns the default value of `0`" }
|
||||
default_impl! { i8, 0, "Returns the default value of `0`" }
|
||||
default_impl! { i16, 0, "Returns the default value of `0`" }
|
||||
default_impl! { i32, 0, "Returns the default value of `0`" }
|
||||
default_impl! { i64, 0, "Returns the default value of `0`" }
|
||||
default_impl! { i128, 0, "Returns the default value of `0`" }
|
||||
|
||||
default_impl! { f32, 0.0f32, "Returns the default value of `0.0`" }
|
||||
default_impl! { f64, 0.0f64, "Returns the default value of `0.0`" }
|
||||
407
libgrust/rustc-lib/core/src/ffi.rs
Normal file
407
libgrust/rustc-lib/core/src/ffi.rs
Normal file
@@ -0,0 +1,407 @@
|
||||
#![stable(feature = "", since = "1.30.0")]
|
||||
#![allow(non_camel_case_types)]
|
||||
|
||||
//! Utilities related to foreign function interface (FFI) bindings.
|
||||
|
||||
use crate::fmt;
|
||||
use crate::marker::PhantomData;
|
||||
use crate::ops::{Deref, DerefMut};
|
||||
|
||||
/// Equivalent to C's `void` type when used as a [pointer].
|
||||
///
|
||||
/// In essence, `*const c_void` is equivalent to C's `const void*`
|
||||
/// and `*mut c_void` is equivalent to C's `void*`. That said, this is
|
||||
/// *not* the same as C's `void` return type, which is Rust's `()` type.
|
||||
///
|
||||
/// To model pointers to opaque types in FFI, until `extern type` is
|
||||
/// stabilized, it is recommended to use a newtype wrapper around an empty
|
||||
/// byte array. See the [Nomicon] for details.
|
||||
///
|
||||
/// One could use `std::os::raw::c_void` if they want to support old Rust
|
||||
/// compiler down to 1.1.0. After Rust 1.30.0, it was re-exported by
|
||||
/// this definition. For more information, please read [RFC 2521].
|
||||
///
|
||||
/// [pointer]: ../../std/primitive.pointer.html
|
||||
/// [Nomicon]: https://doc.rust-lang.org/nomicon/ffi.html#representing-opaque-structs
|
||||
/// [RFC 2521]: https://github.com/rust-lang/rfcs/blob/master/text/2521-c_void-reunification.md
|
||||
// N.B., for LLVM to recognize the void pointer type and by extension
|
||||
// functions like malloc(), we need to have it represented as i8* in
|
||||
// LLVM bitcode. The enum used here ensures this and prevents misuse
|
||||
// of the "raw" type by only having private variants. We need two
|
||||
// variants, because the compiler complains about the repr attribute
|
||||
// otherwise and we need at least one variant as otherwise the enum
|
||||
// would be uninhabited and at least dereferencing such pointers would
|
||||
// be UB.
|
||||
#[repr(u8)]
|
||||
#[stable(feature = "core_c_void", since = "1.30.0")]
|
||||
pub enum c_void {
|
||||
#[unstable(
|
||||
feature = "c_void_variant",
|
||||
reason = "temporary implementation detail",
|
||||
issue = "none"
|
||||
)]
|
||||
#[doc(hidden)]
|
||||
__variant1,
|
||||
#[unstable(
|
||||
feature = "c_void_variant",
|
||||
reason = "temporary implementation detail",
|
||||
issue = "none"
|
||||
)]
|
||||
#[doc(hidden)]
|
||||
__variant2,
|
||||
}
|
||||
|
||||
#[stable(feature = "std_debug", since = "1.16.0")]
|
||||
impl fmt::Debug for c_void {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.pad("c_void")
|
||||
}
|
||||
}
|
||||
|
||||
/// Basic implementation of a `va_list`.
|
||||
// The name is WIP, using `VaListImpl` for now.
|
||||
#[cfg(any(
|
||||
all(not(target_arch = "aarch64"), not(target_arch = "powerpc"), not(target_arch = "x86_64")),
|
||||
all(target_arch = "aarch64", any(target_os = "macos", target_os = "ios")),
|
||||
target_arch = "wasm32",
|
||||
target_arch = "asmjs",
|
||||
windows
|
||||
))]
|
||||
#[repr(transparent)]
|
||||
#[unstable(
|
||||
feature = "c_variadic",
|
||||
reason = "the `c_variadic` feature has not been properly tested on \
|
||||
all supported platforms",
|
||||
issue = "44930"
|
||||
)]
|
||||
#[lang = "va_list"]
|
||||
pub struct VaListImpl<'f> {
|
||||
ptr: *mut c_void,
|
||||
|
||||
// Invariant over `'f`, so each `VaListImpl<'f>` object is tied to
|
||||
// the region of the function it's defined in
|
||||
_marker: PhantomData<&'f mut &'f c_void>,
|
||||
}
|
||||
|
||||
#[cfg(any(
|
||||
all(not(target_arch = "aarch64"), not(target_arch = "powerpc"), not(target_arch = "x86_64")),
|
||||
all(target_arch = "aarch64", any(target_os = "macos", target_os = "ios")),
|
||||
target_arch = "wasm32",
|
||||
target_arch = "asmjs",
|
||||
windows
|
||||
))]
|
||||
#[unstable(
|
||||
feature = "c_variadic",
|
||||
reason = "the `c_variadic` feature has not been properly tested on \
|
||||
all supported platforms",
|
||||
issue = "44930"
|
||||
)]
|
||||
impl<'f> fmt::Debug for VaListImpl<'f> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "va_list* {:p}", self.ptr)
|
||||
}
|
||||
}
|
||||
|
||||
/// AArch64 ABI implementation of a `va_list`. See the
|
||||
/// [AArch64 Procedure Call Standard] for more details.
|
||||
///
|
||||
/// [AArch64 Procedure Call Standard]:
|
||||
/// http://infocenter.arm.com/help/topic/com.arm.doc.ihi0055b/IHI0055B_aapcs64.pdf
|
||||
#[cfg(all(
|
||||
target_arch = "aarch64",
|
||||
not(any(target_os = "macos", target_os = "ios")),
|
||||
not(windows)
|
||||
))]
|
||||
#[repr(C)]
|
||||
#[derive(Debug)]
|
||||
#[unstable(
|
||||
feature = "c_variadic",
|
||||
reason = "the `c_variadic` feature has not been properly tested on \
|
||||
all supported platforms",
|
||||
issue = "44930"
|
||||
)]
|
||||
#[lang = "va_list"]
|
||||
pub struct VaListImpl<'f> {
|
||||
stack: *mut c_void,
|
||||
gr_top: *mut c_void,
|
||||
vr_top: *mut c_void,
|
||||
gr_offs: i32,
|
||||
vr_offs: i32,
|
||||
_marker: PhantomData<&'f mut &'f c_void>,
|
||||
}
|
||||
|
||||
/// PowerPC ABI implementation of a `va_list`.
|
||||
#[cfg(all(target_arch = "powerpc", not(windows)))]
|
||||
#[repr(C)]
|
||||
#[derive(Debug)]
|
||||
#[unstable(
|
||||
feature = "c_variadic",
|
||||
reason = "the `c_variadic` feature has not been properly tested on \
|
||||
all supported platforms",
|
||||
issue = "44930"
|
||||
)]
|
||||
#[lang = "va_list"]
|
||||
pub struct VaListImpl<'f> {
|
||||
gpr: u8,
|
||||
fpr: u8,
|
||||
reserved: u16,
|
||||
overflow_arg_area: *mut c_void,
|
||||
reg_save_area: *mut c_void,
|
||||
_marker: PhantomData<&'f mut &'f c_void>,
|
||||
}
|
||||
|
||||
/// x86_64 ABI implementation of a `va_list`.
|
||||
#[cfg(all(target_arch = "x86_64", not(windows)))]
|
||||
#[repr(C)]
|
||||
#[derive(Debug)]
|
||||
#[unstable(
|
||||
feature = "c_variadic",
|
||||
reason = "the `c_variadic` feature has not been properly tested on \
|
||||
all supported platforms",
|
||||
issue = "44930"
|
||||
)]
|
||||
#[lang = "va_list"]
|
||||
pub struct VaListImpl<'f> {
|
||||
gp_offset: i32,
|
||||
fp_offset: i32,
|
||||
overflow_arg_area: *mut c_void,
|
||||
reg_save_area: *mut c_void,
|
||||
_marker: PhantomData<&'f mut &'f c_void>,
|
||||
}
|
||||
|
||||
/// A wrapper for a `va_list`
|
||||
#[repr(transparent)]
|
||||
#[derive(Debug)]
|
||||
#[unstable(
|
||||
feature = "c_variadic",
|
||||
reason = "the `c_variadic` feature has not been properly tested on \
|
||||
all supported platforms",
|
||||
issue = "44930"
|
||||
)]
|
||||
pub struct VaList<'a, 'f: 'a> {
|
||||
#[cfg(any(
|
||||
all(
|
||||
not(target_arch = "aarch64"),
|
||||
not(target_arch = "powerpc"),
|
||||
not(target_arch = "x86_64")
|
||||
),
|
||||
all(target_arch = "aarch64", any(target_os = "macos", target_os = "ios")),
|
||||
target_arch = "wasm32",
|
||||
target_arch = "asmjs",
|
||||
windows
|
||||
))]
|
||||
inner: VaListImpl<'f>,
|
||||
|
||||
#[cfg(all(
|
||||
any(target_arch = "aarch64", target_arch = "powerpc", target_arch = "x86_64"),
|
||||
any(not(target_arch = "aarch64"), not(any(target_os = "macos", target_os = "ios"))),
|
||||
not(target_arch = "wasm32"),
|
||||
not(target_arch = "asmjs"),
|
||||
not(windows)
|
||||
))]
|
||||
inner: &'a mut VaListImpl<'f>,
|
||||
|
||||
_marker: PhantomData<&'a mut VaListImpl<'f>>,
|
||||
}
|
||||
|
||||
#[cfg(any(
|
||||
all(not(target_arch = "aarch64"), not(target_arch = "powerpc"), not(target_arch = "x86_64")),
|
||||
all(target_arch = "aarch64", any(target_os = "macos", target_os = "ios")),
|
||||
target_arch = "wasm32",
|
||||
target_arch = "asmjs",
|
||||
windows
|
||||
))]
|
||||
#[unstable(
|
||||
feature = "c_variadic",
|
||||
reason = "the `c_variadic` feature has not been properly tested on \
|
||||
all supported platforms",
|
||||
issue = "44930"
|
||||
)]
|
||||
impl<'f> VaListImpl<'f> {
|
||||
/// Convert a `VaListImpl` into a `VaList` that is binary-compatible with C's `va_list`.
|
||||
#[inline]
|
||||
pub fn as_va_list<'a>(&'a mut self) -> VaList<'a, 'f> {
|
||||
VaList { inner: VaListImpl { ..*self }, _marker: PhantomData }
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(all(
|
||||
any(target_arch = "aarch64", target_arch = "powerpc", target_arch = "x86_64"),
|
||||
any(not(target_arch = "aarch64"), not(any(target_os = "macos", target_os = "ios"))),
|
||||
not(target_arch = "wasm32"),
|
||||
not(target_arch = "asmjs"),
|
||||
not(windows)
|
||||
))]
|
||||
#[unstable(
|
||||
feature = "c_variadic",
|
||||
reason = "the `c_variadic` feature has not been properly tested on \
|
||||
all supported platforms",
|
||||
issue = "44930"
|
||||
)]
|
||||
impl<'f> VaListImpl<'f> {
|
||||
/// Convert a `VaListImpl` into a `VaList` that is binary-compatible with C's `va_list`.
|
||||
#[inline]
|
||||
pub fn as_va_list<'a>(&'a mut self) -> VaList<'a, 'f> {
|
||||
VaList { inner: self, _marker: PhantomData }
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(
|
||||
feature = "c_variadic",
|
||||
reason = "the `c_variadic` feature has not been properly tested on \
|
||||
all supported platforms",
|
||||
issue = "44930"
|
||||
)]
|
||||
impl<'a, 'f: 'a> Deref for VaList<'a, 'f> {
|
||||
type Target = VaListImpl<'f>;
|
||||
|
||||
#[inline]
|
||||
fn deref(&self) -> &VaListImpl<'f> {
|
||||
&self.inner
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(
|
||||
feature = "c_variadic",
|
||||
reason = "the `c_variadic` feature has not been properly tested on \
|
||||
all supported platforms",
|
||||
issue = "44930"
|
||||
)]
|
||||
impl<'a, 'f: 'a> DerefMut for VaList<'a, 'f> {
|
||||
#[inline]
|
||||
fn deref_mut(&mut self) -> &mut VaListImpl<'f> {
|
||||
&mut self.inner
|
||||
}
|
||||
}
|
||||
|
||||
// The VaArgSafe trait needs to be used in public interfaces, however, the trait
|
||||
// itself must not be allowed to be used outside this module. Allowing users to
|
||||
// implement the trait for a new type (thereby allowing the va_arg intrinsic to
|
||||
// be used on a new type) is likely to cause undefined behavior.
|
||||
//
|
||||
// FIXME(dlrobertson): In order to use the VaArgSafe trait in a public interface
|
||||
// but also ensure it cannot be used elsewhere, the trait needs to be public
|
||||
// within a private module. Once RFC 2145 has been implemented look into
|
||||
// improving this.
|
||||
mod sealed_trait {
|
||||
/// Trait which permits the allowed types to be used with [super::VaListImpl::arg].
|
||||
#[unstable(
|
||||
feature = "c_variadic",
|
||||
reason = "the `c_variadic` feature has not been properly tested on \
|
||||
all supported platforms",
|
||||
issue = "44930"
|
||||
)]
|
||||
pub trait VaArgSafe {}
|
||||
}
|
||||
|
||||
macro_rules! impl_va_arg_safe {
|
||||
($($t:ty),+) => {
|
||||
$(
|
||||
#[unstable(feature = "c_variadic",
|
||||
reason = "the `c_variadic` feature has not been properly tested on \
|
||||
all supported platforms",
|
||||
issue = "44930")]
|
||||
impl sealed_trait::VaArgSafe for $t {}
|
||||
)+
|
||||
}
|
||||
}
|
||||
|
||||
impl_va_arg_safe! {i8, i16, i32, i64, usize}
|
||||
impl_va_arg_safe! {u8, u16, u32, u64, isize}
|
||||
impl_va_arg_safe! {f64}
|
||||
|
||||
#[unstable(
|
||||
feature = "c_variadic",
|
||||
reason = "the `c_variadic` feature has not been properly tested on \
|
||||
all supported platforms",
|
||||
issue = "44930"
|
||||
)]
|
||||
impl<T> sealed_trait::VaArgSafe for *mut T {}
|
||||
#[unstable(
|
||||
feature = "c_variadic",
|
||||
reason = "the `c_variadic` feature has not been properly tested on \
|
||||
all supported platforms",
|
||||
issue = "44930"
|
||||
)]
|
||||
impl<T> sealed_trait::VaArgSafe for *const T {}
|
||||
|
||||
#[unstable(
|
||||
feature = "c_variadic",
|
||||
reason = "the `c_variadic` feature has not been properly tested on \
|
||||
all supported platforms",
|
||||
issue = "44930"
|
||||
)]
|
||||
impl<'f> VaListImpl<'f> {
|
||||
/// Advance to the next arg.
|
||||
#[inline]
|
||||
pub unsafe fn arg<T: sealed_trait::VaArgSafe>(&mut self) -> T {
|
||||
// SAFETY: the caller must uphold the safety contract for `va_arg`.
|
||||
unsafe { va_arg(self) }
|
||||
}
|
||||
|
||||
/// Copies the `va_list` at the current location.
|
||||
pub unsafe fn with_copy<F, R>(&self, f: F) -> R
|
||||
where
|
||||
F: for<'copy> FnOnce(VaList<'copy, 'f>) -> R,
|
||||
{
|
||||
let mut ap = self.clone();
|
||||
let ret = f(ap.as_va_list());
|
||||
// SAFETY: the caller must uphold the safety contract for `va_end`.
|
||||
unsafe {
|
||||
va_end(&mut ap);
|
||||
}
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(
|
||||
feature = "c_variadic",
|
||||
reason = "the `c_variadic` feature has not been properly tested on \
|
||||
all supported platforms",
|
||||
issue = "44930"
|
||||
)]
|
||||
impl<'f> Clone for VaListImpl<'f> {
|
||||
#[inline]
|
||||
fn clone(&self) -> Self {
|
||||
let mut dest = crate::mem::MaybeUninit::uninit();
|
||||
// SAFETY: we write to the `MaybeUninit`, thus it is initialized and `assume_init` is legal
|
||||
unsafe {
|
||||
va_copy(dest.as_mut_ptr(), self);
|
||||
dest.assume_init()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(
|
||||
feature = "c_variadic",
|
||||
reason = "the `c_variadic` feature has not been properly tested on \
|
||||
all supported platforms",
|
||||
issue = "44930"
|
||||
)]
|
||||
impl<'f> Drop for VaListImpl<'f> {
|
||||
fn drop(&mut self) {
|
||||
// FIXME: this should call `va_end`, but there's no clean way to
|
||||
// guarantee that `drop` always gets inlined into its caller,
|
||||
// so the `va_end` would get directly called from the same function as
|
||||
// the corresponding `va_copy`. `man va_end` states that C requires this,
|
||||
// and LLVM basically follows the C semantics, so we need to make sure
|
||||
// that `va_end` is always called from the same function as `va_copy`.
|
||||
// For more details, see https://github.com/rust-lang/rust/pull/59625
|
||||
// and https://llvm.org/docs/LangRef.html#llvm-va-end-intrinsic.
|
||||
//
|
||||
// This works for now, since `va_end` is a no-op on all current LLVM targets.
|
||||
}
|
||||
}
|
||||
|
||||
extern "rust-intrinsic" {
|
||||
/// Destroy the arglist `ap` after initialization with `va_start` or
|
||||
/// `va_copy`.
|
||||
fn va_end(ap: &mut VaListImpl<'_>);
|
||||
|
||||
/// Copies the current location of arglist `src` to the arglist `dst`.
|
||||
fn va_copy<'f>(dest: *mut VaListImpl<'f>, src: &VaListImpl<'f>);
|
||||
|
||||
/// Loads an argument of type `T` from the `va_list` `ap` and increment the
|
||||
/// argument `ap` points to.
|
||||
fn va_arg<T: sealed_trait::VaArgSafe>(ap: &mut VaListImpl<'_>) -> T;
|
||||
}
|
||||
952
libgrust/rustc-lib/core/src/fmt/builders.rs
Normal file
952
libgrust/rustc-lib/core/src/fmt/builders.rs
Normal file
@@ -0,0 +1,952 @@
|
||||
#![allow(unused_imports)]
|
||||
|
||||
use crate::fmt::{self, Debug, Formatter};
|
||||
|
||||
struct PadAdapter<'buf, 'state> {
|
||||
buf: &'buf mut (dyn fmt::Write + 'buf),
|
||||
state: &'state mut PadAdapterState,
|
||||
}
|
||||
|
||||
struct PadAdapterState {
|
||||
on_newline: bool,
|
||||
}
|
||||
|
||||
impl Default for PadAdapterState {
|
||||
fn default() -> Self {
|
||||
PadAdapterState { on_newline: true }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'buf, 'state> PadAdapter<'buf, 'state> {
|
||||
fn wrap<'slot, 'fmt: 'buf + 'slot>(
|
||||
fmt: &'fmt mut fmt::Formatter<'_>,
|
||||
slot: &'slot mut Option<Self>,
|
||||
state: &'state mut PadAdapterState,
|
||||
) -> fmt::Formatter<'slot> {
|
||||
fmt.wrap_buf(move |buf| {
|
||||
*slot = Some(PadAdapter { buf, state });
|
||||
slot.as_mut().unwrap()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Write for PadAdapter<'_, '_> {
|
||||
fn write_str(&mut self, mut s: &str) -> fmt::Result {
|
||||
while !s.is_empty() {
|
||||
if self.state.on_newline {
|
||||
self.buf.write_str(" ")?;
|
||||
}
|
||||
|
||||
let split = match s.find('\n') {
|
||||
Some(pos) => {
|
||||
self.state.on_newline = true;
|
||||
pos + 1
|
||||
}
|
||||
None => {
|
||||
self.state.on_newline = false;
|
||||
s.len()
|
||||
}
|
||||
};
|
||||
self.buf.write_str(&s[..split])?;
|
||||
s = &s[split..];
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// A struct to help with [`fmt::Debug`](Debug) implementations.
|
||||
///
|
||||
/// This is useful when you wish to output a formatted struct as a part of your
|
||||
/// [`Debug::fmt`] implementation.
|
||||
///
|
||||
/// This can be constructed by the [`Formatter::debug_struct`] method.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::fmt;
|
||||
///
|
||||
/// struct Foo {
|
||||
/// bar: i32,
|
||||
/// baz: String,
|
||||
/// }
|
||||
///
|
||||
/// impl fmt::Debug for Foo {
|
||||
/// fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||
/// fmt.debug_struct("Foo")
|
||||
/// .field("bar", &self.bar)
|
||||
/// .field("baz", &self.baz)
|
||||
/// .finish()
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// assert_eq!(
|
||||
/// format!("{:?}", Foo { bar: 10, baz: "Hello World".to_string() }),
|
||||
/// "Foo { bar: 10, baz: \"Hello World\" }",
|
||||
/// );
|
||||
/// ```
|
||||
#[must_use = "must eventually call `finish()` on Debug builders"]
|
||||
#[allow(missing_debug_implementations)]
|
||||
#[stable(feature = "debug_builders", since = "1.2.0")]
|
||||
pub struct DebugStruct<'a, 'b: 'a> {
|
||||
fmt: &'a mut fmt::Formatter<'b>,
|
||||
result: fmt::Result,
|
||||
has_fields: bool,
|
||||
}
|
||||
|
||||
pub(super) fn debug_struct_new<'a, 'b>(
|
||||
fmt: &'a mut fmt::Formatter<'b>,
|
||||
name: &str,
|
||||
) -> DebugStruct<'a, 'b> {
|
||||
let result = fmt.write_str(name);
|
||||
DebugStruct { fmt, result, has_fields: false }
|
||||
}
|
||||
|
||||
impl<'a, 'b: 'a> DebugStruct<'a, 'b> {
|
||||
/// Adds a new field to the generated struct output.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::fmt;
|
||||
///
|
||||
/// struct Bar {
|
||||
/// bar: i32,
|
||||
/// another: String,
|
||||
/// }
|
||||
///
|
||||
/// impl fmt::Debug for Bar {
|
||||
/// fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
/// fmt.debug_struct("Bar")
|
||||
/// .field("bar", &self.bar) // We add `bar` field.
|
||||
/// .field("another", &self.another) // We add `another` field.
|
||||
/// // We even add a field which doesn't exist (because why not?).
|
||||
/// .field("not_existing_field", &1)
|
||||
/// .finish() // We're good to go!
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// assert_eq!(
|
||||
/// format!("{:?}", Bar { bar: 10, another: "Hello World".to_string() }),
|
||||
/// "Bar { bar: 10, another: \"Hello World\", not_existing_field: 1 }",
|
||||
/// );
|
||||
/// ```
|
||||
#[stable(feature = "debug_builders", since = "1.2.0")]
|
||||
pub fn field(&mut self, name: &str, value: &dyn fmt::Debug) -> &mut Self {
|
||||
self.result = self.result.and_then(|_| {
|
||||
if self.is_pretty() {
|
||||
if !self.has_fields {
|
||||
self.fmt.write_str(" {\n")?;
|
||||
}
|
||||
let mut slot = None;
|
||||
let mut state = Default::default();
|
||||
let mut writer = PadAdapter::wrap(&mut self.fmt, &mut slot, &mut state);
|
||||
writer.write_str(name)?;
|
||||
writer.write_str(": ")?;
|
||||
value.fmt(&mut writer)?;
|
||||
writer.write_str(",\n")
|
||||
} else {
|
||||
let prefix = if self.has_fields { ", " } else { " { " };
|
||||
self.fmt.write_str(prefix)?;
|
||||
self.fmt.write_str(name)?;
|
||||
self.fmt.write_str(": ")?;
|
||||
value.fmt(self.fmt)
|
||||
}
|
||||
});
|
||||
|
||||
self.has_fields = true;
|
||||
self
|
||||
}
|
||||
|
||||
/// Marks the struct as non-exhaustive, indicating to the reader that there are some other
|
||||
/// fields that are not shown in the debug representation.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// # #![feature(debug_non_exhaustive)]
|
||||
/// use std::fmt;
|
||||
///
|
||||
/// struct Bar {
|
||||
/// bar: i32,
|
||||
/// hidden: f32,
|
||||
/// }
|
||||
///
|
||||
/// impl fmt::Debug for Bar {
|
||||
/// fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
/// fmt.debug_struct("Bar")
|
||||
/// .field("bar", &self.bar)
|
||||
/// .finish_non_exhaustive() // Show that some other field(s) exist.
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// assert_eq!(
|
||||
/// format!("{:?}", Bar { bar: 10, hidden: 1.0 }),
|
||||
/// "Bar { bar: 10, .. }",
|
||||
/// );
|
||||
/// ```
|
||||
#[unstable(feature = "debug_non_exhaustive", issue = "67364")]
|
||||
pub fn finish_non_exhaustive(&mut self) -> fmt::Result {
|
||||
self.result = self.result.and_then(|_| {
|
||||
// Draw non-exhaustive dots (`..`), and open brace if necessary (no fields).
|
||||
if self.is_pretty() {
|
||||
if !self.has_fields {
|
||||
self.fmt.write_str(" {\n")?;
|
||||
}
|
||||
let mut slot = None;
|
||||
let mut state = Default::default();
|
||||
let mut writer = PadAdapter::wrap(&mut self.fmt, &mut slot, &mut state);
|
||||
writer.write_str("..\n")?;
|
||||
} else {
|
||||
if self.has_fields {
|
||||
self.fmt.write_str(", ..")?;
|
||||
} else {
|
||||
self.fmt.write_str(" { ..")?;
|
||||
}
|
||||
}
|
||||
if self.is_pretty() {
|
||||
self.fmt.write_str("}")?
|
||||
} else {
|
||||
self.fmt.write_str(" }")?;
|
||||
}
|
||||
Ok(())
|
||||
});
|
||||
self.result
|
||||
}
|
||||
|
||||
/// Finishes output and returns any error encountered.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::fmt;
|
||||
///
|
||||
/// struct Bar {
|
||||
/// bar: i32,
|
||||
/// baz: String,
|
||||
/// }
|
||||
///
|
||||
/// impl fmt::Debug for Bar {
|
||||
/// fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
/// fmt.debug_struct("Bar")
|
||||
/// .field("bar", &self.bar)
|
||||
/// .field("baz", &self.baz)
|
||||
/// .finish() // You need to call it to "finish" the
|
||||
/// // struct formatting.
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// assert_eq!(
|
||||
/// format!("{:?}", Bar { bar: 10, baz: "Hello World".to_string() }),
|
||||
/// "Bar { bar: 10, baz: \"Hello World\" }",
|
||||
/// );
|
||||
/// ```
|
||||
#[stable(feature = "debug_builders", since = "1.2.0")]
|
||||
pub fn finish(&mut self) -> fmt::Result {
|
||||
if self.has_fields {
|
||||
self.result = self.result.and_then(|_| {
|
||||
if self.is_pretty() { self.fmt.write_str("}") } else { self.fmt.write_str(" }") }
|
||||
});
|
||||
}
|
||||
self.result
|
||||
}
|
||||
|
||||
fn is_pretty(&self) -> bool {
|
||||
self.fmt.alternate()
|
||||
}
|
||||
}
|
||||
|
||||
/// A struct to help with [`fmt::Debug`](Debug) implementations.
|
||||
///
|
||||
/// This is useful when you wish to output a formatted tuple as a part of your
|
||||
/// [`Debug::fmt`] implementation.
|
||||
///
|
||||
/// This can be constructed by the [`Formatter::debug_tuple`] method.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::fmt;
|
||||
///
|
||||
/// struct Foo(i32, String);
|
||||
///
|
||||
/// impl fmt::Debug for Foo {
|
||||
/// fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||
/// fmt.debug_tuple("Foo")
|
||||
/// .field(&self.0)
|
||||
/// .field(&self.1)
|
||||
/// .finish()
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// assert_eq!(
|
||||
/// format!("{:?}", Foo(10, "Hello World".to_string())),
|
||||
/// "Foo(10, \"Hello World\")",
|
||||
/// );
|
||||
/// ```
|
||||
#[must_use = "must eventually call `finish()` on Debug builders"]
|
||||
#[allow(missing_debug_implementations)]
|
||||
#[stable(feature = "debug_builders", since = "1.2.0")]
|
||||
pub struct DebugTuple<'a, 'b: 'a> {
|
||||
fmt: &'a mut fmt::Formatter<'b>,
|
||||
result: fmt::Result,
|
||||
fields: usize,
|
||||
empty_name: bool,
|
||||
}
|
||||
|
||||
pub(super) fn debug_tuple_new<'a, 'b>(
|
||||
fmt: &'a mut fmt::Formatter<'b>,
|
||||
name: &str,
|
||||
) -> DebugTuple<'a, 'b> {
|
||||
let result = fmt.write_str(name);
|
||||
DebugTuple { fmt, result, fields: 0, empty_name: name.is_empty() }
|
||||
}
|
||||
|
||||
impl<'a, 'b: 'a> DebugTuple<'a, 'b> {
|
||||
/// Adds a new field to the generated tuple struct output.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::fmt;
|
||||
///
|
||||
/// struct Foo(i32, String);
|
||||
///
|
||||
/// impl fmt::Debug for Foo {
|
||||
/// fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
/// fmt.debug_tuple("Foo")
|
||||
/// .field(&self.0) // We add the first field.
|
||||
/// .field(&self.1) // We add the second field.
|
||||
/// .finish() // We're good to go!
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// assert_eq!(
|
||||
/// format!("{:?}", Foo(10, "Hello World".to_string())),
|
||||
/// "Foo(10, \"Hello World\")",
|
||||
/// );
|
||||
/// ```
|
||||
#[stable(feature = "debug_builders", since = "1.2.0")]
|
||||
pub fn field(&mut self, value: &dyn fmt::Debug) -> &mut Self {
|
||||
self.result = self.result.and_then(|_| {
|
||||
if self.is_pretty() {
|
||||
if self.fields == 0 {
|
||||
self.fmt.write_str("(\n")?;
|
||||
}
|
||||
let mut slot = None;
|
||||
let mut state = Default::default();
|
||||
let mut writer = PadAdapter::wrap(&mut self.fmt, &mut slot, &mut state);
|
||||
value.fmt(&mut writer)?;
|
||||
writer.write_str(",\n")
|
||||
} else {
|
||||
let prefix = if self.fields == 0 { "(" } else { ", " };
|
||||
self.fmt.write_str(prefix)?;
|
||||
value.fmt(self.fmt)
|
||||
}
|
||||
});
|
||||
|
||||
self.fields += 1;
|
||||
self
|
||||
}
|
||||
|
||||
/// Finishes output and returns any error encountered.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::fmt;
|
||||
///
|
||||
/// struct Foo(i32, String);
|
||||
///
|
||||
/// impl fmt::Debug for Foo {
|
||||
/// fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
/// fmt.debug_tuple("Foo")
|
||||
/// .field(&self.0)
|
||||
/// .field(&self.1)
|
||||
/// .finish() // You need to call it to "finish" the
|
||||
/// // tuple formatting.
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// assert_eq!(
|
||||
/// format!("{:?}", Foo(10, "Hello World".to_string())),
|
||||
/// "Foo(10, \"Hello World\")",
|
||||
/// );
|
||||
/// ```
|
||||
#[stable(feature = "debug_builders", since = "1.2.0")]
|
||||
pub fn finish(&mut self) -> fmt::Result {
|
||||
if self.fields > 0 {
|
||||
self.result = self.result.and_then(|_| {
|
||||
if self.fields == 1 && self.empty_name && !self.is_pretty() {
|
||||
self.fmt.write_str(",")?;
|
||||
}
|
||||
self.fmt.write_str(")")
|
||||
});
|
||||
}
|
||||
self.result
|
||||
}
|
||||
|
||||
fn is_pretty(&self) -> bool {
|
||||
self.fmt.alternate()
|
||||
}
|
||||
}
|
||||
|
||||
struct DebugInner<'a, 'b: 'a> {
|
||||
fmt: &'a mut fmt::Formatter<'b>,
|
||||
result: fmt::Result,
|
||||
has_fields: bool,
|
||||
}
|
||||
|
||||
impl<'a, 'b: 'a> DebugInner<'a, 'b> {
|
||||
fn entry(&mut self, entry: &dyn fmt::Debug) {
|
||||
self.result = self.result.and_then(|_| {
|
||||
if self.is_pretty() {
|
||||
if !self.has_fields {
|
||||
self.fmt.write_str("\n")?;
|
||||
}
|
||||
let mut slot = None;
|
||||
let mut state = Default::default();
|
||||
let mut writer = PadAdapter::wrap(&mut self.fmt, &mut slot, &mut state);
|
||||
entry.fmt(&mut writer)?;
|
||||
writer.write_str(",\n")
|
||||
} else {
|
||||
if self.has_fields {
|
||||
self.fmt.write_str(", ")?
|
||||
}
|
||||
entry.fmt(self.fmt)
|
||||
}
|
||||
});
|
||||
|
||||
self.has_fields = true;
|
||||
}
|
||||
|
||||
fn is_pretty(&self) -> bool {
|
||||
self.fmt.alternate()
|
||||
}
|
||||
}
|
||||
|
||||
/// A struct to help with [`fmt::Debug`](Debug) implementations.
|
||||
///
|
||||
/// This is useful when you wish to output a formatted set of items as a part
|
||||
/// of your [`Debug::fmt`] implementation.
|
||||
///
|
||||
/// This can be constructed by the [`Formatter::debug_set`] method.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::fmt;
|
||||
///
|
||||
/// struct Foo(Vec<i32>);
|
||||
///
|
||||
/// impl fmt::Debug for Foo {
|
||||
/// fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||
/// fmt.debug_set().entries(self.0.iter()).finish()
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// assert_eq!(
|
||||
/// format!("{:?}", Foo(vec![10, 11])),
|
||||
/// "{10, 11}",
|
||||
/// );
|
||||
/// ```
|
||||
#[must_use = "must eventually call `finish()` on Debug builders"]
|
||||
#[allow(missing_debug_implementations)]
|
||||
#[stable(feature = "debug_builders", since = "1.2.0")]
|
||||
pub struct DebugSet<'a, 'b: 'a> {
|
||||
inner: DebugInner<'a, 'b>,
|
||||
}
|
||||
|
||||
pub(super) fn debug_set_new<'a, 'b>(fmt: &'a mut fmt::Formatter<'b>) -> DebugSet<'a, 'b> {
|
||||
let result = fmt.write_str("{");
|
||||
DebugSet { inner: DebugInner { fmt, result, has_fields: false } }
|
||||
}
|
||||
|
||||
impl<'a, 'b: 'a> DebugSet<'a, 'b> {
|
||||
/// Adds a new entry to the set output.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::fmt;
|
||||
///
|
||||
/// struct Foo(Vec<i32>, Vec<u32>);
|
||||
///
|
||||
/// impl fmt::Debug for Foo {
|
||||
/// fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
/// fmt.debug_set()
|
||||
/// .entry(&self.0) // Adds the first "entry".
|
||||
/// .entry(&self.1) // Adds the second "entry".
|
||||
/// .finish()
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// assert_eq!(
|
||||
/// format!("{:?}", Foo(vec![10, 11], vec![12, 13])),
|
||||
/// "{[10, 11], [12, 13]}",
|
||||
/// );
|
||||
/// ```
|
||||
#[stable(feature = "debug_builders", since = "1.2.0")]
|
||||
pub fn entry(&mut self, entry: &dyn fmt::Debug) -> &mut Self {
|
||||
self.inner.entry(entry);
|
||||
self
|
||||
}
|
||||
|
||||
/// Adds the contents of an iterator of entries to the set output.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::fmt;
|
||||
///
|
||||
/// struct Foo(Vec<i32>, Vec<u32>);
|
||||
///
|
||||
/// impl fmt::Debug for Foo {
|
||||
/// fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
/// fmt.debug_set()
|
||||
/// .entries(self.0.iter()) // Adds the first "entry".
|
||||
/// .entries(self.1.iter()) // Adds the second "entry".
|
||||
/// .finish()
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// assert_eq!(
|
||||
/// format!("{:?}", Foo(vec![10, 11], vec![12, 13])),
|
||||
/// "{10, 11, 12, 13}",
|
||||
/// );
|
||||
/// ```
|
||||
#[stable(feature = "debug_builders", since = "1.2.0")]
|
||||
pub fn entries<D, I>(&mut self, entries: I) -> &mut Self
|
||||
where
|
||||
D: fmt::Debug,
|
||||
I: IntoIterator<Item = D>,
|
||||
{
|
||||
for entry in entries {
|
||||
self.entry(&entry);
|
||||
}
|
||||
self
|
||||
}
|
||||
|
||||
/// Finishes output and returns any error encountered.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::fmt;
|
||||
///
|
||||
/// struct Foo(Vec<i32>);
|
||||
///
|
||||
/// impl fmt::Debug for Foo {
|
||||
/// fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
/// fmt.debug_set()
|
||||
/// .entries(self.0.iter())
|
||||
/// .finish() // Ends the struct formatting.
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// assert_eq!(
|
||||
/// format!("{:?}", Foo(vec![10, 11])),
|
||||
/// "{10, 11}",
|
||||
/// );
|
||||
/// ```
|
||||
#[stable(feature = "debug_builders", since = "1.2.0")]
|
||||
pub fn finish(&mut self) -> fmt::Result {
|
||||
self.inner.result.and_then(|_| self.inner.fmt.write_str("}"))
|
||||
}
|
||||
}
|
||||
|
||||
/// A struct to help with [`fmt::Debug`](Debug) implementations.
|
||||
///
|
||||
/// This is useful when you wish to output a formatted list of items as a part
|
||||
/// of your [`Debug::fmt`] implementation.
|
||||
///
|
||||
/// This can be constructed by the [`Formatter::debug_list`] method.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::fmt;
|
||||
///
|
||||
/// struct Foo(Vec<i32>);
|
||||
///
|
||||
/// impl fmt::Debug for Foo {
|
||||
/// fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||
/// fmt.debug_list().entries(self.0.iter()).finish()
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// assert_eq!(
|
||||
/// format!("{:?}", Foo(vec![10, 11])),
|
||||
/// "[10, 11]",
|
||||
/// );
|
||||
/// ```
|
||||
#[must_use = "must eventually call `finish()` on Debug builders"]
|
||||
#[allow(missing_debug_implementations)]
|
||||
#[stable(feature = "debug_builders", since = "1.2.0")]
|
||||
pub struct DebugList<'a, 'b: 'a> {
|
||||
inner: DebugInner<'a, 'b>,
|
||||
}
|
||||
|
||||
pub(super) fn debug_list_new<'a, 'b>(fmt: &'a mut fmt::Formatter<'b>) -> DebugList<'a, 'b> {
|
||||
let result = fmt.write_str("[");
|
||||
DebugList { inner: DebugInner { fmt, result, has_fields: false } }
|
||||
}
|
||||
|
||||
impl<'a, 'b: 'a> DebugList<'a, 'b> {
|
||||
/// Adds a new entry to the list output.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::fmt;
|
||||
///
|
||||
/// struct Foo(Vec<i32>, Vec<u32>);
|
||||
///
|
||||
/// impl fmt::Debug for Foo {
|
||||
/// fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
/// fmt.debug_list()
|
||||
/// .entry(&self.0) // We add the first "entry".
|
||||
/// .entry(&self.1) // We add the second "entry".
|
||||
/// .finish()
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// assert_eq!(
|
||||
/// format!("{:?}", Foo(vec![10, 11], vec![12, 13])),
|
||||
/// "[[10, 11], [12, 13]]",
|
||||
/// );
|
||||
/// ```
|
||||
#[stable(feature = "debug_builders", since = "1.2.0")]
|
||||
pub fn entry(&mut self, entry: &dyn fmt::Debug) -> &mut Self {
|
||||
self.inner.entry(entry);
|
||||
self
|
||||
}
|
||||
|
||||
/// Adds the contents of an iterator of entries to the list output.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::fmt;
|
||||
///
|
||||
/// struct Foo(Vec<i32>, Vec<u32>);
|
||||
///
|
||||
/// impl fmt::Debug for Foo {
|
||||
/// fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
/// fmt.debug_list()
|
||||
/// .entries(self.0.iter())
|
||||
/// .entries(self.1.iter())
|
||||
/// .finish()
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// assert_eq!(
|
||||
/// format!("{:?}", Foo(vec![10, 11], vec![12, 13])),
|
||||
/// "[10, 11, 12, 13]",
|
||||
/// );
|
||||
/// ```
|
||||
#[stable(feature = "debug_builders", since = "1.2.0")]
|
||||
pub fn entries<D, I>(&mut self, entries: I) -> &mut Self
|
||||
where
|
||||
D: fmt::Debug,
|
||||
I: IntoIterator<Item = D>,
|
||||
{
|
||||
for entry in entries {
|
||||
self.entry(&entry);
|
||||
}
|
||||
self
|
||||
}
|
||||
|
||||
/// Finishes output and returns any error encountered.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::fmt;
|
||||
///
|
||||
/// struct Foo(Vec<i32>);
|
||||
///
|
||||
/// impl fmt::Debug for Foo {
|
||||
/// fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
/// fmt.debug_list()
|
||||
/// .entries(self.0.iter())
|
||||
/// .finish() // Ends the struct formatting.
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// assert_eq!(
|
||||
/// format!("{:?}", Foo(vec![10, 11])),
|
||||
/// "[10, 11]",
|
||||
/// );
|
||||
/// ```
|
||||
#[stable(feature = "debug_builders", since = "1.2.0")]
|
||||
pub fn finish(&mut self) -> fmt::Result {
|
||||
self.inner.result.and_then(|_| self.inner.fmt.write_str("]"))
|
||||
}
|
||||
}
|
||||
|
||||
/// A struct to help with [`fmt::Debug`](Debug) implementations.
|
||||
///
|
||||
/// This is useful when you wish to output a formatted map as a part of your
|
||||
/// [`Debug::fmt`] implementation.
|
||||
///
|
||||
/// This can be constructed by the [`Formatter::debug_map`] method.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::fmt;
|
||||
///
|
||||
/// struct Foo(Vec<(String, i32)>);
|
||||
///
|
||||
/// impl fmt::Debug for Foo {
|
||||
/// fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||
/// fmt.debug_map().entries(self.0.iter().map(|&(ref k, ref v)| (k, v))).finish()
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// assert_eq!(
|
||||
/// format!("{:?}", Foo(vec![("A".to_string(), 10), ("B".to_string(), 11)])),
|
||||
/// "{\"A\": 10, \"B\": 11}",
|
||||
/// );
|
||||
/// ```
|
||||
#[must_use = "must eventually call `finish()` on Debug builders"]
|
||||
#[allow(missing_debug_implementations)]
|
||||
#[stable(feature = "debug_builders", since = "1.2.0")]
|
||||
pub struct DebugMap<'a, 'b: 'a> {
|
||||
fmt: &'a mut fmt::Formatter<'b>,
|
||||
result: fmt::Result,
|
||||
has_fields: bool,
|
||||
has_key: bool,
|
||||
// The state of newlines is tracked between keys and values
|
||||
state: PadAdapterState,
|
||||
}
|
||||
|
||||
pub(super) fn debug_map_new<'a, 'b>(fmt: &'a mut fmt::Formatter<'b>) -> DebugMap<'a, 'b> {
|
||||
let result = fmt.write_str("{");
|
||||
DebugMap { fmt, result, has_fields: false, has_key: false, state: Default::default() }
|
||||
}
|
||||
|
||||
impl<'a, 'b: 'a> DebugMap<'a, 'b> {
|
||||
/// Adds a new entry to the map output.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::fmt;
|
||||
///
|
||||
/// struct Foo(Vec<(String, i32)>);
|
||||
///
|
||||
/// impl fmt::Debug for Foo {
|
||||
/// fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
/// fmt.debug_map()
|
||||
/// .entry(&"whole", &self.0) // We add the "whole" entry.
|
||||
/// .finish()
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// assert_eq!(
|
||||
/// format!("{:?}", Foo(vec![("A".to_string(), 10), ("B".to_string(), 11)])),
|
||||
/// "{\"whole\": [(\"A\", 10), (\"B\", 11)]}",
|
||||
/// );
|
||||
/// ```
|
||||
#[stable(feature = "debug_builders", since = "1.2.0")]
|
||||
pub fn entry(&mut self, key: &dyn fmt::Debug, value: &dyn fmt::Debug) -> &mut Self {
|
||||
self.key(key).value(value)
|
||||
}
|
||||
|
||||
/// Adds the key part of a new entry to the map output.
|
||||
///
|
||||
/// This method, together with `value`, is an alternative to `entry` that
|
||||
/// can be used when the complete entry isn't known upfront. Prefer the `entry`
|
||||
/// method when it's possible to use.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// `key` must be called before `value` and each call to `key` must be followed
|
||||
/// by a corresponding call to `value`. Otherwise this method will panic.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::fmt;
|
||||
///
|
||||
/// struct Foo(Vec<(String, i32)>);
|
||||
///
|
||||
/// impl fmt::Debug for Foo {
|
||||
/// fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
/// fmt.debug_map()
|
||||
/// .key(&"whole").value(&self.0) // We add the "whole" entry.
|
||||
/// .finish()
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// assert_eq!(
|
||||
/// format!("{:?}", Foo(vec![("A".to_string(), 10), ("B".to_string(), 11)])),
|
||||
/// "{\"whole\": [(\"A\", 10), (\"B\", 11)]}",
|
||||
/// );
|
||||
/// ```
|
||||
#[stable(feature = "debug_map_key_value", since = "1.42.0")]
|
||||
pub fn key(&mut self, key: &dyn fmt::Debug) -> &mut Self {
|
||||
self.result = self.result.and_then(|_| {
|
||||
assert!(
|
||||
!self.has_key,
|
||||
"attempted to begin a new map entry \
|
||||
without completing the previous one"
|
||||
);
|
||||
|
||||
if self.is_pretty() {
|
||||
if !self.has_fields {
|
||||
self.fmt.write_str("\n")?;
|
||||
}
|
||||
let mut slot = None;
|
||||
self.state = Default::default();
|
||||
let mut writer = PadAdapter::wrap(&mut self.fmt, &mut slot, &mut self.state);
|
||||
key.fmt(&mut writer)?;
|
||||
writer.write_str(": ")?;
|
||||
} else {
|
||||
if self.has_fields {
|
||||
self.fmt.write_str(", ")?
|
||||
}
|
||||
key.fmt(self.fmt)?;
|
||||
self.fmt.write_str(": ")?;
|
||||
}
|
||||
|
||||
self.has_key = true;
|
||||
Ok(())
|
||||
});
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
/// Adds the value part of a new entry to the map output.
|
||||
///
|
||||
/// This method, together with `key`, is an alternative to `entry` that
|
||||
/// can be used when the complete entry isn't known upfront. Prefer the `entry`
|
||||
/// method when it's possible to use.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// `key` must be called before `value` and each call to `key` must be followed
|
||||
/// by a corresponding call to `value`. Otherwise this method will panic.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::fmt;
|
||||
///
|
||||
/// struct Foo(Vec<(String, i32)>);
|
||||
///
|
||||
/// impl fmt::Debug for Foo {
|
||||
/// fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
/// fmt.debug_map()
|
||||
/// .key(&"whole").value(&self.0) // We add the "whole" entry.
|
||||
/// .finish()
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// assert_eq!(
|
||||
/// format!("{:?}", Foo(vec![("A".to_string(), 10), ("B".to_string(), 11)])),
|
||||
/// "{\"whole\": [(\"A\", 10), (\"B\", 11)]}",
|
||||
/// );
|
||||
/// ```
|
||||
#[stable(feature = "debug_map_key_value", since = "1.42.0")]
|
||||
pub fn value(&mut self, value: &dyn fmt::Debug) -> &mut Self {
|
||||
self.result = self.result.and_then(|_| {
|
||||
assert!(self.has_key, "attempted to format a map value before its key");
|
||||
|
||||
if self.is_pretty() {
|
||||
let mut slot = None;
|
||||
let mut writer = PadAdapter::wrap(&mut self.fmt, &mut slot, &mut self.state);
|
||||
value.fmt(&mut writer)?;
|
||||
writer.write_str(",\n")?;
|
||||
} else {
|
||||
value.fmt(self.fmt)?;
|
||||
}
|
||||
|
||||
self.has_key = false;
|
||||
Ok(())
|
||||
});
|
||||
|
||||
self.has_fields = true;
|
||||
self
|
||||
}
|
||||
|
||||
/// Adds the contents of an iterator of entries to the map output.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::fmt;
|
||||
///
|
||||
/// struct Foo(Vec<(String, i32)>);
|
||||
///
|
||||
/// impl fmt::Debug for Foo {
|
||||
/// fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
/// fmt.debug_map()
|
||||
/// // We map our vec so each entries' first field will become
|
||||
/// // the "key".
|
||||
/// .entries(self.0.iter().map(|&(ref k, ref v)| (k, v)))
|
||||
/// .finish()
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// assert_eq!(
|
||||
/// format!("{:?}", Foo(vec![("A".to_string(), 10), ("B".to_string(), 11)])),
|
||||
/// "{\"A\": 10, \"B\": 11}",
|
||||
/// );
|
||||
/// ```
|
||||
#[stable(feature = "debug_builders", since = "1.2.0")]
|
||||
pub fn entries<K, V, I>(&mut self, entries: I) -> &mut Self
|
||||
where
|
||||
K: fmt::Debug,
|
||||
V: fmt::Debug,
|
||||
I: IntoIterator<Item = (K, V)>,
|
||||
{
|
||||
for (k, v) in entries {
|
||||
self.entry(&k, &v);
|
||||
}
|
||||
self
|
||||
}
|
||||
|
||||
/// Finishes output and returns any error encountered.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// `key` must be called before `value` and each call to `key` must be followed
|
||||
/// by a corresponding call to `value`. Otherwise this method will panic.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::fmt;
|
||||
///
|
||||
/// struct Foo(Vec<(String, i32)>);
|
||||
///
|
||||
/// impl fmt::Debug for Foo {
|
||||
/// fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
/// fmt.debug_map()
|
||||
/// .entries(self.0.iter().map(|&(ref k, ref v)| (k, v)))
|
||||
/// .finish() // Ends the struct formatting.
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// assert_eq!(
|
||||
/// format!("{:?}", Foo(vec![("A".to_string(), 10), ("B".to_string(), 11)])),
|
||||
/// "{\"A\": 10, \"B\": 11}",
|
||||
/// );
|
||||
/// ```
|
||||
#[stable(feature = "debug_builders", since = "1.2.0")]
|
||||
pub fn finish(&mut self) -> fmt::Result {
|
||||
self.result.and_then(|_| {
|
||||
assert!(!self.has_key, "attempted to finish a map with a partial entry");
|
||||
|
||||
self.fmt.write_str("}")
|
||||
})
|
||||
}
|
||||
|
||||
fn is_pretty(&self) -> bool {
|
||||
self.fmt.alternate()
|
||||
}
|
||||
}
|
||||
187
libgrust/rustc-lib/core/src/fmt/float.rs
Normal file
187
libgrust/rustc-lib/core/src/fmt/float.rs
Normal file
@@ -0,0 +1,187 @@
|
||||
use crate::fmt::{Debug, Display, Formatter, LowerExp, Result, UpperExp};
|
||||
use crate::mem::MaybeUninit;
|
||||
use crate::num::flt2dec;
|
||||
|
||||
// Don't inline this so callers don't use the stack space this function
|
||||
// requires unless they have to.
|
||||
#[inline(never)]
|
||||
fn float_to_decimal_common_exact<T>(
|
||||
fmt: &mut Formatter<'_>,
|
||||
num: &T,
|
||||
sign: flt2dec::Sign,
|
||||
precision: usize,
|
||||
) -> Result
|
||||
where
|
||||
T: flt2dec::DecodableFloat,
|
||||
{
|
||||
let mut buf: [MaybeUninit<u8>; 1024] = MaybeUninit::uninit_array(); // enough for f32 and f64
|
||||
let mut parts: [MaybeUninit<flt2dec::Part<'_>>; 4] = MaybeUninit::uninit_array();
|
||||
let formatted = flt2dec::to_exact_fixed_str(
|
||||
flt2dec::strategy::grisu::format_exact,
|
||||
*num,
|
||||
sign,
|
||||
precision,
|
||||
&mut buf,
|
||||
&mut parts,
|
||||
);
|
||||
fmt.pad_formatted_parts(&formatted)
|
||||
}
|
||||
|
||||
// Don't inline this so callers that call both this and the above won't wind
|
||||
// up using the combined stack space of both functions in some cases.
|
||||
#[inline(never)]
|
||||
fn float_to_decimal_common_shortest<T>(
|
||||
fmt: &mut Formatter<'_>,
|
||||
num: &T,
|
||||
sign: flt2dec::Sign,
|
||||
precision: usize,
|
||||
) -> Result
|
||||
where
|
||||
T: flt2dec::DecodableFloat,
|
||||
{
|
||||
// enough for f32 and f64
|
||||
let mut buf: [MaybeUninit<u8>; flt2dec::MAX_SIG_DIGITS] = MaybeUninit::uninit_array();
|
||||
let mut parts: [MaybeUninit<flt2dec::Part<'_>>; 4] = MaybeUninit::uninit_array();
|
||||
let formatted = flt2dec::to_shortest_str(
|
||||
flt2dec::strategy::grisu::format_shortest,
|
||||
*num,
|
||||
sign,
|
||||
precision,
|
||||
&mut buf,
|
||||
&mut parts,
|
||||
);
|
||||
fmt.pad_formatted_parts(&formatted)
|
||||
}
|
||||
|
||||
// Common code of floating point Debug and Display.
|
||||
fn float_to_decimal_common<T>(
|
||||
fmt: &mut Formatter<'_>,
|
||||
num: &T,
|
||||
negative_zero: bool,
|
||||
min_precision: usize,
|
||||
) -> Result
|
||||
where
|
||||
T: flt2dec::DecodableFloat,
|
||||
{
|
||||
let force_sign = fmt.sign_plus();
|
||||
let sign = match (force_sign, negative_zero) {
|
||||
(false, false) => flt2dec::Sign::Minus,
|
||||
(false, true) => flt2dec::Sign::MinusRaw,
|
||||
(true, false) => flt2dec::Sign::MinusPlus,
|
||||
(true, true) => flt2dec::Sign::MinusPlusRaw,
|
||||
};
|
||||
|
||||
if let Some(precision) = fmt.precision {
|
||||
float_to_decimal_common_exact(fmt, num, sign, precision)
|
||||
} else {
|
||||
float_to_decimal_common_shortest(fmt, num, sign, min_precision)
|
||||
}
|
||||
}
|
||||
|
||||
// Don't inline this so callers don't use the stack space this function
|
||||
// requires unless they have to.
|
||||
#[inline(never)]
|
||||
fn float_to_exponential_common_exact<T>(
|
||||
fmt: &mut Formatter<'_>,
|
||||
num: &T,
|
||||
sign: flt2dec::Sign,
|
||||
precision: usize,
|
||||
upper: bool,
|
||||
) -> Result
|
||||
where
|
||||
T: flt2dec::DecodableFloat,
|
||||
{
|
||||
let mut buf: [MaybeUninit<u8>; 1024] = MaybeUninit::uninit_array(); // enough for f32 and f64
|
||||
let mut parts: [MaybeUninit<flt2dec::Part<'_>>; 6] = MaybeUninit::uninit_array();
|
||||
let formatted = flt2dec::to_exact_exp_str(
|
||||
flt2dec::strategy::grisu::format_exact,
|
||||
*num,
|
||||
sign,
|
||||
precision,
|
||||
upper,
|
||||
&mut buf,
|
||||
&mut parts,
|
||||
);
|
||||
fmt.pad_formatted_parts(&formatted)
|
||||
}
|
||||
|
||||
// Don't inline this so callers that call both this and the above won't wind
|
||||
// up using the combined stack space of both functions in some cases.
|
||||
#[inline(never)]
|
||||
fn float_to_exponential_common_shortest<T>(
|
||||
fmt: &mut Formatter<'_>,
|
||||
num: &T,
|
||||
sign: flt2dec::Sign,
|
||||
upper: bool,
|
||||
) -> Result
|
||||
where
|
||||
T: flt2dec::DecodableFloat,
|
||||
{
|
||||
// enough for f32 and f64
|
||||
let mut buf: [MaybeUninit<u8>; flt2dec::MAX_SIG_DIGITS] = MaybeUninit::uninit_array();
|
||||
let mut parts: [MaybeUninit<flt2dec::Part<'_>>; 6] = MaybeUninit::uninit_array();
|
||||
let formatted = flt2dec::to_shortest_exp_str(
|
||||
flt2dec::strategy::grisu::format_shortest,
|
||||
*num,
|
||||
sign,
|
||||
(0, 0),
|
||||
upper,
|
||||
&mut buf,
|
||||
&mut parts,
|
||||
);
|
||||
fmt.pad_formatted_parts(&formatted)
|
||||
}
|
||||
|
||||
// Common code of floating point LowerExp and UpperExp.
|
||||
fn float_to_exponential_common<T>(fmt: &mut Formatter<'_>, num: &T, upper: bool) -> Result
|
||||
where
|
||||
T: flt2dec::DecodableFloat,
|
||||
{
|
||||
let force_sign = fmt.sign_plus();
|
||||
let sign = match force_sign {
|
||||
false => flt2dec::Sign::Minus,
|
||||
true => flt2dec::Sign::MinusPlus,
|
||||
};
|
||||
|
||||
if let Some(precision) = fmt.precision {
|
||||
// 1 integral digit + `precision` fractional digits = `precision + 1` total digits
|
||||
float_to_exponential_common_exact(fmt, num, sign, precision + 1, upper)
|
||||
} else {
|
||||
float_to_exponential_common_shortest(fmt, num, sign, upper)
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! floating {
|
||||
($ty:ident) => {
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl Debug for $ty {
|
||||
fn fmt(&self, fmt: &mut Formatter<'_>) -> Result {
|
||||
float_to_decimal_common(fmt, self, true, 1)
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl Display for $ty {
|
||||
fn fmt(&self, fmt: &mut Formatter<'_>) -> Result {
|
||||
float_to_decimal_common(fmt, self, false, 0)
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl LowerExp for $ty {
|
||||
fn fmt(&self, fmt: &mut Formatter<'_>) -> Result {
|
||||
float_to_exponential_common(fmt, self, false)
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl UpperExp for $ty {
|
||||
fn fmt(&self, fmt: &mut Formatter<'_>) -> Result {
|
||||
float_to_exponential_common(fmt, self, true)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
floating! { f32 }
|
||||
floating! { f64 }
|
||||
2241
libgrust/rustc-lib/core/src/fmt/mod.rs
Normal file
2241
libgrust/rustc-lib/core/src/fmt/mod.rs
Normal file
File diff suppressed because it is too large
Load Diff
667
libgrust/rustc-lib/core/src/fmt/num.rs
Normal file
667
libgrust/rustc-lib/core/src/fmt/num.rs
Normal file
@@ -0,0 +1,667 @@
|
||||
//! Integer and floating-point number formatting
|
||||
|
||||
use crate::fmt;
|
||||
use crate::mem::MaybeUninit;
|
||||
use crate::num::flt2dec;
|
||||
use crate::ops::{Div, Rem, Sub};
|
||||
use crate::ptr;
|
||||
use crate::slice;
|
||||
use crate::str;
|
||||
|
||||
#[doc(hidden)]
|
||||
trait DisplayInt:
|
||||
PartialEq + PartialOrd + Div<Output = Self> + Rem<Output = Self> + Sub<Output = Self> + Copy
|
||||
{
|
||||
fn zero() -> Self;
|
||||
fn from_u8(u: u8) -> Self;
|
||||
fn to_u8(&self) -> u8;
|
||||
fn to_u16(&self) -> u16;
|
||||
fn to_u32(&self) -> u32;
|
||||
fn to_u64(&self) -> u64;
|
||||
fn to_u128(&self) -> u128;
|
||||
}
|
||||
|
||||
macro_rules! impl_int {
|
||||
($($t:ident)*) => (
|
||||
$(impl DisplayInt for $t {
|
||||
fn zero() -> Self { 0 }
|
||||
fn from_u8(u: u8) -> Self { u as Self }
|
||||
fn to_u8(&self) -> u8 { *self as u8 }
|
||||
fn to_u16(&self) -> u16 { *self as u16 }
|
||||
fn to_u32(&self) -> u32 { *self as u32 }
|
||||
fn to_u64(&self) -> u64 { *self as u64 }
|
||||
fn to_u128(&self) -> u128 { *self as u128 }
|
||||
})*
|
||||
)
|
||||
}
|
||||
macro_rules! impl_uint {
|
||||
($($t:ident)*) => (
|
||||
$(impl DisplayInt for $t {
|
||||
fn zero() -> Self { 0 }
|
||||
fn from_u8(u: u8) -> Self { u as Self }
|
||||
fn to_u8(&self) -> u8 { *self as u8 }
|
||||
fn to_u16(&self) -> u16 { *self as u16 }
|
||||
fn to_u32(&self) -> u32 { *self as u32 }
|
||||
fn to_u64(&self) -> u64 { *self as u64 }
|
||||
fn to_u128(&self) -> u128 { *self as u128 }
|
||||
})*
|
||||
)
|
||||
}
|
||||
|
||||
impl_int! { i8 i16 i32 i64 i128 isize }
|
||||
impl_uint! { u8 u16 u32 u64 u128 usize }
|
||||
|
||||
/// A type that represents a specific radix
|
||||
#[doc(hidden)]
|
||||
trait GenericRadix: Sized {
|
||||
/// The number of digits.
|
||||
const BASE: u8;
|
||||
|
||||
/// A radix-specific prefix string.
|
||||
const PREFIX: &'static str;
|
||||
|
||||
/// Converts an integer to corresponding radix digit.
|
||||
fn digit(x: u8) -> u8;
|
||||
|
||||
/// Format an integer using the radix using a formatter.
|
||||
fn fmt_int<T: DisplayInt>(&self, mut x: T, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
// The radix can be as low as 2, so we need a buffer of at least 128
|
||||
// characters for a base 2 number.
|
||||
let zero = T::zero();
|
||||
let is_nonnegative = x >= zero;
|
||||
let mut buf = [MaybeUninit::<u8>::uninit(); 128];
|
||||
let mut curr = buf.len();
|
||||
let base = T::from_u8(Self::BASE);
|
||||
if is_nonnegative {
|
||||
// Accumulate each digit of the number from the least significant
|
||||
// to the most significant figure.
|
||||
for byte in buf.iter_mut().rev() {
|
||||
let n = x % base; // Get the current place value.
|
||||
x = x / base; // Deaccumulate the number.
|
||||
byte.write(Self::digit(n.to_u8())); // Store the digit in the buffer.
|
||||
curr -= 1;
|
||||
if x == zero {
|
||||
// No more digits left to accumulate.
|
||||
break;
|
||||
};
|
||||
}
|
||||
} else {
|
||||
// Do the same as above, but accounting for two's complement.
|
||||
for byte in buf.iter_mut().rev() {
|
||||
let n = zero - (x % base); // Get the current place value.
|
||||
x = x / base; // Deaccumulate the number.
|
||||
byte.write(Self::digit(n.to_u8())); // Store the digit in the buffer.
|
||||
curr -= 1;
|
||||
if x == zero {
|
||||
// No more digits left to accumulate.
|
||||
break;
|
||||
};
|
||||
}
|
||||
}
|
||||
let buf = &buf[curr..];
|
||||
// SAFETY: The only chars in `buf` are created by `Self::digit` which are assumed to be
|
||||
// valid UTF-8
|
||||
let buf = unsafe {
|
||||
str::from_utf8_unchecked(slice::from_raw_parts(
|
||||
MaybeUninit::slice_as_ptr(buf),
|
||||
buf.len(),
|
||||
))
|
||||
};
|
||||
f.pad_integral(is_nonnegative, Self::PREFIX, buf)
|
||||
}
|
||||
}
|
||||
|
||||
/// A binary (base 2) radix
|
||||
#[derive(Clone, PartialEq)]
|
||||
struct Binary;
|
||||
|
||||
/// An octal (base 8) radix
|
||||
#[derive(Clone, PartialEq)]
|
||||
struct Octal;
|
||||
|
||||
/// A hexadecimal (base 16) radix, formatted with lower-case characters
|
||||
#[derive(Clone, PartialEq)]
|
||||
struct LowerHex;
|
||||
|
||||
/// A hexadecimal (base 16) radix, formatted with upper-case characters
|
||||
#[derive(Clone, PartialEq)]
|
||||
struct UpperHex;
|
||||
|
||||
macro_rules! radix {
|
||||
($T:ident, $base:expr, $prefix:expr, $($x:pat => $conv:expr),+) => {
|
||||
impl GenericRadix for $T {
|
||||
const BASE: u8 = $base;
|
||||
const PREFIX: &'static str = $prefix;
|
||||
fn digit(x: u8) -> u8 {
|
||||
match x {
|
||||
$($x => $conv,)+
|
||||
x => panic!("number not in the range 0..={}: {}", Self::BASE - 1, x),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
radix! { Binary, 2, "0b", x @ 0 ..= 1 => b'0' + x }
|
||||
radix! { Octal, 8, "0o", x @ 0 ..= 7 => b'0' + x }
|
||||
radix! { LowerHex, 16, "0x", x @ 0 ..= 9 => b'0' + x, x @ 10 ..= 15 => b'a' + (x - 10) }
|
||||
radix! { UpperHex, 16, "0x", x @ 0 ..= 9 => b'0' + x, x @ 10 ..= 15 => b'A' + (x - 10) }
|
||||
|
||||
macro_rules! int_base {
|
||||
(fmt::$Trait:ident for $T:ident as $U:ident -> $Radix:ident) => {
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl fmt::$Trait for $T {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
$Radix.fmt_int(*self as $U, f)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! integer {
|
||||
($Int:ident, $Uint:ident) => {
|
||||
int_base! { fmt::Binary for $Int as $Uint -> Binary }
|
||||
int_base! { fmt::Octal for $Int as $Uint -> Octal }
|
||||
int_base! { fmt::LowerHex for $Int as $Uint -> LowerHex }
|
||||
int_base! { fmt::UpperHex for $Int as $Uint -> UpperHex }
|
||||
|
||||
int_base! { fmt::Binary for $Uint as $Uint -> Binary }
|
||||
int_base! { fmt::Octal for $Uint as $Uint -> Octal }
|
||||
int_base! { fmt::LowerHex for $Uint as $Uint -> LowerHex }
|
||||
int_base! { fmt::UpperHex for $Uint as $Uint -> UpperHex }
|
||||
};
|
||||
}
|
||||
integer! { isize, usize }
|
||||
integer! { i8, u8 }
|
||||
integer! { i16, u16 }
|
||||
integer! { i32, u32 }
|
||||
integer! { i64, u64 }
|
||||
integer! { i128, u128 }
|
||||
macro_rules! debug {
|
||||
($($T:ident)*) => {$(
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl fmt::Debug for $T {
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
if f.debug_lower_hex() {
|
||||
fmt::LowerHex::fmt(self, f)
|
||||
} else if f.debug_upper_hex() {
|
||||
fmt::UpperHex::fmt(self, f)
|
||||
} else {
|
||||
fmt::Display::fmt(self, f)
|
||||
}
|
||||
}
|
||||
}
|
||||
)*};
|
||||
}
|
||||
debug! {
|
||||
i8 i16 i32 i64 i128 isize
|
||||
u8 u16 u32 u64 u128 usize
|
||||
}
|
||||
|
||||
// 2 digit decimal look up table
|
||||
static DEC_DIGITS_LUT: &[u8; 200] = b"0001020304050607080910111213141516171819\
|
||||
2021222324252627282930313233343536373839\
|
||||
4041424344454647484950515253545556575859\
|
||||
6061626364656667686970717273747576777879\
|
||||
8081828384858687888990919293949596979899";
|
||||
|
||||
macro_rules! impl_Display {
|
||||
($($t:ident),* as $u:ident via $conv_fn:ident named $name:ident) => {
|
||||
fn $name(mut n: $u, is_nonnegative: bool, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
// 2^128 is about 3*10^38, so 39 gives an extra byte of space
|
||||
let mut buf = [MaybeUninit::<u8>::uninit(); 39];
|
||||
let mut curr = buf.len() as isize;
|
||||
let buf_ptr = MaybeUninit::slice_as_mut_ptr(&mut buf);
|
||||
let lut_ptr = DEC_DIGITS_LUT.as_ptr();
|
||||
|
||||
// SAFETY: Since `d1` and `d2` are always less than or equal to `198`, we
|
||||
// can copy from `lut_ptr[d1..d1 + 1]` and `lut_ptr[d2..d2 + 1]`. To show
|
||||
// that it's OK to copy into `buf_ptr`, notice that at the beginning
|
||||
// `curr == buf.len() == 39 > log(n)` since `n < 2^128 < 10^39`, and at
|
||||
// each step this is kept the same as `n` is divided. Since `n` is always
|
||||
// non-negative, this means that `curr > 0` so `buf_ptr[curr..curr + 1]`
|
||||
// is safe to access.
|
||||
unsafe {
|
||||
// need at least 16 bits for the 4-characters-at-a-time to work.
|
||||
assert!(crate::mem::size_of::<$u>() >= 2);
|
||||
|
||||
// eagerly decode 4 characters at a time
|
||||
while n >= 10000 {
|
||||
let rem = (n % 10000) as isize;
|
||||
n /= 10000;
|
||||
|
||||
let d1 = (rem / 100) << 1;
|
||||
let d2 = (rem % 100) << 1;
|
||||
curr -= 4;
|
||||
|
||||
// We are allowed to copy to `buf_ptr[curr..curr + 3]` here since
|
||||
// otherwise `curr < 0`. But then `n` was originally at least `10000^10`
|
||||
// which is `10^40 > 2^128 > n`.
|
||||
ptr::copy_nonoverlapping(lut_ptr.offset(d1), buf_ptr.offset(curr), 2);
|
||||
ptr::copy_nonoverlapping(lut_ptr.offset(d2), buf_ptr.offset(curr + 2), 2);
|
||||
}
|
||||
|
||||
// if we reach here numbers are <= 9999, so at most 4 chars long
|
||||
let mut n = n as isize; // possibly reduce 64bit math
|
||||
|
||||
// decode 2 more chars, if > 2 chars
|
||||
if n >= 100 {
|
||||
let d1 = (n % 100) << 1;
|
||||
n /= 100;
|
||||
curr -= 2;
|
||||
ptr::copy_nonoverlapping(lut_ptr.offset(d1), buf_ptr.offset(curr), 2);
|
||||
}
|
||||
|
||||
// decode last 1 or 2 chars
|
||||
if n < 10 {
|
||||
curr -= 1;
|
||||
*buf_ptr.offset(curr) = (n as u8) + b'0';
|
||||
} else {
|
||||
let d1 = n << 1;
|
||||
curr -= 2;
|
||||
ptr::copy_nonoverlapping(lut_ptr.offset(d1), buf_ptr.offset(curr), 2);
|
||||
}
|
||||
}
|
||||
|
||||
// SAFETY: `curr` > 0 (since we made `buf` large enough), and all the chars are valid
|
||||
// UTF-8 since `DEC_DIGITS_LUT` is
|
||||
let buf_slice = unsafe {
|
||||
str::from_utf8_unchecked(
|
||||
slice::from_raw_parts(buf_ptr.offset(curr), buf.len() - curr as usize))
|
||||
};
|
||||
f.pad_integral(is_nonnegative, "", buf_slice)
|
||||
}
|
||||
|
||||
$(#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl fmt::Display for $t {
|
||||
#[allow(unused_comparisons)]
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let is_nonnegative = *self >= 0;
|
||||
let n = if is_nonnegative {
|
||||
self.$conv_fn()
|
||||
} else {
|
||||
// convert the negative num to positive by summing 1 to it's 2 complement
|
||||
(!self.$conv_fn()).wrapping_add(1)
|
||||
};
|
||||
$name(n, is_nonnegative, f)
|
||||
}
|
||||
})*
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! impl_Exp {
|
||||
($($t:ident),* as $u:ident via $conv_fn:ident named $name:ident) => {
|
||||
fn $name(
|
||||
mut n: $u,
|
||||
is_nonnegative: bool,
|
||||
upper: bool,
|
||||
f: &mut fmt::Formatter<'_>
|
||||
) -> fmt::Result {
|
||||
let (mut n, mut exponent, trailing_zeros, added_precision) = {
|
||||
let mut exponent = 0;
|
||||
// count and remove trailing decimal zeroes
|
||||
while n % 10 == 0 && n >= 10 {
|
||||
n /= 10;
|
||||
exponent += 1;
|
||||
}
|
||||
let trailing_zeros = exponent;
|
||||
|
||||
let (added_precision, subtracted_precision) = match f.precision() {
|
||||
Some(fmt_prec) => {
|
||||
// number of decimal digits minus 1
|
||||
let mut tmp = n;
|
||||
let mut prec = 0;
|
||||
while tmp >= 10 {
|
||||
tmp /= 10;
|
||||
prec += 1;
|
||||
}
|
||||
(fmt_prec.saturating_sub(prec), prec.saturating_sub(fmt_prec))
|
||||
}
|
||||
None => (0,0)
|
||||
};
|
||||
for _ in 1..subtracted_precision {
|
||||
n/=10;
|
||||
exponent += 1;
|
||||
}
|
||||
if subtracted_precision != 0 {
|
||||
let rem = n % 10;
|
||||
n /= 10;
|
||||
exponent += 1;
|
||||
// round up last digit
|
||||
if rem >= 5 {
|
||||
n += 1;
|
||||
}
|
||||
}
|
||||
(n, exponent, trailing_zeros, added_precision)
|
||||
};
|
||||
|
||||
// 39 digits (worst case u128) + . = 40
|
||||
// Since `curr` always decreases by the number of digits copied, this means
|
||||
// that `curr >= 0`.
|
||||
let mut buf = [MaybeUninit::<u8>::uninit(); 40];
|
||||
let mut curr = buf.len() as isize; //index for buf
|
||||
let buf_ptr = MaybeUninit::slice_as_mut_ptr(&mut buf);
|
||||
let lut_ptr = DEC_DIGITS_LUT.as_ptr();
|
||||
|
||||
// decode 2 chars at a time
|
||||
while n >= 100 {
|
||||
let d1 = ((n % 100) as isize) << 1;
|
||||
curr -= 2;
|
||||
// SAFETY: `d1 <= 198`, so we can copy from `lut_ptr[d1..d1 + 2]` since
|
||||
// `DEC_DIGITS_LUT` has a length of 200.
|
||||
unsafe {
|
||||
ptr::copy_nonoverlapping(lut_ptr.offset(d1), buf_ptr.offset(curr), 2);
|
||||
}
|
||||
n /= 100;
|
||||
exponent += 2;
|
||||
}
|
||||
// n is <= 99, so at most 2 chars long
|
||||
let mut n = n as isize; // possibly reduce 64bit math
|
||||
// decode second-to-last character
|
||||
if n >= 10 {
|
||||
curr -= 1;
|
||||
// SAFETY: Safe since `40 > curr >= 0` (see comment)
|
||||
unsafe {
|
||||
*buf_ptr.offset(curr) = (n as u8 % 10_u8) + b'0';
|
||||
}
|
||||
n /= 10;
|
||||
exponent += 1;
|
||||
}
|
||||
// add decimal point iff >1 mantissa digit will be printed
|
||||
if exponent != trailing_zeros || added_precision != 0 {
|
||||
curr -= 1;
|
||||
// SAFETY: Safe since `40 > curr >= 0`
|
||||
unsafe {
|
||||
*buf_ptr.offset(curr) = b'.';
|
||||
}
|
||||
}
|
||||
|
||||
// SAFETY: Safe since `40 > curr >= 0`
|
||||
let buf_slice = unsafe {
|
||||
// decode last character
|
||||
curr -= 1;
|
||||
*buf_ptr.offset(curr) = (n as u8) + b'0';
|
||||
|
||||
let len = buf.len() - curr as usize;
|
||||
slice::from_raw_parts(buf_ptr.offset(curr), len)
|
||||
};
|
||||
|
||||
// stores 'e' (or 'E') and the up to 2-digit exponent
|
||||
let mut exp_buf = [MaybeUninit::<u8>::uninit(); 3];
|
||||
let exp_ptr = MaybeUninit::slice_as_mut_ptr(&mut exp_buf);
|
||||
// SAFETY: In either case, `exp_buf` is written within bounds and `exp_ptr[..len]`
|
||||
// is contained within `exp_buf` since `len <= 3`.
|
||||
let exp_slice = unsafe {
|
||||
*exp_ptr.offset(0) = if upper {b'E'} else {b'e'};
|
||||
let len = if exponent < 10 {
|
||||
*exp_ptr.offset(1) = (exponent as u8) + b'0';
|
||||
2
|
||||
} else {
|
||||
let off = exponent << 1;
|
||||
ptr::copy_nonoverlapping(lut_ptr.offset(off), exp_ptr.offset(1), 2);
|
||||
3
|
||||
};
|
||||
slice::from_raw_parts(exp_ptr, len)
|
||||
};
|
||||
|
||||
let parts = &[
|
||||
flt2dec::Part::Copy(buf_slice),
|
||||
flt2dec::Part::Zero(added_precision),
|
||||
flt2dec::Part::Copy(exp_slice)
|
||||
];
|
||||
let sign = if !is_nonnegative {
|
||||
"-"
|
||||
} else if f.sign_plus() {
|
||||
"+"
|
||||
} else {
|
||||
""
|
||||
};
|
||||
let formatted = flt2dec::Formatted{sign, parts};
|
||||
f.pad_formatted_parts(&formatted)
|
||||
}
|
||||
|
||||
$(
|
||||
#[stable(feature = "integer_exp_format", since = "1.42.0")]
|
||||
impl fmt::LowerExp for $t {
|
||||
#[allow(unused_comparisons)]
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let is_nonnegative = *self >= 0;
|
||||
let n = if is_nonnegative {
|
||||
self.$conv_fn()
|
||||
} else {
|
||||
// convert the negative num to positive by summing 1 to it's 2 complement
|
||||
(!self.$conv_fn()).wrapping_add(1)
|
||||
};
|
||||
$name(n, is_nonnegative, false, f)
|
||||
}
|
||||
})*
|
||||
$(
|
||||
#[stable(feature = "integer_exp_format", since = "1.42.0")]
|
||||
impl fmt::UpperExp for $t {
|
||||
#[allow(unused_comparisons)]
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let is_nonnegative = *self >= 0;
|
||||
let n = if is_nonnegative {
|
||||
self.$conv_fn()
|
||||
} else {
|
||||
// convert the negative num to positive by summing 1 to it's 2 complement
|
||||
(!self.$conv_fn()).wrapping_add(1)
|
||||
};
|
||||
$name(n, is_nonnegative, true, f)
|
||||
}
|
||||
})*
|
||||
};
|
||||
}
|
||||
|
||||
// Include wasm32 in here since it doesn't reflect the native pointer size, and
|
||||
// often cares strongly about getting a smaller code size.
|
||||
#[cfg(any(target_pointer_width = "64", target_arch = "wasm32"))]
|
||||
mod imp {
|
||||
use super::*;
|
||||
impl_Display!(
|
||||
i8, u8, i16, u16, i32, u32, i64, u64, usize, isize
|
||||
as u64 via to_u64 named fmt_u64
|
||||
);
|
||||
impl_Exp!(
|
||||
i8, u8, i16, u16, i32, u32, i64, u64, usize, isize
|
||||
as u64 via to_u64 named exp_u64
|
||||
);
|
||||
}
|
||||
|
||||
#[cfg(not(any(target_pointer_width = "64", target_arch = "wasm32")))]
|
||||
mod imp {
|
||||
use super::*;
|
||||
impl_Display!(i8, u8, i16, u16, i32, u32, isize, usize as u32 via to_u32 named fmt_u32);
|
||||
impl_Display!(i64, u64 as u64 via to_u64 named fmt_u64);
|
||||
impl_Exp!(i8, u8, i16, u16, i32, u32, isize, usize as u32 via to_u32 named exp_u32);
|
||||
impl_Exp!(i64, u64 as u64 via to_u64 named exp_u64);
|
||||
}
|
||||
impl_Exp!(i128, u128 as u128 via to_u128 named exp_u128);
|
||||
|
||||
/// Helper function for writing a u64 into `buf` going from last to first, with `curr`.
|
||||
fn parse_u64_into<const N: usize>(mut n: u64, buf: &mut [MaybeUninit<u8>; N], curr: &mut isize) {
|
||||
let buf_ptr = MaybeUninit::slice_as_mut_ptr(buf);
|
||||
let lut_ptr = DEC_DIGITS_LUT.as_ptr();
|
||||
assert!(*curr > 19);
|
||||
|
||||
// SAFETY:
|
||||
// Writes at most 19 characters into the buffer. Guaranteed that any ptr into LUT is at most
|
||||
// 198, so will never OOB. There is a check above that there are at least 19 characters
|
||||
// remaining.
|
||||
unsafe {
|
||||
if n >= 1e16 as u64 {
|
||||
let to_parse = n % 1e16 as u64;
|
||||
n /= 1e16 as u64;
|
||||
|
||||
// Some of these are nops but it looks more elegant this way.
|
||||
let d1 = ((to_parse / 1e14 as u64) % 100) << 1;
|
||||
let d2 = ((to_parse / 1e12 as u64) % 100) << 1;
|
||||
let d3 = ((to_parse / 1e10 as u64) % 100) << 1;
|
||||
let d4 = ((to_parse / 1e8 as u64) % 100) << 1;
|
||||
let d5 = ((to_parse / 1e6 as u64) % 100) << 1;
|
||||
let d6 = ((to_parse / 1e4 as u64) % 100) << 1;
|
||||
let d7 = ((to_parse / 1e2 as u64) % 100) << 1;
|
||||
let d8 = ((to_parse / 1e0 as u64) % 100) << 1;
|
||||
|
||||
*curr -= 16;
|
||||
|
||||
ptr::copy_nonoverlapping(lut_ptr.offset(d1 as isize), buf_ptr.offset(*curr + 0), 2);
|
||||
ptr::copy_nonoverlapping(lut_ptr.offset(d2 as isize), buf_ptr.offset(*curr + 2), 2);
|
||||
ptr::copy_nonoverlapping(lut_ptr.offset(d3 as isize), buf_ptr.offset(*curr + 4), 2);
|
||||
ptr::copy_nonoverlapping(lut_ptr.offset(d4 as isize), buf_ptr.offset(*curr + 6), 2);
|
||||
ptr::copy_nonoverlapping(lut_ptr.offset(d5 as isize), buf_ptr.offset(*curr + 8), 2);
|
||||
ptr::copy_nonoverlapping(lut_ptr.offset(d6 as isize), buf_ptr.offset(*curr + 10), 2);
|
||||
ptr::copy_nonoverlapping(lut_ptr.offset(d7 as isize), buf_ptr.offset(*curr + 12), 2);
|
||||
ptr::copy_nonoverlapping(lut_ptr.offset(d8 as isize), buf_ptr.offset(*curr + 14), 2);
|
||||
}
|
||||
if n >= 1e8 as u64 {
|
||||
let to_parse = n % 1e8 as u64;
|
||||
n /= 1e8 as u64;
|
||||
|
||||
// Some of these are nops but it looks more elegant this way.
|
||||
let d1 = ((to_parse / 1e6 as u64) % 100) << 1;
|
||||
let d2 = ((to_parse / 1e4 as u64) % 100) << 1;
|
||||
let d3 = ((to_parse / 1e2 as u64) % 100) << 1;
|
||||
let d4 = ((to_parse / 1e0 as u64) % 100) << 1;
|
||||
*curr -= 8;
|
||||
|
||||
ptr::copy_nonoverlapping(lut_ptr.offset(d1 as isize), buf_ptr.offset(*curr + 0), 2);
|
||||
ptr::copy_nonoverlapping(lut_ptr.offset(d2 as isize), buf_ptr.offset(*curr + 2), 2);
|
||||
ptr::copy_nonoverlapping(lut_ptr.offset(d3 as isize), buf_ptr.offset(*curr + 4), 2);
|
||||
ptr::copy_nonoverlapping(lut_ptr.offset(d4 as isize), buf_ptr.offset(*curr + 6), 2);
|
||||
}
|
||||
// `n` < 1e8 < (1 << 32)
|
||||
let mut n = n as u32;
|
||||
if n >= 1e4 as u32 {
|
||||
let to_parse = n % 1e4 as u32;
|
||||
n /= 1e4 as u32;
|
||||
|
||||
let d1 = (to_parse / 100) << 1;
|
||||
let d2 = (to_parse % 100) << 1;
|
||||
*curr -= 4;
|
||||
|
||||
ptr::copy_nonoverlapping(lut_ptr.offset(d1 as isize), buf_ptr.offset(*curr + 0), 2);
|
||||
ptr::copy_nonoverlapping(lut_ptr.offset(d2 as isize), buf_ptr.offset(*curr + 2), 2);
|
||||
}
|
||||
|
||||
// `n` < 1e4 < (1 << 16)
|
||||
let mut n = n as u16;
|
||||
if n >= 100 {
|
||||
let d1 = (n % 100) << 1;
|
||||
n /= 100;
|
||||
*curr -= 2;
|
||||
ptr::copy_nonoverlapping(lut_ptr.offset(d1 as isize), buf_ptr.offset(*curr), 2);
|
||||
}
|
||||
|
||||
// decode last 1 or 2 chars
|
||||
if n < 10 {
|
||||
*curr -= 1;
|
||||
*buf_ptr.offset(*curr) = (n as u8) + b'0';
|
||||
} else {
|
||||
let d1 = n << 1;
|
||||
*curr -= 2;
|
||||
ptr::copy_nonoverlapping(lut_ptr.offset(d1 as isize), buf_ptr.offset(*curr), 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl fmt::Display for u128 {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
fmt_u128(*self, true, f)
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl fmt::Display for i128 {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let is_nonnegative = *self >= 0;
|
||||
let n = if is_nonnegative {
|
||||
self.to_u128()
|
||||
} else {
|
||||
// convert the negative num to positive by summing 1 to it's 2 complement
|
||||
(!self.to_u128()).wrapping_add(1)
|
||||
};
|
||||
fmt_u128(n, is_nonnegative, f)
|
||||
}
|
||||
}
|
||||
|
||||
/// Specialized optimization for u128. Instead of taking two items at a time, it splits
|
||||
/// into at most 2 u64s, and then chunks by 10e16, 10e8, 10e4, 10e2, and then 10e1.
|
||||
/// It also has to handle 1 last item, as 10^40 > 2^128 > 10^39, whereas
|
||||
/// 10^20 > 2^64 > 10^19.
|
||||
fn fmt_u128(n: u128, is_nonnegative: bool, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
// 2^128 is about 3*10^38, so 39 gives an extra byte of space
|
||||
let mut buf = [MaybeUninit::<u8>::uninit(); 39];
|
||||
let mut curr = buf.len() as isize;
|
||||
|
||||
let (n, rem) = udiv_1e19(n);
|
||||
parse_u64_into(rem, &mut buf, &mut curr);
|
||||
|
||||
if n != 0 {
|
||||
// 0 pad up to point
|
||||
let target = (buf.len() - 19) as isize;
|
||||
// SAFETY: Guaranteed that we wrote at most 19 bytes, and there must be space
|
||||
// remaining since it has length 39
|
||||
unsafe {
|
||||
ptr::write_bytes(
|
||||
MaybeUninit::slice_as_mut_ptr(&mut buf).offset(target),
|
||||
b'0',
|
||||
(curr - target) as usize,
|
||||
);
|
||||
}
|
||||
curr = target;
|
||||
|
||||
let (n, rem) = udiv_1e19(n);
|
||||
parse_u64_into(rem, &mut buf, &mut curr);
|
||||
// Should this following branch be annotated with unlikely?
|
||||
if n != 0 {
|
||||
let target = (buf.len() - 38) as isize;
|
||||
// The raw `buf_ptr` pointer is only valid until `buf` is used the next time,
|
||||
// buf `buf` is not used in this scope so we are good.
|
||||
let buf_ptr = MaybeUninit::slice_as_mut_ptr(&mut buf);
|
||||
// SAFETY: At this point we wrote at most 38 bytes, pad up to that point,
|
||||
// There can only be at most 1 digit remaining.
|
||||
unsafe {
|
||||
ptr::write_bytes(buf_ptr.offset(target), b'0', (curr - target) as usize);
|
||||
curr = target - 1;
|
||||
*buf_ptr.offset(curr) = (n as u8) + b'0';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// SAFETY: `curr` > 0 (since we made `buf` large enough), and all the chars are valid
|
||||
// UTF-8 since `DEC_DIGITS_LUT` is
|
||||
let buf_slice = unsafe {
|
||||
str::from_utf8_unchecked(slice::from_raw_parts(
|
||||
MaybeUninit::slice_as_mut_ptr(&mut buf).offset(curr),
|
||||
buf.len() - curr as usize,
|
||||
))
|
||||
};
|
||||
f.pad_integral(is_nonnegative, "", buf_slice)
|
||||
}
|
||||
|
||||
/// Partition of `n` into n > 1e19 and rem <= 1e19
|
||||
fn udiv_1e19(n: u128) -> (u128, u64) {
|
||||
const DIV: u64 = 1e19 as u64;
|
||||
let high = (n >> 64) as u64;
|
||||
if high == 0 {
|
||||
let low = n as u64;
|
||||
return ((low / DIV) as u128, low % DIV);
|
||||
}
|
||||
let sr = 65 - high.leading_zeros();
|
||||
let mut q = n << (128 - sr);
|
||||
let mut r = n >> sr;
|
||||
let mut carry = 0;
|
||||
|
||||
for _ in 0..sr {
|
||||
r = (r << 1) | (q >> 127);
|
||||
q = (q << 1) | carry as u128;
|
||||
|
||||
let s = (DIV as u128).wrapping_sub(r).wrapping_sub(1) as i128 >> 127;
|
||||
carry = (s & 1) as u64;
|
||||
r -= (DIV as u128) & s as u128;
|
||||
}
|
||||
((q << 1) | carry as u128, r as u64)
|
||||
}
|
||||
45
libgrust/rustc-lib/core/src/fmt/rt/v1.rs
Normal file
45
libgrust/rustc-lib/core/src/fmt/rt/v1.rs
Normal file
@@ -0,0 +1,45 @@
|
||||
//! This is an internal module used by the ifmt! runtime. These structures are
|
||||
//! emitted to static arrays to precompile format strings ahead of time.
|
||||
//!
|
||||
//! These definitions are similar to their `ct` equivalents, but differ in that
|
||||
//! these can be statically allocated and are slightly optimized for the runtime
|
||||
#![allow(missing_debug_implementations)]
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct Argument {
|
||||
pub position: usize,
|
||||
pub format: FormatSpec,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct FormatSpec {
|
||||
pub fill: char,
|
||||
pub align: Alignment,
|
||||
pub flags: u32,
|
||||
pub precision: Count,
|
||||
pub width: Count,
|
||||
}
|
||||
|
||||
/// Possible alignments that can be requested as part of a formatting directive.
|
||||
#[derive(Copy, Clone, PartialEq, Eq)]
|
||||
pub enum Alignment {
|
||||
/// Indication that contents should be left-aligned.
|
||||
Left,
|
||||
/// Indication that contents should be right-aligned.
|
||||
Right,
|
||||
/// Indication that contents should be center-aligned.
|
||||
Center,
|
||||
/// No alignment was requested.
|
||||
Unknown,
|
||||
}
|
||||
|
||||
/// Used by [width](https://doc.rust-lang.org/std/fmt/#width) and [precision](https://doc.rust-lang.org/std/fmt/#precision) specifiers.
|
||||
#[derive(Copy, Clone)]
|
||||
pub enum Count {
|
||||
/// Specified with a literal number, stores the value
|
||||
Is(usize),
|
||||
/// Specified using `$` and `*` syntaxes, stores the index into `args`
|
||||
Param(usize),
|
||||
/// Not specified
|
||||
Implied,
|
||||
}
|
||||
121
libgrust/rustc-lib/core/src/future/future.rs
Normal file
121
libgrust/rustc-lib/core/src/future/future.rs
Normal file
@@ -0,0 +1,121 @@
|
||||
#![stable(feature = "futures_api", since = "1.36.0")]
|
||||
|
||||
use crate::marker::Unpin;
|
||||
use crate::ops;
|
||||
use crate::pin::Pin;
|
||||
use crate::task::{Context, Poll};
|
||||
|
||||
/// A future represents an asynchronous computation.
|
||||
///
|
||||
/// A future is a value that may not have finished computing yet. This kind of
|
||||
/// "asynchronous value" makes it possible for a thread to continue doing useful
|
||||
/// work while it waits for the value to become available.
|
||||
///
|
||||
/// # The `poll` method
|
||||
///
|
||||
/// The core method of future, `poll`, *attempts* to resolve the future into a
|
||||
/// final value. This method does not block if the value is not ready. Instead,
|
||||
/// the current task is scheduled to be woken up when it's possible to make
|
||||
/// further progress by `poll`ing again. The `context` passed to the `poll`
|
||||
/// method can provide a [`Waker`], which is a handle for waking up the current
|
||||
/// task.
|
||||
///
|
||||
/// When using a future, you generally won't call `poll` directly, but instead
|
||||
/// `.await` the value.
|
||||
///
|
||||
/// [`Waker`]: crate::task::Waker
|
||||
#[doc(spotlight)]
|
||||
#[must_use = "futures do nothing unless you `.await` or poll them"]
|
||||
#[stable(feature = "futures_api", since = "1.36.0")]
|
||||
#[lang = "future_trait"]
|
||||
#[rustc_on_unimplemented(label = "`{Self}` is not a future", message = "`{Self}` is not a future")]
|
||||
pub trait Future {
|
||||
/// The type of value produced on completion.
|
||||
#[stable(feature = "futures_api", since = "1.36.0")]
|
||||
type Output;
|
||||
|
||||
/// Attempt to resolve the future to a final value, registering
|
||||
/// the current task for wakeup if the value is not yet available.
|
||||
///
|
||||
/// # Return value
|
||||
///
|
||||
/// This function returns:
|
||||
///
|
||||
/// - [`Poll::Pending`] if the future is not ready yet
|
||||
/// - [`Poll::Ready(val)`] with the result `val` of this future if it
|
||||
/// finished successfully.
|
||||
///
|
||||
/// Once a future has finished, clients should not `poll` it again.
|
||||
///
|
||||
/// When a future is not ready yet, `poll` returns `Poll::Pending` and
|
||||
/// stores a clone of the [`Waker`] copied from the current [`Context`].
|
||||
/// This [`Waker`] is then woken once the future can make progress.
|
||||
/// For example, a future waiting for a socket to become
|
||||
/// readable would call `.clone()` on the [`Waker`] and store it.
|
||||
/// When a signal arrives elsewhere indicating that the socket is readable,
|
||||
/// [`Waker::wake`] is called and the socket future's task is awoken.
|
||||
/// Once a task has been woken up, it should attempt to `poll` the future
|
||||
/// again, which may or may not produce a final value.
|
||||
///
|
||||
/// Note that on multiple calls to `poll`, only the [`Waker`] from the
|
||||
/// [`Context`] passed to the most recent call should be scheduled to
|
||||
/// receive a wakeup.
|
||||
///
|
||||
/// # Runtime characteristics
|
||||
///
|
||||
/// Futures alone are *inert*; they must be *actively* `poll`ed to make
|
||||
/// progress, meaning that each time the current task is woken up, it should
|
||||
/// actively re-`poll` pending futures that it still has an interest in.
|
||||
///
|
||||
/// The `poll` function is not called repeatedly in a tight loop -- instead,
|
||||
/// it should only be called when the future indicates that it is ready to
|
||||
/// make progress (by calling `wake()`). If you're familiar with the
|
||||
/// `poll(2)` or `select(2)` syscalls on Unix it's worth noting that futures
|
||||
/// typically do *not* suffer the same problems of "all wakeups must poll
|
||||
/// all events"; they are more like `epoll(4)`.
|
||||
///
|
||||
/// An implementation of `poll` should strive to return quickly, and should
|
||||
/// not block. Returning quickly prevents unnecessarily clogging up
|
||||
/// threads or event loops. If it is known ahead of time that a call to
|
||||
/// `poll` may end up taking awhile, the work should be offloaded to a
|
||||
/// thread pool (or something similar) to ensure that `poll` can return
|
||||
/// quickly.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Once a future has completed (returned `Ready` from `poll`), calling its
|
||||
/// `poll` method again may panic, block forever, or cause other kinds of
|
||||
/// problems; the `Future` trait places no requirements on the effects of
|
||||
/// such a call. However, as the `poll` method is not marked `unsafe`,
|
||||
/// Rust's usual rules apply: calls must never cause undefined behavior
|
||||
/// (memory corruption, incorrect use of `unsafe` functions, or the like),
|
||||
/// regardless of the future's state.
|
||||
///
|
||||
/// [`Poll::Ready(val)`]: Poll::Ready
|
||||
/// [`Waker`]: crate::task::Waker
|
||||
/// [`Waker::wake`]: crate::task::Waker::wake
|
||||
#[lang = "poll"]
|
||||
#[stable(feature = "futures_api", since = "1.36.0")]
|
||||
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output>;
|
||||
}
|
||||
|
||||
#[stable(feature = "futures_api", since = "1.36.0")]
|
||||
impl<F: ?Sized + Future + Unpin> Future for &mut F {
|
||||
type Output = F::Output;
|
||||
|
||||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
F::poll(Pin::new(&mut **self), cx)
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "futures_api", since = "1.36.0")]
|
||||
impl<P> Future for Pin<P>
|
||||
where
|
||||
P: Unpin + ops::DerefMut<Target: Future>,
|
||||
{
|
||||
type Output = <<P as ops::Deref>::Target as Future>::Output;
|
||||
|
||||
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
Pin::get_mut(self).as_mut().poll(cx)
|
||||
}
|
||||
}
|
||||
27
libgrust/rustc-lib/core/src/future/into_future.rs
Normal file
27
libgrust/rustc-lib/core/src/future/into_future.rs
Normal file
@@ -0,0 +1,27 @@
|
||||
use crate::future::Future;
|
||||
|
||||
/// Conversion into a `Future`.
|
||||
#[unstable(feature = "into_future", issue = "67644")]
|
||||
pub trait IntoFuture {
|
||||
/// The output that the future will produce on completion.
|
||||
#[unstable(feature = "into_future", issue = "67644")]
|
||||
type Output;
|
||||
|
||||
/// Which kind of future are we turning this into?
|
||||
#[unstable(feature = "into_future", issue = "67644")]
|
||||
type Future: Future<Output = Self::Output>;
|
||||
|
||||
/// Creates a future from a value.
|
||||
#[unstable(feature = "into_future", issue = "67644")]
|
||||
fn into_future(self) -> Self::Future;
|
||||
}
|
||||
|
||||
#[unstable(feature = "into_future", issue = "67644")]
|
||||
impl<F: Future> IntoFuture for F {
|
||||
type Output = F::Output;
|
||||
type Future = F;
|
||||
|
||||
fn into_future(self) -> Self::Future {
|
||||
self
|
||||
}
|
||||
}
|
||||
98
libgrust/rustc-lib/core/src/future/mod.rs
Normal file
98
libgrust/rustc-lib/core/src/future/mod.rs
Normal file
@@ -0,0 +1,98 @@
|
||||
#![stable(feature = "futures_api", since = "1.36.0")]
|
||||
|
||||
//! Asynchronous values.
|
||||
|
||||
use crate::{
|
||||
ops::{Generator, GeneratorState},
|
||||
pin::Pin,
|
||||
ptr::NonNull,
|
||||
task::{Context, Poll},
|
||||
};
|
||||
|
||||
mod future;
|
||||
mod into_future;
|
||||
mod pending;
|
||||
mod poll_fn;
|
||||
mod ready;
|
||||
|
||||
#[stable(feature = "futures_api", since = "1.36.0")]
|
||||
pub use self::future::Future;
|
||||
|
||||
#[unstable(feature = "into_future", issue = "67644")]
|
||||
pub use into_future::IntoFuture;
|
||||
|
||||
#[stable(feature = "future_readiness_fns", since = "1.48.0")]
|
||||
pub use pending::{pending, Pending};
|
||||
#[stable(feature = "future_readiness_fns", since = "1.48.0")]
|
||||
pub use ready::{ready, Ready};
|
||||
|
||||
#[unstable(feature = "future_poll_fn", issue = "72302")]
|
||||
pub use poll_fn::{poll_fn, PollFn};
|
||||
|
||||
/// This type is needed because:
|
||||
///
|
||||
/// a) Generators cannot implement `for<'a, 'b> Generator<&'a mut Context<'b>>`, so we need to pass
|
||||
/// a raw pointer (see <https://github.com/rust-lang/rust/issues/68923>).
|
||||
/// b) Raw pointers and `NonNull` aren't `Send` or `Sync`, so that would make every single future
|
||||
/// non-Send/Sync as well, and we don't want that.
|
||||
///
|
||||
/// It also simplifies the HIR lowering of `.await`.
|
||||
#[doc(hidden)]
|
||||
#[unstable(feature = "gen_future", issue = "50547")]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub struct ResumeTy(NonNull<Context<'static>>);
|
||||
|
||||
#[unstable(feature = "gen_future", issue = "50547")]
|
||||
unsafe impl Send for ResumeTy {}
|
||||
|
||||
#[unstable(feature = "gen_future", issue = "50547")]
|
||||
unsafe impl Sync for ResumeTy {}
|
||||
|
||||
/// Wrap a generator in a future.
|
||||
///
|
||||
/// This function returns a `GenFuture` underneath, but hides it in `impl Trait` to give
|
||||
/// better error messages (`impl Future` rather than `GenFuture<[closure.....]>`).
|
||||
// This is `const` to avoid extra errors after we recover from `const async fn`
|
||||
#[lang = "from_generator"]
|
||||
#[doc(hidden)]
|
||||
#[unstable(feature = "gen_future", issue = "50547")]
|
||||
#[rustc_const_unstable(feature = "gen_future", issue = "50547")]
|
||||
#[inline]
|
||||
pub const fn from_generator<T>(gen: T) -> impl Future<Output = T::Return>
|
||||
where
|
||||
T: Generator<ResumeTy, Yield = ()>,
|
||||
{
|
||||
#[rustc_diagnostic_item = "gen_future"]
|
||||
struct GenFuture<T: Generator<ResumeTy, Yield = ()>>(T);
|
||||
|
||||
// We rely on the fact that async/await futures are immovable in order to create
|
||||
// self-referential borrows in the underlying generator.
|
||||
impl<T: Generator<ResumeTy, Yield = ()>> !Unpin for GenFuture<T> {}
|
||||
|
||||
impl<T: Generator<ResumeTy, Yield = ()>> Future for GenFuture<T> {
|
||||
type Output = T::Return;
|
||||
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
// SAFETY: Safe because we're !Unpin + !Drop, and this is just a field projection.
|
||||
let gen = unsafe { Pin::map_unchecked_mut(self, |s| &mut s.0) };
|
||||
|
||||
// Resume the generator, turning the `&mut Context` into a `NonNull` raw pointer. The
|
||||
// `.await` lowering will safely cast that back to a `&mut Context`.
|
||||
match gen.resume(ResumeTy(NonNull::from(cx).cast::<Context<'static>>())) {
|
||||
GeneratorState::Yielded(()) => Poll::Pending,
|
||||
GeneratorState::Complete(x) => Poll::Ready(x),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
GenFuture(gen)
|
||||
}
|
||||
|
||||
#[lang = "get_context"]
|
||||
#[doc(hidden)]
|
||||
#[unstable(feature = "gen_future", issue = "50547")]
|
||||
#[inline]
|
||||
pub unsafe fn get_context<'a, 'b>(cx: ResumeTy) -> &'a mut Context<'b> {
|
||||
// SAFETY: the caller must guarantee that `cx.0` is a valid pointer
|
||||
// that fulfills all the requirements for a mutable reference.
|
||||
unsafe { &mut *cx.0.as_ptr().cast() }
|
||||
}
|
||||
61
libgrust/rustc-lib/core/src/future/pending.rs
Normal file
61
libgrust/rustc-lib/core/src/future/pending.rs
Normal file
@@ -0,0 +1,61 @@
|
||||
use crate::fmt::{self, Debug};
|
||||
use crate::future::Future;
|
||||
use crate::marker;
|
||||
use crate::pin::Pin;
|
||||
use crate::task::{Context, Poll};
|
||||
|
||||
/// Creates a future which never resolves, representing a computation that never
|
||||
/// finishes.
|
||||
///
|
||||
/// This `struct` is created by [`pending()`]. See its
|
||||
/// documentation for more.
|
||||
#[stable(feature = "future_readiness_fns", since = "1.48.0")]
|
||||
#[must_use = "futures do nothing unless you `.await` or poll them"]
|
||||
pub struct Pending<T> {
|
||||
_data: marker::PhantomData<T>,
|
||||
}
|
||||
|
||||
/// Creates a future which never resolves, representing a computation that never
|
||||
/// finishes.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use core::future;
|
||||
///
|
||||
/// # async fn run() {
|
||||
/// let future = future::pending();
|
||||
/// let () = future.await;
|
||||
/// unreachable!();
|
||||
/// # }
|
||||
/// ```
|
||||
#[stable(feature = "future_readiness_fns", since = "1.48.0")]
|
||||
pub fn pending<T>() -> Pending<T> {
|
||||
Pending { _data: marker::PhantomData }
|
||||
}
|
||||
|
||||
#[stable(feature = "future_readiness_fns", since = "1.48.0")]
|
||||
impl<T> Future for Pending<T> {
|
||||
type Output = T;
|
||||
|
||||
fn poll(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<T> {
|
||||
Poll::Pending
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "future_readiness_fns", since = "1.48.0")]
|
||||
impl<T> Unpin for Pending<T> {}
|
||||
|
||||
#[stable(feature = "future_readiness_fns", since = "1.48.0")]
|
||||
impl<T> Debug for Pending<T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("Pending").finish()
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "future_readiness_fns", since = "1.48.0")]
|
||||
impl<T> Clone for Pending<T> {
|
||||
fn clone(&self) -> Self {
|
||||
pending()
|
||||
}
|
||||
}
|
||||
64
libgrust/rustc-lib/core/src/future/poll_fn.rs
Normal file
64
libgrust/rustc-lib/core/src/future/poll_fn.rs
Normal file
@@ -0,0 +1,64 @@
|
||||
use crate::fmt;
|
||||
use crate::future::Future;
|
||||
use crate::pin::Pin;
|
||||
use crate::task::{Context, Poll};
|
||||
|
||||
/// Creates a future that wraps a function returning `Poll`.
|
||||
///
|
||||
/// Polling the future delegates to the wrapped function.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(future_poll_fn)]
|
||||
/// # async fn run() {
|
||||
/// use core::future::poll_fn;
|
||||
/// use core::task::{Context, Poll};
|
||||
///
|
||||
/// fn read_line(_cx: &mut Context<'_>) -> Poll<String> {
|
||||
/// Poll::Ready("Hello, World!".into())
|
||||
/// }
|
||||
///
|
||||
/// let read_future = poll_fn(read_line);
|
||||
/// assert_eq!(read_future.await, "Hello, World!".to_owned());
|
||||
/// # };
|
||||
/// ```
|
||||
#[unstable(feature = "future_poll_fn", issue = "72302")]
|
||||
pub fn poll_fn<T, F>(f: F) -> PollFn<F>
|
||||
where
|
||||
F: FnMut(&mut Context<'_>) -> Poll<T>,
|
||||
{
|
||||
PollFn { f }
|
||||
}
|
||||
|
||||
/// A Future that wraps a function returning `Poll`.
|
||||
///
|
||||
/// This `struct` is created by [`poll_fn()`]. See its
|
||||
/// documentation for more.
|
||||
#[must_use = "futures do nothing unless you `.await` or poll them"]
|
||||
#[unstable(feature = "future_poll_fn", issue = "72302")]
|
||||
pub struct PollFn<F> {
|
||||
f: F,
|
||||
}
|
||||
|
||||
#[unstable(feature = "future_poll_fn", issue = "72302")]
|
||||
impl<F> Unpin for PollFn<F> {}
|
||||
|
||||
#[unstable(feature = "future_poll_fn", issue = "72302")]
|
||||
impl<F> fmt::Debug for PollFn<F> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("PollFn").finish()
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "future_poll_fn", issue = "72302")]
|
||||
impl<T, F> Future for PollFn<F>
|
||||
where
|
||||
F: FnMut(&mut Context<'_>) -> Poll<T>,
|
||||
{
|
||||
type Output = T;
|
||||
|
||||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<T> {
|
||||
(&mut self.f)(cx)
|
||||
}
|
||||
}
|
||||
46
libgrust/rustc-lib/core/src/future/ready.rs
Normal file
46
libgrust/rustc-lib/core/src/future/ready.rs
Normal file
@@ -0,0 +1,46 @@
|
||||
use crate::future::Future;
|
||||
use crate::pin::Pin;
|
||||
use crate::task::{Context, Poll};
|
||||
|
||||
/// Creates a future that is immediately ready with a value.
|
||||
///
|
||||
/// This `struct` is created by [`ready()`]. See its
|
||||
/// documentation for more.
|
||||
#[stable(feature = "future_readiness_fns", since = "1.48.0")]
|
||||
#[derive(Debug, Clone)]
|
||||
#[must_use = "futures do nothing unless you `.await` or poll them"]
|
||||
pub struct Ready<T>(Option<T>);
|
||||
|
||||
#[stable(feature = "future_readiness_fns", since = "1.48.0")]
|
||||
impl<T> Unpin for Ready<T> {}
|
||||
|
||||
#[stable(feature = "future_readiness_fns", since = "1.48.0")]
|
||||
impl<T> Future for Ready<T> {
|
||||
type Output = T;
|
||||
|
||||
#[inline]
|
||||
fn poll(mut self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<T> {
|
||||
Poll::Ready(self.0.take().expect("Ready polled after completion"))
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a future that is immediately ready with a value.
|
||||
///
|
||||
/// Futures created through this function are functionally similar to those
|
||||
/// created through `async {}`. The main difference is that futures created
|
||||
/// through this function are named and implement `Unpin`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use core::future;
|
||||
///
|
||||
/// # async fn run() {
|
||||
/// let a = future::ready(1);
|
||||
/// assert_eq!(a.await, 1);
|
||||
/// # }
|
||||
/// ```
|
||||
#[stable(feature = "future_readiness_fns", since = "1.48.0")]
|
||||
pub fn ready<T>(t: T) -> Ready<T> {
|
||||
Ready(Some(t))
|
||||
}
|
||||
712
libgrust/rustc-lib/core/src/hash/mod.rs
Normal file
712
libgrust/rustc-lib/core/src/hash/mod.rs
Normal file
@@ -0,0 +1,712 @@
|
||||
//! Generic hashing support.
|
||||
//!
|
||||
//! This module provides a generic way to compute the hash of a value. The
|
||||
//! simplest way to make a type hashable is to use `#[derive(Hash)]`:
|
||||
//!
|
||||
//! # Examples
|
||||
//!
|
||||
//! ```rust
|
||||
//! use std::collections::hash_map::DefaultHasher;
|
||||
//! use std::hash::{Hash, Hasher};
|
||||
//!
|
||||
//! #[derive(Hash)]
|
||||
//! struct Person {
|
||||
//! id: u32,
|
||||
//! name: String,
|
||||
//! phone: u64,
|
||||
//! }
|
||||
//!
|
||||
//! let person1 = Person {
|
||||
//! id: 5,
|
||||
//! name: "Janet".to_string(),
|
||||
//! phone: 555_666_7777,
|
||||
//! };
|
||||
//! let person2 = Person {
|
||||
//! id: 5,
|
||||
//! name: "Bob".to_string(),
|
||||
//! phone: 555_666_7777,
|
||||
//! };
|
||||
//!
|
||||
//! assert!(calculate_hash(&person1) != calculate_hash(&person2));
|
||||
//!
|
||||
//! fn calculate_hash<T: Hash>(t: &T) -> u64 {
|
||||
//! let mut s = DefaultHasher::new();
|
||||
//! t.hash(&mut s);
|
||||
//! s.finish()
|
||||
//! }
|
||||
//! ```
|
||||
//!
|
||||
//! If you need more control over how a value is hashed, you need to implement
|
||||
//! the [`Hash`] trait:
|
||||
//!
|
||||
//! ```rust
|
||||
//! use std::collections::hash_map::DefaultHasher;
|
||||
//! use std::hash::{Hash, Hasher};
|
||||
//!
|
||||
//! struct Person {
|
||||
//! id: u32,
|
||||
//! # #[allow(dead_code)]
|
||||
//! name: String,
|
||||
//! phone: u64,
|
||||
//! }
|
||||
//!
|
||||
//! impl Hash for Person {
|
||||
//! fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
//! self.id.hash(state);
|
||||
//! self.phone.hash(state);
|
||||
//! }
|
||||
//! }
|
||||
//!
|
||||
//! let person1 = Person {
|
||||
//! id: 5,
|
||||
//! name: "Janet".to_string(),
|
||||
//! phone: 555_666_7777,
|
||||
//! };
|
||||
//! let person2 = Person {
|
||||
//! id: 5,
|
||||
//! name: "Bob".to_string(),
|
||||
//! phone: 555_666_7777,
|
||||
//! };
|
||||
//!
|
||||
//! assert_eq!(calculate_hash(&person1), calculate_hash(&person2));
|
||||
//!
|
||||
//! fn calculate_hash<T: Hash>(t: &T) -> u64 {
|
||||
//! let mut s = DefaultHasher::new();
|
||||
//! t.hash(&mut s);
|
||||
//! s.finish()
|
||||
//! }
|
||||
//! ```
|
||||
|
||||
#![stable(feature = "rust1", since = "1.0.0")]
|
||||
|
||||
use crate::fmt;
|
||||
use crate::marker;
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[allow(deprecated)]
|
||||
pub use self::sip::SipHasher;
|
||||
|
||||
#[unstable(feature = "hashmap_internals", issue = "none")]
|
||||
#[allow(deprecated)]
|
||||
#[doc(hidden)]
|
||||
pub use self::sip::SipHasher13;
|
||||
|
||||
mod sip;
|
||||
|
||||
/// A hashable type.
|
||||
///
|
||||
/// Types implementing `Hash` are able to be [`hash`]ed with an instance of
|
||||
/// [`Hasher`].
|
||||
///
|
||||
/// ## Implementing `Hash`
|
||||
///
|
||||
/// You can derive `Hash` with `#[derive(Hash)]` if all fields implement `Hash`.
|
||||
/// The resulting hash will be the combination of the values from calling
|
||||
/// [`hash`] on each field.
|
||||
///
|
||||
/// ```
|
||||
/// #[derive(Hash)]
|
||||
/// struct Rustacean {
|
||||
/// name: String,
|
||||
/// country: String,
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// If you need more control over how a value is hashed, you can of course
|
||||
/// implement the `Hash` trait yourself:
|
||||
///
|
||||
/// ```
|
||||
/// use std::hash::{Hash, Hasher};
|
||||
///
|
||||
/// struct Person {
|
||||
/// id: u32,
|
||||
/// name: String,
|
||||
/// phone: u64,
|
||||
/// }
|
||||
///
|
||||
/// impl Hash for Person {
|
||||
/// fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
/// self.id.hash(state);
|
||||
/// self.phone.hash(state);
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// ## `Hash` and `Eq`
|
||||
///
|
||||
/// When implementing both `Hash` and [`Eq`], it is important that the following
|
||||
/// property holds:
|
||||
///
|
||||
/// ```text
|
||||
/// k1 == k2 -> hash(k1) == hash(k2)
|
||||
/// ```
|
||||
///
|
||||
/// In other words, if two keys are equal, their hashes must also be equal.
|
||||
/// [`HashMap`] and [`HashSet`] both rely on this behavior.
|
||||
///
|
||||
/// Thankfully, you won't need to worry about upholding this property when
|
||||
/// deriving both [`Eq`] and `Hash` with `#[derive(PartialEq, Eq, Hash)]`.
|
||||
///
|
||||
/// [`HashMap`]: ../../std/collections/struct.HashMap.html
|
||||
/// [`HashSet`]: ../../std/collections/struct.HashSet.html
|
||||
/// [`hash`]: Hash::hash
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub trait Hash {
|
||||
/// Feeds this value into the given [`Hasher`].
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::collections::hash_map::DefaultHasher;
|
||||
/// use std::hash::{Hash, Hasher};
|
||||
///
|
||||
/// let mut hasher = DefaultHasher::new();
|
||||
/// 7920.hash(&mut hasher);
|
||||
/// println!("Hash is {:x}!", hasher.finish());
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
fn hash<H: Hasher>(&self, state: &mut H);
|
||||
|
||||
/// Feeds a slice of this type into the given [`Hasher`].
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::collections::hash_map::DefaultHasher;
|
||||
/// use std::hash::{Hash, Hasher};
|
||||
///
|
||||
/// let mut hasher = DefaultHasher::new();
|
||||
/// let numbers = [6, 28, 496, 8128];
|
||||
/// Hash::hash_slice(&numbers, &mut hasher);
|
||||
/// println!("Hash is {:x}!", hasher.finish());
|
||||
/// ```
|
||||
#[stable(feature = "hash_slice", since = "1.3.0")]
|
||||
fn hash_slice<H: Hasher>(data: &[Self], state: &mut H)
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
for piece in data {
|
||||
piece.hash(state);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Separate module to reexport the macro `Hash` from prelude without the trait `Hash`.
|
||||
pub(crate) mod macros {
|
||||
/// Derive macro generating an impl of the trait `Hash`.
|
||||
#[rustc_builtin_macro]
|
||||
#[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
|
||||
#[allow_internal_unstable(core_intrinsics)]
|
||||
pub macro Hash($item:item) {
|
||||
/* compiler built-in */
|
||||
}
|
||||
}
|
||||
#[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
|
||||
#[doc(inline)]
|
||||
pub use macros::Hash;
|
||||
|
||||
/// A trait for hashing an arbitrary stream of bytes.
|
||||
///
|
||||
/// Instances of `Hasher` usually represent state that is changed while hashing
|
||||
/// data.
|
||||
///
|
||||
/// `Hasher` provides a fairly basic interface for retrieving the generated hash
|
||||
/// (with [`finish`]), and writing integers as well as slices of bytes into an
|
||||
/// instance (with [`write`] and [`write_u8`] etc.). Most of the time, `Hasher`
|
||||
/// instances are used in conjunction with the [`Hash`] trait.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::collections::hash_map::DefaultHasher;
|
||||
/// use std::hash::Hasher;
|
||||
///
|
||||
/// let mut hasher = DefaultHasher::new();
|
||||
///
|
||||
/// hasher.write_u32(1989);
|
||||
/// hasher.write_u8(11);
|
||||
/// hasher.write_u8(9);
|
||||
/// hasher.write(b"Huh?");
|
||||
///
|
||||
/// println!("Hash is {:x}!", hasher.finish());
|
||||
/// ```
|
||||
///
|
||||
/// [`finish`]: Hasher::finish
|
||||
/// [`write`]: Hasher::write
|
||||
/// [`write_u8`]: Hasher::write_u8
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub trait Hasher {
|
||||
/// Returns the hash value for the values written so far.
|
||||
///
|
||||
/// Despite its name, the method does not reset the hasher’s internal
|
||||
/// state. Additional [`write`]s will continue from the current value.
|
||||
/// If you need to start a fresh hash value, you will have to create
|
||||
/// a new hasher.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::collections::hash_map::DefaultHasher;
|
||||
/// use std::hash::Hasher;
|
||||
///
|
||||
/// let mut hasher = DefaultHasher::new();
|
||||
/// hasher.write(b"Cool!");
|
||||
///
|
||||
/// println!("Hash is {:x}!", hasher.finish());
|
||||
/// ```
|
||||
///
|
||||
/// [`write`]: Hasher::write
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
fn finish(&self) -> u64;
|
||||
|
||||
/// Writes some data into this `Hasher`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::collections::hash_map::DefaultHasher;
|
||||
/// use std::hash::Hasher;
|
||||
///
|
||||
/// let mut hasher = DefaultHasher::new();
|
||||
/// let data = [0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef];
|
||||
///
|
||||
/// hasher.write(&data);
|
||||
///
|
||||
/// println!("Hash is {:x}!", hasher.finish());
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
fn write(&mut self, bytes: &[u8]);
|
||||
|
||||
/// Writes a single `u8` into this hasher.
|
||||
#[inline]
|
||||
#[stable(feature = "hasher_write", since = "1.3.0")]
|
||||
fn write_u8(&mut self, i: u8) {
|
||||
self.write(&[i])
|
||||
}
|
||||
/// Writes a single `u16` into this hasher.
|
||||
#[inline]
|
||||
#[stable(feature = "hasher_write", since = "1.3.0")]
|
||||
fn write_u16(&mut self, i: u16) {
|
||||
self.write(&i.to_ne_bytes())
|
||||
}
|
||||
/// Writes a single `u32` into this hasher.
|
||||
#[inline]
|
||||
#[stable(feature = "hasher_write", since = "1.3.0")]
|
||||
fn write_u32(&mut self, i: u32) {
|
||||
self.write(&i.to_ne_bytes())
|
||||
}
|
||||
/// Writes a single `u64` into this hasher.
|
||||
#[inline]
|
||||
#[stable(feature = "hasher_write", since = "1.3.0")]
|
||||
fn write_u64(&mut self, i: u64) {
|
||||
self.write(&i.to_ne_bytes())
|
||||
}
|
||||
/// Writes a single `u128` into this hasher.
|
||||
#[inline]
|
||||
#[stable(feature = "i128", since = "1.26.0")]
|
||||
fn write_u128(&mut self, i: u128) {
|
||||
self.write(&i.to_ne_bytes())
|
||||
}
|
||||
/// Writes a single `usize` into this hasher.
|
||||
#[inline]
|
||||
#[stable(feature = "hasher_write", since = "1.3.0")]
|
||||
fn write_usize(&mut self, i: usize) {
|
||||
self.write(&i.to_ne_bytes())
|
||||
}
|
||||
|
||||
/// Writes a single `i8` into this hasher.
|
||||
#[inline]
|
||||
#[stable(feature = "hasher_write", since = "1.3.0")]
|
||||
fn write_i8(&mut self, i: i8) {
|
||||
self.write_u8(i as u8)
|
||||
}
|
||||
/// Writes a single `i16` into this hasher.
|
||||
#[inline]
|
||||
#[stable(feature = "hasher_write", since = "1.3.0")]
|
||||
fn write_i16(&mut self, i: i16) {
|
||||
self.write_u16(i as u16)
|
||||
}
|
||||
/// Writes a single `i32` into this hasher.
|
||||
#[inline]
|
||||
#[stable(feature = "hasher_write", since = "1.3.0")]
|
||||
fn write_i32(&mut self, i: i32) {
|
||||
self.write_u32(i as u32)
|
||||
}
|
||||
/// Writes a single `i64` into this hasher.
|
||||
#[inline]
|
||||
#[stable(feature = "hasher_write", since = "1.3.0")]
|
||||
fn write_i64(&mut self, i: i64) {
|
||||
self.write_u64(i as u64)
|
||||
}
|
||||
/// Writes a single `i128` into this hasher.
|
||||
#[inline]
|
||||
#[stable(feature = "i128", since = "1.26.0")]
|
||||
fn write_i128(&mut self, i: i128) {
|
||||
self.write_u128(i as u128)
|
||||
}
|
||||
/// Writes a single `isize` into this hasher.
|
||||
#[inline]
|
||||
#[stable(feature = "hasher_write", since = "1.3.0")]
|
||||
fn write_isize(&mut self, i: isize) {
|
||||
self.write_usize(i as usize)
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "indirect_hasher_impl", since = "1.22.0")]
|
||||
impl<H: Hasher + ?Sized> Hasher for &mut H {
|
||||
fn finish(&self) -> u64 {
|
||||
(**self).finish()
|
||||
}
|
||||
fn write(&mut self, bytes: &[u8]) {
|
||||
(**self).write(bytes)
|
||||
}
|
||||
fn write_u8(&mut self, i: u8) {
|
||||
(**self).write_u8(i)
|
||||
}
|
||||
fn write_u16(&mut self, i: u16) {
|
||||
(**self).write_u16(i)
|
||||
}
|
||||
fn write_u32(&mut self, i: u32) {
|
||||
(**self).write_u32(i)
|
||||
}
|
||||
fn write_u64(&mut self, i: u64) {
|
||||
(**self).write_u64(i)
|
||||
}
|
||||
fn write_u128(&mut self, i: u128) {
|
||||
(**self).write_u128(i)
|
||||
}
|
||||
fn write_usize(&mut self, i: usize) {
|
||||
(**self).write_usize(i)
|
||||
}
|
||||
fn write_i8(&mut self, i: i8) {
|
||||
(**self).write_i8(i)
|
||||
}
|
||||
fn write_i16(&mut self, i: i16) {
|
||||
(**self).write_i16(i)
|
||||
}
|
||||
fn write_i32(&mut self, i: i32) {
|
||||
(**self).write_i32(i)
|
||||
}
|
||||
fn write_i64(&mut self, i: i64) {
|
||||
(**self).write_i64(i)
|
||||
}
|
||||
fn write_i128(&mut self, i: i128) {
|
||||
(**self).write_i128(i)
|
||||
}
|
||||
fn write_isize(&mut self, i: isize) {
|
||||
(**self).write_isize(i)
|
||||
}
|
||||
}
|
||||
|
||||
/// A trait for creating instances of [`Hasher`].
|
||||
///
|
||||
/// A `BuildHasher` is typically used (e.g., by [`HashMap`]) to create
|
||||
/// [`Hasher`]s for each key such that they are hashed independently of one
|
||||
/// another, since [`Hasher`]s contain state.
|
||||
///
|
||||
/// For each instance of `BuildHasher`, the [`Hasher`]s created by
|
||||
/// [`build_hasher`] should be identical. That is, if the same stream of bytes
|
||||
/// is fed into each hasher, the same output will also be generated.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::collections::hash_map::RandomState;
|
||||
/// use std::hash::{BuildHasher, Hasher};
|
||||
///
|
||||
/// let s = RandomState::new();
|
||||
/// let mut hasher_1 = s.build_hasher();
|
||||
/// let mut hasher_2 = s.build_hasher();
|
||||
///
|
||||
/// hasher_1.write_u32(8128);
|
||||
/// hasher_2.write_u32(8128);
|
||||
///
|
||||
/// assert_eq!(hasher_1.finish(), hasher_2.finish());
|
||||
/// ```
|
||||
///
|
||||
/// [`build_hasher`]: BuildHasher::build_hasher
|
||||
/// [`HashMap`]: ../../std/collections/struct.HashMap.html
|
||||
#[stable(since = "1.7.0", feature = "build_hasher")]
|
||||
pub trait BuildHasher {
|
||||
/// Type of the hasher that will be created.
|
||||
#[stable(since = "1.7.0", feature = "build_hasher")]
|
||||
type Hasher: Hasher;
|
||||
|
||||
/// Creates a new hasher.
|
||||
///
|
||||
/// Each call to `build_hasher` on the same instance should produce identical
|
||||
/// [`Hasher`]s.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::collections::hash_map::RandomState;
|
||||
/// use std::hash::BuildHasher;
|
||||
///
|
||||
/// let s = RandomState::new();
|
||||
/// let new_s = s.build_hasher();
|
||||
/// ```
|
||||
#[stable(since = "1.7.0", feature = "build_hasher")]
|
||||
fn build_hasher(&self) -> Self::Hasher;
|
||||
}
|
||||
|
||||
/// Used to create a default [`BuildHasher`] instance for types that implement
|
||||
/// [`Hasher`] and [`Default`].
|
||||
///
|
||||
/// `BuildHasherDefault<H>` can be used when a type `H` implements [`Hasher`] and
|
||||
/// [`Default`], and you need a corresponding [`BuildHasher`] instance, but none is
|
||||
/// defined.
|
||||
///
|
||||
/// Any `BuildHasherDefault` is [zero-sized]. It can be created with
|
||||
/// [`default`][method.default]. When using `BuildHasherDefault` with [`HashMap`] or
|
||||
/// [`HashSet`], this doesn't need to be done, since they implement appropriate
|
||||
/// [`Default`] instances themselves.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Using `BuildHasherDefault` to specify a custom [`BuildHasher`] for
|
||||
/// [`HashMap`]:
|
||||
///
|
||||
/// ```
|
||||
/// use std::collections::HashMap;
|
||||
/// use std::hash::{BuildHasherDefault, Hasher};
|
||||
///
|
||||
/// #[derive(Default)]
|
||||
/// struct MyHasher;
|
||||
///
|
||||
/// impl Hasher for MyHasher {
|
||||
/// fn write(&mut self, bytes: &[u8]) {
|
||||
/// // Your hashing algorithm goes here!
|
||||
/// unimplemented!()
|
||||
/// }
|
||||
///
|
||||
/// fn finish(&self) -> u64 {
|
||||
/// // Your hashing algorithm goes here!
|
||||
/// unimplemented!()
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// type MyBuildHasher = BuildHasherDefault<MyHasher>;
|
||||
///
|
||||
/// let hash_map = HashMap::<u32, u32, MyBuildHasher>::default();
|
||||
/// ```
|
||||
///
|
||||
/// [method.default]: BuildHasherDefault::default
|
||||
/// [`HashMap`]: ../../std/collections/struct.HashMap.html
|
||||
/// [`HashSet`]: ../../std/collections/struct.HashSet.html
|
||||
/// [zero-sized]: https://doc.rust-lang.org/nomicon/exotic-sizes.html#zero-sized-types-zsts
|
||||
#[stable(since = "1.7.0", feature = "build_hasher")]
|
||||
pub struct BuildHasherDefault<H>(marker::PhantomData<H>);
|
||||
|
||||
#[stable(since = "1.9.0", feature = "core_impl_debug")]
|
||||
impl<H> fmt::Debug for BuildHasherDefault<H> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.pad("BuildHasherDefault")
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(since = "1.7.0", feature = "build_hasher")]
|
||||
impl<H: Default + Hasher> BuildHasher for BuildHasherDefault<H> {
|
||||
type Hasher = H;
|
||||
|
||||
fn build_hasher(&self) -> H {
|
||||
H::default()
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(since = "1.7.0", feature = "build_hasher")]
|
||||
impl<H> Clone for BuildHasherDefault<H> {
|
||||
fn clone(&self) -> BuildHasherDefault<H> {
|
||||
BuildHasherDefault(marker::PhantomData)
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(since = "1.7.0", feature = "build_hasher")]
|
||||
impl<H> Default for BuildHasherDefault<H> {
|
||||
fn default() -> BuildHasherDefault<H> {
|
||||
BuildHasherDefault(marker::PhantomData)
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(since = "1.29.0", feature = "build_hasher_eq")]
|
||||
impl<H> PartialEq for BuildHasherDefault<H> {
|
||||
fn eq(&self, _other: &BuildHasherDefault<H>) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(since = "1.29.0", feature = "build_hasher_eq")]
|
||||
impl<H> Eq for BuildHasherDefault<H> {}
|
||||
|
||||
mod impls {
|
||||
use crate::mem;
|
||||
use crate::slice;
|
||||
|
||||
use super::*;
|
||||
|
||||
macro_rules! impl_write {
|
||||
($(($ty:ident, $meth:ident),)*) => {$(
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl Hash for $ty {
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
state.$meth(*self)
|
||||
}
|
||||
|
||||
fn hash_slice<H: Hasher>(data: &[$ty], state: &mut H) {
|
||||
let newlen = data.len() * mem::size_of::<$ty>();
|
||||
let ptr = data.as_ptr() as *const u8;
|
||||
// SAFETY: `ptr` is valid and aligned, as this macro is only used
|
||||
// for numeric primitives which have no padding. The new slice only
|
||||
// spans across `data` and is never mutated, and its total size is the
|
||||
// same as the original `data` so it can't be over `isize::MAX`.
|
||||
state.write(unsafe { slice::from_raw_parts(ptr, newlen) })
|
||||
}
|
||||
}
|
||||
)*}
|
||||
}
|
||||
|
||||
impl_write! {
|
||||
(u8, write_u8),
|
||||
(u16, write_u16),
|
||||
(u32, write_u32),
|
||||
(u64, write_u64),
|
||||
(usize, write_usize),
|
||||
(i8, write_i8),
|
||||
(i16, write_i16),
|
||||
(i32, write_i32),
|
||||
(i64, write_i64),
|
||||
(isize, write_isize),
|
||||
(u128, write_u128),
|
||||
(i128, write_i128),
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl Hash for bool {
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
state.write_u8(*self as u8)
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl Hash for char {
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
state.write_u32(*self as u32)
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl Hash for str {
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
state.write(self.as_bytes());
|
||||
state.write_u8(0xff)
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "never_hash", since = "1.29.0")]
|
||||
impl Hash for ! {
|
||||
fn hash<H: Hasher>(&self, _: &mut H) {
|
||||
*self
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! impl_hash_tuple {
|
||||
() => (
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl Hash for () {
|
||||
fn hash<H: Hasher>(&self, _state: &mut H) {}
|
||||
}
|
||||
);
|
||||
|
||||
( $($name:ident)+) => (
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<$($name: Hash),+> Hash for ($($name,)+) where last_type!($($name,)+): ?Sized {
|
||||
#[allow(non_snake_case)]
|
||||
fn hash<S: Hasher>(&self, state: &mut S) {
|
||||
let ($(ref $name,)+) = *self;
|
||||
$($name.hash(state);)+
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
macro_rules! last_type {
|
||||
($a:ident,) => { $a };
|
||||
($a:ident, $($rest_a:ident,)+) => { last_type!($($rest_a,)+) };
|
||||
}
|
||||
|
||||
impl_hash_tuple! {}
|
||||
impl_hash_tuple! { A }
|
||||
impl_hash_tuple! { A B }
|
||||
impl_hash_tuple! { A B C }
|
||||
impl_hash_tuple! { A B C D }
|
||||
impl_hash_tuple! { A B C D E }
|
||||
impl_hash_tuple! { A B C D E F }
|
||||
impl_hash_tuple! { A B C D E F G }
|
||||
impl_hash_tuple! { A B C D E F G H }
|
||||
impl_hash_tuple! { A B C D E F G H I }
|
||||
impl_hash_tuple! { A B C D E F G H I J }
|
||||
impl_hash_tuple! { A B C D E F G H I J K }
|
||||
impl_hash_tuple! { A B C D E F G H I J K L }
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: Hash> Hash for [T] {
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
self.len().hash(state);
|
||||
Hash::hash_slice(self, state)
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: ?Sized + Hash> Hash for &T {
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
(**self).hash(state);
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: ?Sized + Hash> Hash for &mut T {
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
(**self).hash(state);
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: ?Sized> Hash for *const T {
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
if mem::size_of::<Self>() == mem::size_of::<usize>() {
|
||||
// Thin pointer
|
||||
state.write_usize(*self as *const () as usize);
|
||||
} else {
|
||||
// Fat pointer
|
||||
// SAFETY: we are accessing the memory occupied by `self`
|
||||
// which is guaranteed to be valid.
|
||||
// This assumes a fat pointer can be represented by a `(usize, usize)`,
|
||||
// which is safe to do in `std` because it is shipped and kept in sync
|
||||
// with the implementation of fat pointers in `rustc`.
|
||||
let (a, b) = unsafe { *(self as *const Self as *const (usize, usize)) };
|
||||
state.write_usize(a);
|
||||
state.write_usize(b);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: ?Sized> Hash for *mut T {
|
||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||
if mem::size_of::<Self>() == mem::size_of::<usize>() {
|
||||
// Thin pointer
|
||||
state.write_usize(*self as *const () as usize);
|
||||
} else {
|
||||
// Fat pointer
|
||||
// SAFETY: we are accessing the memory occupied by `self`
|
||||
// which is guaranteed to be valid.
|
||||
// This assumes a fat pointer can be represented by a `(usize, usize)`,
|
||||
// which is safe to do in `std` because it is shipped and kept in sync
|
||||
// with the implementation of fat pointers in `rustc`.
|
||||
let (a, b) = unsafe { *(self as *const Self as *const (usize, usize)) };
|
||||
state.write_usize(a);
|
||||
state.write_usize(b);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
388
libgrust/rustc-lib/core/src/hash/sip.rs
Normal file
388
libgrust/rustc-lib/core/src/hash/sip.rs
Normal file
@@ -0,0 +1,388 @@
|
||||
//! An implementation of SipHash.
|
||||
|
||||
#![allow(deprecated)] // the types in this module are deprecated
|
||||
|
||||
use crate::cmp;
|
||||
use crate::marker::PhantomData;
|
||||
use crate::mem;
|
||||
use crate::ptr;
|
||||
|
||||
/// An implementation of SipHash 1-3.
|
||||
///
|
||||
/// This is currently the default hashing function used by standard library
|
||||
/// (e.g., `collections::HashMap` uses it by default).
|
||||
///
|
||||
/// See: <https://131002.net/siphash>
|
||||
#[unstable(feature = "hashmap_internals", issue = "none")]
|
||||
#[rustc_deprecated(
|
||||
since = "1.13.0",
|
||||
reason = "use `std::collections::hash_map::DefaultHasher` instead"
|
||||
)]
|
||||
#[derive(Debug, Clone, Default)]
|
||||
#[doc(hidden)]
|
||||
pub struct SipHasher13 {
|
||||
hasher: Hasher<Sip13Rounds>,
|
||||
}
|
||||
|
||||
/// An implementation of SipHash 2-4.
|
||||
///
|
||||
/// See: <https://131002.net/siphash/>
|
||||
#[unstable(feature = "hashmap_internals", issue = "none")]
|
||||
#[rustc_deprecated(
|
||||
since = "1.13.0",
|
||||
reason = "use `std::collections::hash_map::DefaultHasher` instead"
|
||||
)]
|
||||
#[derive(Debug, Clone, Default)]
|
||||
struct SipHasher24 {
|
||||
hasher: Hasher<Sip24Rounds>,
|
||||
}
|
||||
|
||||
/// An implementation of SipHash 2-4.
|
||||
///
|
||||
/// See: <https://131002.net/siphash/>
|
||||
///
|
||||
/// SipHash is a general-purpose hashing function: it runs at a good
|
||||
/// speed (competitive with Spooky and City) and permits strong _keyed_
|
||||
/// hashing. This lets you key your hash tables from a strong RNG, such as
|
||||
/// [`rand::os::OsRng`](https://doc.rust-lang.org/rand/rand/os/struct.OsRng.html).
|
||||
///
|
||||
/// Although the SipHash algorithm is considered to be generally strong,
|
||||
/// it is not intended for cryptographic purposes. As such, all
|
||||
/// cryptographic uses of this implementation are _strongly discouraged_.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_deprecated(
|
||||
since = "1.13.0",
|
||||
reason = "use `std::collections::hash_map::DefaultHasher` instead"
|
||||
)]
|
||||
#[derive(Debug, Clone, Default)]
|
||||
pub struct SipHasher(SipHasher24);
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Hasher<S: Sip> {
|
||||
k0: u64,
|
||||
k1: u64,
|
||||
length: usize, // how many bytes we've processed
|
||||
state: State, // hash State
|
||||
tail: u64, // unprocessed bytes le
|
||||
ntail: usize, // how many bytes in tail are valid
|
||||
_marker: PhantomData<S>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
#[repr(C)]
|
||||
struct State {
|
||||
// v0, v2 and v1, v3 show up in pairs in the algorithm,
|
||||
// and simd implementations of SipHash will use vectors
|
||||
// of v02 and v13. By placing them in this order in the struct,
|
||||
// the compiler can pick up on just a few simd optimizations by itself.
|
||||
v0: u64,
|
||||
v2: u64,
|
||||
v1: u64,
|
||||
v3: u64,
|
||||
}
|
||||
|
||||
macro_rules! compress {
|
||||
($state:expr) => {{ compress!($state.v0, $state.v1, $state.v2, $state.v3) }};
|
||||
($v0:expr, $v1:expr, $v2:expr, $v3:expr) => {{
|
||||
$v0 = $v0.wrapping_add($v1);
|
||||
$v1 = $v1.rotate_left(13);
|
||||
$v1 ^= $v0;
|
||||
$v0 = $v0.rotate_left(32);
|
||||
$v2 = $v2.wrapping_add($v3);
|
||||
$v3 = $v3.rotate_left(16);
|
||||
$v3 ^= $v2;
|
||||
$v0 = $v0.wrapping_add($v3);
|
||||
$v3 = $v3.rotate_left(21);
|
||||
$v3 ^= $v0;
|
||||
$v2 = $v2.wrapping_add($v1);
|
||||
$v1 = $v1.rotate_left(17);
|
||||
$v1 ^= $v2;
|
||||
$v2 = $v2.rotate_left(32);
|
||||
}};
|
||||
}
|
||||
|
||||
/// Loads an integer of the desired type from a byte stream, in LE order. Uses
|
||||
/// `copy_nonoverlapping` to let the compiler generate the most efficient way
|
||||
/// to load it from a possibly unaligned address.
|
||||
///
|
||||
/// Unsafe because: unchecked indexing at i..i+size_of(int_ty)
|
||||
macro_rules! load_int_le {
|
||||
($buf:expr, $i:expr, $int_ty:ident) => {{
|
||||
debug_assert!($i + mem::size_of::<$int_ty>() <= $buf.len());
|
||||
let mut data = 0 as $int_ty;
|
||||
ptr::copy_nonoverlapping(
|
||||
$buf.as_ptr().add($i),
|
||||
&mut data as *mut _ as *mut u8,
|
||||
mem::size_of::<$int_ty>(),
|
||||
);
|
||||
data.to_le()
|
||||
}};
|
||||
}
|
||||
|
||||
/// Loads a u64 using up to 7 bytes of a byte slice. It looks clumsy but the
|
||||
/// `copy_nonoverlapping` calls that occur (via `load_int_le!`) all have fixed
|
||||
/// sizes and avoid calling `memcpy`, which is good for speed.
|
||||
///
|
||||
/// Unsafe because: unchecked indexing at start..start+len
|
||||
#[inline]
|
||||
unsafe fn u8to64_le(buf: &[u8], start: usize, len: usize) -> u64 {
|
||||
debug_assert!(len < 8);
|
||||
let mut i = 0; // current byte index (from LSB) in the output u64
|
||||
let mut out = 0;
|
||||
if i + 3 < len {
|
||||
// SAFETY: `i` cannot be greater than `len`, and the caller must guarantee
|
||||
// that the index start..start+len is in bounds.
|
||||
out = unsafe { load_int_le!(buf, start + i, u32) } as u64;
|
||||
i += 4;
|
||||
}
|
||||
if i + 1 < len {
|
||||
// SAFETY: same as above.
|
||||
out |= (unsafe { load_int_le!(buf, start + i, u16) } as u64) << (i * 8);
|
||||
i += 2
|
||||
}
|
||||
if i < len {
|
||||
// SAFETY: same as above.
|
||||
out |= (unsafe { *buf.get_unchecked(start + i) } as u64) << (i * 8);
|
||||
i += 1;
|
||||
}
|
||||
debug_assert_eq!(i, len);
|
||||
out
|
||||
}
|
||||
|
||||
impl SipHasher {
|
||||
/// Creates a new `SipHasher` with the two initial keys set to 0.
|
||||
#[inline]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_deprecated(
|
||||
since = "1.13.0",
|
||||
reason = "use `std::collections::hash_map::DefaultHasher` instead"
|
||||
)]
|
||||
pub fn new() -> SipHasher {
|
||||
SipHasher::new_with_keys(0, 0)
|
||||
}
|
||||
|
||||
/// Creates a `SipHasher` that is keyed off the provided keys.
|
||||
#[inline]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_deprecated(
|
||||
since = "1.13.0",
|
||||
reason = "use `std::collections::hash_map::DefaultHasher` instead"
|
||||
)]
|
||||
pub fn new_with_keys(key0: u64, key1: u64) -> SipHasher {
|
||||
SipHasher(SipHasher24 { hasher: Hasher::new_with_keys(key0, key1) })
|
||||
}
|
||||
}
|
||||
|
||||
impl SipHasher13 {
|
||||
/// Creates a new `SipHasher13` with the two initial keys set to 0.
|
||||
#[inline]
|
||||
#[unstable(feature = "hashmap_internals", issue = "none")]
|
||||
#[rustc_deprecated(
|
||||
since = "1.13.0",
|
||||
reason = "use `std::collections::hash_map::DefaultHasher` instead"
|
||||
)]
|
||||
pub fn new() -> SipHasher13 {
|
||||
SipHasher13::new_with_keys(0, 0)
|
||||
}
|
||||
|
||||
/// Creates a `SipHasher13` that is keyed off the provided keys.
|
||||
#[inline]
|
||||
#[unstable(feature = "hashmap_internals", issue = "none")]
|
||||
#[rustc_deprecated(
|
||||
since = "1.13.0",
|
||||
reason = "use `std::collections::hash_map::DefaultHasher` instead"
|
||||
)]
|
||||
pub fn new_with_keys(key0: u64, key1: u64) -> SipHasher13 {
|
||||
SipHasher13 { hasher: Hasher::new_with_keys(key0, key1) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: Sip> Hasher<S> {
|
||||
#[inline]
|
||||
fn new_with_keys(key0: u64, key1: u64) -> Hasher<S> {
|
||||
let mut state = Hasher {
|
||||
k0: key0,
|
||||
k1: key1,
|
||||
length: 0,
|
||||
state: State { v0: 0, v1: 0, v2: 0, v3: 0 },
|
||||
tail: 0,
|
||||
ntail: 0,
|
||||
_marker: PhantomData,
|
||||
};
|
||||
state.reset();
|
||||
state
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn reset(&mut self) {
|
||||
self.length = 0;
|
||||
self.state.v0 = self.k0 ^ 0x736f6d6570736575;
|
||||
self.state.v1 = self.k1 ^ 0x646f72616e646f6d;
|
||||
self.state.v2 = self.k0 ^ 0x6c7967656e657261;
|
||||
self.state.v3 = self.k1 ^ 0x7465646279746573;
|
||||
self.ntail = 0;
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl super::Hasher for SipHasher {
|
||||
#[inline]
|
||||
fn write(&mut self, msg: &[u8]) {
|
||||
self.0.hasher.write(msg)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn finish(&self) -> u64 {
|
||||
self.0.hasher.finish()
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "hashmap_internals", issue = "none")]
|
||||
impl super::Hasher for SipHasher13 {
|
||||
#[inline]
|
||||
fn write(&mut self, msg: &[u8]) {
|
||||
self.hasher.write(msg)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn finish(&self) -> u64 {
|
||||
self.hasher.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: Sip> super::Hasher for Hasher<S> {
|
||||
// Note: no integer hashing methods (`write_u*`, `write_i*`) are defined
|
||||
// for this type. We could add them, copy the `short_write` implementation
|
||||
// in librustc_data_structures/sip128.rs, and add `write_u*`/`write_i*`
|
||||
// methods to `SipHasher`, `SipHasher13`, and `DefaultHasher`. This would
|
||||
// greatly speed up integer hashing by those hashers, at the cost of
|
||||
// slightly slowing down compile speeds on some benchmarks. See #69152 for
|
||||
// details.
|
||||
#[inline]
|
||||
fn write(&mut self, msg: &[u8]) {
|
||||
let length = msg.len();
|
||||
self.length += length;
|
||||
|
||||
let mut needed = 0;
|
||||
|
||||
if self.ntail != 0 {
|
||||
needed = 8 - self.ntail;
|
||||
// SAFETY: `cmp::min(length, needed)` is guaranteed to not be over `length`
|
||||
self.tail |= unsafe { u8to64_le(msg, 0, cmp::min(length, needed)) } << (8 * self.ntail);
|
||||
if length < needed {
|
||||
self.ntail += length;
|
||||
return;
|
||||
} else {
|
||||
self.state.v3 ^= self.tail;
|
||||
S::c_rounds(&mut self.state);
|
||||
self.state.v0 ^= self.tail;
|
||||
self.ntail = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Buffered tail is now flushed, process new input.
|
||||
let len = length - needed;
|
||||
let left = len & 0x7; // len % 8
|
||||
|
||||
let mut i = needed;
|
||||
while i < len - left {
|
||||
// SAFETY: because `len - left` is the biggest multiple of 8 under
|
||||
// `len`, and because `i` starts at `needed` where `len` is `length - needed`,
|
||||
// `i + 8` is guaranteed to be less than or equal to `length`.
|
||||
let mi = unsafe { load_int_le!(msg, i, u64) };
|
||||
|
||||
self.state.v3 ^= mi;
|
||||
S::c_rounds(&mut self.state);
|
||||
self.state.v0 ^= mi;
|
||||
|
||||
i += 8;
|
||||
}
|
||||
|
||||
// SAFETY: `i` is now `needed + len.div_euclid(8) * 8`,
|
||||
// so `i + left` = `needed + len` = `length`, which is by
|
||||
// definition equal to `msg.len()`.
|
||||
self.tail = unsafe { u8to64_le(msg, i, left) };
|
||||
self.ntail = left;
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn finish(&self) -> u64 {
|
||||
let mut state = self.state;
|
||||
|
||||
let b: u64 = ((self.length as u64 & 0xff) << 56) | self.tail;
|
||||
|
||||
state.v3 ^= b;
|
||||
S::c_rounds(&mut state);
|
||||
state.v0 ^= b;
|
||||
|
||||
state.v2 ^= 0xff;
|
||||
S::d_rounds(&mut state);
|
||||
|
||||
state.v0 ^ state.v1 ^ state.v2 ^ state.v3
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: Sip> Clone for Hasher<S> {
|
||||
#[inline]
|
||||
fn clone(&self) -> Hasher<S> {
|
||||
Hasher {
|
||||
k0: self.k0,
|
||||
k1: self.k1,
|
||||
length: self.length,
|
||||
state: self.state,
|
||||
tail: self.tail,
|
||||
ntail: self.ntail,
|
||||
_marker: self._marker,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<S: Sip> Default for Hasher<S> {
|
||||
/// Creates a `Hasher<S>` with the two initial keys set to 0.
|
||||
#[inline]
|
||||
fn default() -> Hasher<S> {
|
||||
Hasher::new_with_keys(0, 0)
|
||||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
trait Sip {
|
||||
fn c_rounds(_: &mut State);
|
||||
fn d_rounds(_: &mut State);
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default)]
|
||||
struct Sip13Rounds;
|
||||
|
||||
impl Sip for Sip13Rounds {
|
||||
#[inline]
|
||||
fn c_rounds(state: &mut State) {
|
||||
compress!(state);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn d_rounds(state: &mut State) {
|
||||
compress!(state);
|
||||
compress!(state);
|
||||
compress!(state);
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default)]
|
||||
struct Sip24Rounds;
|
||||
|
||||
impl Sip for Sip24Rounds {
|
||||
#[inline]
|
||||
fn c_rounds(state: &mut State) {
|
||||
compress!(state);
|
||||
compress!(state);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn d_rounds(state: &mut State) {
|
||||
compress!(state);
|
||||
compress!(state);
|
||||
compress!(state);
|
||||
compress!(state);
|
||||
}
|
||||
}
|
||||
174
libgrust/rustc-lib/core/src/hint.rs
Normal file
174
libgrust/rustc-lib/core/src/hint.rs
Normal file
@@ -0,0 +1,174 @@
|
||||
#![stable(feature = "core_hint", since = "1.27.0")]
|
||||
|
||||
//! Hints to compiler that affects how code should be emitted or optimized.
|
||||
//! Hints may be compile time or runtime.
|
||||
|
||||
use crate::intrinsics;
|
||||
|
||||
/// Informs the compiler that this point in the code is not reachable, enabling
|
||||
/// further optimizations.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// Reaching this function is completely *undefined behavior* (UB). In
|
||||
/// particular, the compiler assumes that all UB must never happen, and
|
||||
/// therefore will eliminate all branches that reach to a call to
|
||||
/// `unreachable_unchecked()`.
|
||||
///
|
||||
/// Like all instances of UB, if this assumption turns out to be wrong, i.e., the
|
||||
/// `unreachable_unchecked()` call is actually reachable among all possible
|
||||
/// control flow, the compiler will apply the wrong optimization strategy, and
|
||||
/// may sometimes even corrupt seemingly unrelated code, causing
|
||||
/// difficult-to-debug problems.
|
||||
///
|
||||
/// Use this function only when you can prove that the code will never call it.
|
||||
/// Otherwise, consider using the [`unreachable!`] macro, which does not allow
|
||||
/// optimizations but will panic when executed.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// fn div_1(a: u32, b: u32) -> u32 {
|
||||
/// use std::hint::unreachable_unchecked;
|
||||
///
|
||||
/// // `b.saturating_add(1)` is always positive (not zero),
|
||||
/// // hence `checked_div` will never return `None`.
|
||||
/// // Therefore, the else branch is unreachable.
|
||||
/// a.checked_div(b.saturating_add(1))
|
||||
/// .unwrap_or_else(|| unsafe { unreachable_unchecked() })
|
||||
/// }
|
||||
///
|
||||
/// assert_eq!(div_1(7, 0), 7);
|
||||
/// assert_eq!(div_1(9, 1), 4);
|
||||
/// assert_eq!(div_1(11, u32::MAX), 0);
|
||||
/// ```
|
||||
#[inline]
|
||||
#[stable(feature = "unreachable", since = "1.27.0")]
|
||||
#[rustc_const_unstable(feature = "const_unreachable_unchecked", issue = "53188")]
|
||||
pub const unsafe fn unreachable_unchecked() -> ! {
|
||||
// SAFETY: the safety contract for `intrinsics::unreachable` must
|
||||
// be upheld by the caller.
|
||||
unsafe { intrinsics::unreachable() }
|
||||
}
|
||||
|
||||
/// Emits a machine instruction to signal the processor that it is running in
|
||||
/// a busy-wait spin-loop ("spin lock").
|
||||
///
|
||||
/// Upon receiving the spin-loop signal the processor can optimize its behavior by,
|
||||
/// for example, saving power or switching hyper-threads.
|
||||
///
|
||||
/// This function is different from [`thread::yield_now`] which directly
|
||||
/// yields to the system's scheduler, whereas `spin_loop` does not interact
|
||||
/// with the operating system.
|
||||
///
|
||||
/// A common use case for `spin_loop` is implementing bounded optimistic
|
||||
/// spinning in a CAS loop in synchronization primitives. To avoid problems
|
||||
/// like priority inversion, it is strongly recommended that the spin loop is
|
||||
/// terminated after a finite amount of iterations and an appropriate blocking
|
||||
/// syscall is made.
|
||||
///
|
||||
/// **Note**: On platforms that do not support receiving spin-loop hints this
|
||||
/// function does not do anything at all.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::sync::atomic::{AtomicBool, Ordering};
|
||||
/// use std::sync::Arc;
|
||||
/// use std::{hint, thread};
|
||||
///
|
||||
/// // A shared atomic value that threads will use to coordinate
|
||||
/// let live = Arc::new(AtomicBool::new(false));
|
||||
///
|
||||
/// // In a background thread we'll eventually set the value
|
||||
/// let bg_work = {
|
||||
/// let live = live.clone();
|
||||
/// thread::spawn(move || {
|
||||
/// // Do some work, then make the value live
|
||||
/// do_some_work();
|
||||
/// live.store(true, Ordering::Release);
|
||||
/// })
|
||||
/// };
|
||||
///
|
||||
/// // Back on our current thread, we wait for the value to be set
|
||||
/// while live.load(Ordering::Acquire) {
|
||||
/// // The spin loop is a hint to the CPU that we're waiting, but probably
|
||||
/// // not for very long
|
||||
/// hint::spin_loop();
|
||||
/// }
|
||||
///
|
||||
/// // The value is now set
|
||||
/// # fn do_some_work() {}
|
||||
/// do_some_work();
|
||||
/// bg_work.join()?;
|
||||
/// # Ok::<(), Box<dyn core::any::Any + Send + 'static>>(())
|
||||
/// ```
|
||||
///
|
||||
/// [`thread::yield_now`]: ../../std/thread/fn.yield_now.html
|
||||
#[inline]
|
||||
#[stable(feature = "renamed_spin_loop", since = "1.49.0")]
|
||||
pub fn spin_loop() {
|
||||
#[cfg(all(any(target_arch = "x86", target_arch = "x86_64"), target_feature = "sse2"))]
|
||||
{
|
||||
#[cfg(target_arch = "x86")]
|
||||
{
|
||||
// SAFETY: the `cfg` attr ensures that we only execute this on x86 targets.
|
||||
unsafe { crate::arch::x86::_mm_pause() };
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
{
|
||||
// SAFETY: the `cfg` attr ensures that we only execute this on x86_64 targets.
|
||||
unsafe { crate::arch::x86_64::_mm_pause() };
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(target_arch = "aarch64", all(target_arch = "arm", target_feature = "v6")))]
|
||||
{
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
{
|
||||
// SAFETY: the `cfg` attr ensures that we only execute this on aarch64 targets.
|
||||
unsafe { crate::arch::aarch64::__yield() };
|
||||
}
|
||||
#[cfg(target_arch = "arm")]
|
||||
{
|
||||
// SAFETY: the `cfg` attr ensures that we only execute this on arm targets
|
||||
// with support for the v6 feature.
|
||||
unsafe { crate::arch::arm::__yield() };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// An identity function that *__hints__* to the compiler to be maximally pessimistic about what
|
||||
/// `black_box` could do.
|
||||
///
|
||||
/// Unlike [`std::convert::identity`], a Rust compiler is encouraged to assume that `black_box` can
|
||||
/// use `dummy` in any possible valid way that Rust code is allowed to without introducing undefined
|
||||
/// behavior in the calling code. This property makes `black_box` useful for writing code in which
|
||||
/// certain optimizations are not desired, such as benchmarks.
|
||||
///
|
||||
/// Note however, that `black_box` is only (and can only be) provided on a "best-effort" basis. The
|
||||
/// extent to which it can block optimisations may vary depending upon the platform and code-gen
|
||||
/// backend used. Programs cannot rely on `black_box` for *correctness* in any way.
|
||||
///
|
||||
/// [`std::convert::identity`]: crate::convert::identity
|
||||
#[cfg_attr(not(miri), inline)]
|
||||
#[cfg_attr(miri, inline(never))]
|
||||
#[unstable(feature = "test", issue = "50297")]
|
||||
#[cfg_attr(miri, allow(unused_mut))]
|
||||
pub fn black_box<T>(mut dummy: T) -> T {
|
||||
// We need to "use" the argument in some way LLVM can't introspect, and on
|
||||
// targets that support it we can typically leverage inline assembly to do
|
||||
// this. LLVM's interpretation of inline assembly is that it's, well, a black
|
||||
// box. This isn't the greatest implementation since it probably deoptimizes
|
||||
// more than we want, but it's so far good enough.
|
||||
|
||||
#[cfg(not(miri))] // This is just a hint, so it is fine to skip in Miri.
|
||||
// SAFETY: the inline assembly is a no-op.
|
||||
unsafe {
|
||||
// FIXME: Cannot use `asm!` because it doesn't support MIPS and other architectures.
|
||||
llvm_asm!("" : : "r"(&mut dummy) : "memory" : "volatile");
|
||||
}
|
||||
|
||||
dummy
|
||||
}
|
||||
119
libgrust/rustc-lib/core/src/internal_macros.rs
Normal file
119
libgrust/rustc-lib/core/src/internal_macros.rs
Normal file
@@ -0,0 +1,119 @@
|
||||
// implements the unary operator "op &T"
|
||||
// based on "op T" where T is expected to be `Copy`able
|
||||
macro_rules! forward_ref_unop {
|
||||
(impl $imp:ident, $method:ident for $t:ty) => {
|
||||
forward_ref_unop!(impl $imp, $method for $t,
|
||||
#[stable(feature = "rust1", since = "1.0.0")]);
|
||||
};
|
||||
(impl $imp:ident, $method:ident for $t:ty, #[$attr:meta]) => {
|
||||
#[$attr]
|
||||
impl $imp for &$t {
|
||||
type Output = <$t as $imp>::Output;
|
||||
|
||||
#[inline]
|
||||
fn $method(self) -> <$t as $imp>::Output {
|
||||
$imp::$method(*self)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// implements binary operators "&T op U", "T op &U", "&T op &U"
|
||||
// based on "T op U" where T and U are expected to be `Copy`able
|
||||
macro_rules! forward_ref_binop {
|
||||
(impl $imp:ident, $method:ident for $t:ty, $u:ty) => {
|
||||
forward_ref_binop!(impl $imp, $method for $t, $u,
|
||||
#[stable(feature = "rust1", since = "1.0.0")]);
|
||||
};
|
||||
(impl $imp:ident, $method:ident for $t:ty, $u:ty, #[$attr:meta]) => {
|
||||
#[$attr]
|
||||
impl<'a> $imp<$u> for &'a $t {
|
||||
type Output = <$t as $imp<$u>>::Output;
|
||||
|
||||
#[inline]
|
||||
fn $method(self, other: $u) -> <$t as $imp<$u>>::Output {
|
||||
$imp::$method(*self, other)
|
||||
}
|
||||
}
|
||||
|
||||
#[$attr]
|
||||
impl $imp<&$u> for $t {
|
||||
type Output = <$t as $imp<$u>>::Output;
|
||||
|
||||
#[inline]
|
||||
fn $method(self, other: &$u) -> <$t as $imp<$u>>::Output {
|
||||
$imp::$method(self, *other)
|
||||
}
|
||||
}
|
||||
|
||||
#[$attr]
|
||||
impl $imp<&$u> for &$t {
|
||||
type Output = <$t as $imp<$u>>::Output;
|
||||
|
||||
#[inline]
|
||||
fn $method(self, other: &$u) -> <$t as $imp<$u>>::Output {
|
||||
$imp::$method(*self, *other)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// implements "T op= &U", based on "T op= U"
|
||||
// where U is expected to be `Copy`able
|
||||
macro_rules! forward_ref_op_assign {
|
||||
(impl $imp:ident, $method:ident for $t:ty, $u:ty) => {
|
||||
forward_ref_op_assign!(impl $imp, $method for $t, $u,
|
||||
#[stable(feature = "op_assign_builtins_by_ref", since = "1.22.0")]);
|
||||
};
|
||||
(impl $imp:ident, $method:ident for $t:ty, $u:ty, #[$attr:meta]) => {
|
||||
#[$attr]
|
||||
impl $imp<&$u> for $t {
|
||||
#[inline]
|
||||
fn $method(&mut self, other: &$u) {
|
||||
$imp::$method(self, *other);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a zero-size type similar to a closure type, but named.
|
||||
#[unstable(feature = "std_internals", issue = "none")]
|
||||
macro_rules! impl_fn_for_zst {
|
||||
($(
|
||||
$( #[$attr: meta] )*
|
||||
struct $Name: ident impl$( <$( $lifetime : lifetime ),+> )? Fn =
|
||||
|$( $arg: ident: $ArgTy: ty ),*| -> $ReturnTy: ty
|
||||
$body: block;
|
||||
)+) => {
|
||||
$(
|
||||
$( #[$attr] )*
|
||||
struct $Name;
|
||||
|
||||
impl $( <$( $lifetime ),+> )? Fn<($( $ArgTy, )*)> for $Name {
|
||||
#[inline]
|
||||
extern "rust-call" fn call(&self, ($( $arg, )*): ($( $ArgTy, )*)) -> $ReturnTy {
|
||||
$body
|
||||
}
|
||||
}
|
||||
|
||||
impl $( <$( $lifetime ),+> )? FnMut<($( $ArgTy, )*)> for $Name {
|
||||
#[inline]
|
||||
extern "rust-call" fn call_mut(
|
||||
&mut self,
|
||||
($( $arg, )*): ($( $ArgTy, )*)
|
||||
) -> $ReturnTy {
|
||||
Fn::call(&*self, ($( $arg, )*))
|
||||
}
|
||||
}
|
||||
|
||||
impl $( <$( $lifetime ),+> )? FnOnce<($( $ArgTy, )*)> for $Name {
|
||||
type Output = $ReturnTy;
|
||||
|
||||
#[inline]
|
||||
extern "rust-call" fn call_once(self, ($( $arg, )*): ($( $ArgTy, )*)) -> $ReturnTy {
|
||||
Fn::call(&self, ($( $arg, )*))
|
||||
}
|
||||
}
|
||||
)+
|
||||
}
|
||||
}
|
||||
2023
libgrust/rustc-lib/core/src/intrinsics.rs
Normal file
2023
libgrust/rustc-lib/core/src/intrinsics.rs
Normal file
File diff suppressed because it is too large
Load Diff
327
libgrust/rustc-lib/core/src/iter/adapters/chain.rs
Normal file
327
libgrust/rustc-lib/core/src/iter/adapters/chain.rs
Normal file
@@ -0,0 +1,327 @@
|
||||
use crate::iter::{DoubleEndedIterator, FusedIterator, Iterator, TrustedLen};
|
||||
use crate::ops::Try;
|
||||
use crate::usize;
|
||||
|
||||
/// An iterator that links two iterators together, in a chain.
|
||||
///
|
||||
/// This `struct` is created by [`Iterator::chain`]. See its documentation
|
||||
/// for more.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::iter::Chain;
|
||||
/// use std::slice::Iter;
|
||||
///
|
||||
/// let a1 = [1, 2, 3];
|
||||
/// let a2 = [4, 5, 6];
|
||||
/// let iter: Chain<Iter<_>, Iter<_>> = a1.iter().chain(a2.iter());
|
||||
/// ```
|
||||
#[derive(Clone, Debug)]
|
||||
#[must_use = "iterators are lazy and do nothing unless consumed"]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub struct Chain<A, B> {
|
||||
// These are "fused" with `Option` so we don't need separate state to track which part is
|
||||
// already exhausted, and we may also get niche layout for `None`. We don't use the real `Fuse`
|
||||
// adapter because its specialization for `FusedIterator` unconditionally descends into the
|
||||
// iterator, and that could be expensive to keep revisiting stuff like nested chains. It also
|
||||
// hurts compiler performance to add more iterator layers to `Chain`.
|
||||
//
|
||||
// Only the "first" iterator is actually set `None` when exhausted, depending on whether you
|
||||
// iterate forward or backward. If you mix directions, then both sides may be `None`.
|
||||
a: Option<A>,
|
||||
b: Option<B>,
|
||||
}
|
||||
impl<A, B> Chain<A, B> {
|
||||
pub(in super::super) fn new(a: A, b: B) -> Chain<A, B> {
|
||||
Chain { a: Some(a), b: Some(b) }
|
||||
}
|
||||
}
|
||||
|
||||
/// Fuse the iterator if the expression is `None`.
|
||||
macro_rules! fuse {
|
||||
($self:ident . $iter:ident . $($call:tt)+) => {
|
||||
match $self.$iter {
|
||||
Some(ref mut iter) => match iter.$($call)+ {
|
||||
None => {
|
||||
$self.$iter = None;
|
||||
None
|
||||
}
|
||||
item => item,
|
||||
},
|
||||
None => None,
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// Try an iterator method without fusing,
|
||||
/// like an inline `.as_mut().and_then(...)`
|
||||
macro_rules! maybe {
|
||||
($self:ident . $iter:ident . $($call:tt)+) => {
|
||||
match $self.$iter {
|
||||
Some(ref mut iter) => iter.$($call)+,
|
||||
None => None,
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<A, B> Iterator for Chain<A, B>
|
||||
where
|
||||
A: Iterator,
|
||||
B: Iterator<Item = A::Item>,
|
||||
{
|
||||
type Item = A::Item;
|
||||
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<A::Item> {
|
||||
match fuse!(self.a.next()) {
|
||||
None => maybe!(self.b.next()),
|
||||
item => item,
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[rustc_inherit_overflow_checks]
|
||||
fn count(self) -> usize {
|
||||
let a_count = match self.a {
|
||||
Some(a) => a.count(),
|
||||
None => 0,
|
||||
};
|
||||
let b_count = match self.b {
|
||||
Some(b) => b.count(),
|
||||
None => 0,
|
||||
};
|
||||
a_count + b_count
|
||||
}
|
||||
|
||||
fn try_fold<Acc, F, R>(&mut self, mut acc: Acc, mut f: F) -> R
|
||||
where
|
||||
Self: Sized,
|
||||
F: FnMut(Acc, Self::Item) -> R,
|
||||
R: Try<Ok = Acc>,
|
||||
{
|
||||
if let Some(ref mut a) = self.a {
|
||||
acc = a.try_fold(acc, &mut f)?;
|
||||
self.a = None;
|
||||
}
|
||||
if let Some(ref mut b) = self.b {
|
||||
acc = b.try_fold(acc, f)?;
|
||||
// we don't fuse the second iterator
|
||||
}
|
||||
try { acc }
|
||||
}
|
||||
|
||||
fn fold<Acc, F>(self, mut acc: Acc, mut f: F) -> Acc
|
||||
where
|
||||
F: FnMut(Acc, Self::Item) -> Acc,
|
||||
{
|
||||
if let Some(a) = self.a {
|
||||
acc = a.fold(acc, &mut f);
|
||||
}
|
||||
if let Some(b) = self.b {
|
||||
acc = b.fold(acc, f);
|
||||
}
|
||||
acc
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn advance_by(&mut self, n: usize) -> Result<(), usize> {
|
||||
let mut rem = n;
|
||||
|
||||
if let Some(ref mut a) = self.a {
|
||||
match a.advance_by(rem) {
|
||||
Ok(()) => return Ok(()),
|
||||
Err(k) => rem -= k,
|
||||
}
|
||||
self.a = None;
|
||||
}
|
||||
|
||||
if let Some(ref mut b) = self.b {
|
||||
match b.advance_by(rem) {
|
||||
Ok(()) => return Ok(()),
|
||||
Err(k) => rem -= k,
|
||||
}
|
||||
// we don't fuse the second iterator
|
||||
}
|
||||
|
||||
if rem == 0 { Ok(()) } else { Err(n - rem) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn nth(&mut self, mut n: usize) -> Option<Self::Item> {
|
||||
if let Some(ref mut a) = self.a {
|
||||
match a.advance_by(n) {
|
||||
Ok(()) => match a.next() {
|
||||
None => n = 0,
|
||||
x => return x,
|
||||
},
|
||||
Err(k) => n -= k,
|
||||
}
|
||||
|
||||
self.a = None;
|
||||
}
|
||||
|
||||
maybe!(self.b.nth(n))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn find<P>(&mut self, mut predicate: P) -> Option<Self::Item>
|
||||
where
|
||||
P: FnMut(&Self::Item) -> bool,
|
||||
{
|
||||
match fuse!(self.a.find(&mut predicate)) {
|
||||
None => maybe!(self.b.find(predicate)),
|
||||
item => item,
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn last(self) -> Option<A::Item> {
|
||||
// Must exhaust a before b.
|
||||
let a_last = match self.a {
|
||||
Some(a) => a.last(),
|
||||
None => None,
|
||||
};
|
||||
let b_last = match self.b {
|
||||
Some(b) => b.last(),
|
||||
None => None,
|
||||
};
|
||||
b_last.or(a_last)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
match self {
|
||||
Chain { a: Some(a), b: Some(b) } => {
|
||||
let (a_lower, a_upper) = a.size_hint();
|
||||
let (b_lower, b_upper) = b.size_hint();
|
||||
|
||||
let lower = a_lower.saturating_add(b_lower);
|
||||
|
||||
let upper = match (a_upper, b_upper) {
|
||||
(Some(x), Some(y)) => x.checked_add(y),
|
||||
_ => None,
|
||||
};
|
||||
|
||||
(lower, upper)
|
||||
}
|
||||
Chain { a: Some(a), b: None } => a.size_hint(),
|
||||
Chain { a: None, b: Some(b) } => b.size_hint(),
|
||||
Chain { a: None, b: None } => (0, Some(0)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<A, B> DoubleEndedIterator for Chain<A, B>
|
||||
where
|
||||
A: DoubleEndedIterator,
|
||||
B: DoubleEndedIterator<Item = A::Item>,
|
||||
{
|
||||
#[inline]
|
||||
fn next_back(&mut self) -> Option<A::Item> {
|
||||
match fuse!(self.b.next_back()) {
|
||||
None => maybe!(self.a.next_back()),
|
||||
item => item,
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn advance_back_by(&mut self, n: usize) -> Result<(), usize> {
|
||||
let mut rem = n;
|
||||
|
||||
if let Some(ref mut b) = self.b {
|
||||
match b.advance_back_by(rem) {
|
||||
Ok(()) => return Ok(()),
|
||||
Err(k) => rem -= k,
|
||||
}
|
||||
self.b = None;
|
||||
}
|
||||
|
||||
if let Some(ref mut a) = self.a {
|
||||
match a.advance_back_by(rem) {
|
||||
Ok(()) => return Ok(()),
|
||||
Err(k) => rem -= k,
|
||||
}
|
||||
// we don't fuse the second iterator
|
||||
}
|
||||
|
||||
if rem == 0 { Ok(()) } else { Err(n - rem) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn nth_back(&mut self, mut n: usize) -> Option<Self::Item> {
|
||||
if let Some(ref mut b) = self.b {
|
||||
match b.advance_back_by(n) {
|
||||
Ok(()) => match b.next_back() {
|
||||
None => n = 0,
|
||||
x => return x,
|
||||
},
|
||||
Err(k) => n -= k,
|
||||
}
|
||||
|
||||
self.b = None;
|
||||
}
|
||||
|
||||
maybe!(self.a.nth_back(n))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn rfind<P>(&mut self, mut predicate: P) -> Option<Self::Item>
|
||||
where
|
||||
P: FnMut(&Self::Item) -> bool,
|
||||
{
|
||||
match fuse!(self.b.rfind(&mut predicate)) {
|
||||
None => maybe!(self.a.rfind(predicate)),
|
||||
item => item,
|
||||
}
|
||||
}
|
||||
|
||||
fn try_rfold<Acc, F, R>(&mut self, mut acc: Acc, mut f: F) -> R
|
||||
where
|
||||
Self: Sized,
|
||||
F: FnMut(Acc, Self::Item) -> R,
|
||||
R: Try<Ok = Acc>,
|
||||
{
|
||||
if let Some(ref mut b) = self.b {
|
||||
acc = b.try_rfold(acc, &mut f)?;
|
||||
self.b = None;
|
||||
}
|
||||
if let Some(ref mut a) = self.a {
|
||||
acc = a.try_rfold(acc, f)?;
|
||||
// we don't fuse the second iterator
|
||||
}
|
||||
try { acc }
|
||||
}
|
||||
|
||||
fn rfold<Acc, F>(self, mut acc: Acc, mut f: F) -> Acc
|
||||
where
|
||||
F: FnMut(Acc, Self::Item) -> Acc,
|
||||
{
|
||||
if let Some(b) = self.b {
|
||||
acc = b.rfold(acc, &mut f);
|
||||
}
|
||||
if let Some(a) = self.a {
|
||||
acc = a.rfold(acc, f);
|
||||
}
|
||||
acc
|
||||
}
|
||||
}
|
||||
|
||||
// Note: *both* must be fused to handle double-ended iterators.
|
||||
#[stable(feature = "fused", since = "1.26.0")]
|
||||
impl<A, B> FusedIterator for Chain<A, B>
|
||||
where
|
||||
A: FusedIterator,
|
||||
B: FusedIterator<Item = A::Item>,
|
||||
{
|
||||
}
|
||||
|
||||
#[unstable(feature = "trusted_len", issue = "37572")]
|
||||
unsafe impl<A, B> TrustedLen for Chain<A, B>
|
||||
where
|
||||
A: TrustedLen,
|
||||
B: TrustedLen<Item = A::Item>,
|
||||
{
|
||||
}
|
||||
421
libgrust/rustc-lib/core/src/iter/adapters/flatten.rs
Normal file
421
libgrust/rustc-lib/core/src/iter/adapters/flatten.rs
Normal file
@@ -0,0 +1,421 @@
|
||||
use crate::fmt;
|
||||
use crate::ops::Try;
|
||||
|
||||
use super::super::{DoubleEndedIterator, Fuse, FusedIterator, Iterator};
|
||||
use super::Map;
|
||||
|
||||
/// An iterator that maps each element to an iterator, and yields the elements
|
||||
/// of the produced iterators.
|
||||
///
|
||||
/// This `struct` is created by [`Iterator::flat_map`]. See its documentation
|
||||
/// for more.
|
||||
#[must_use = "iterators are lazy and do nothing unless consumed"]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub struct FlatMap<I, U: IntoIterator, F> {
|
||||
inner: FlattenCompat<Map<I, F>, <U as IntoIterator>::IntoIter>,
|
||||
}
|
||||
impl<I: Iterator, U: IntoIterator, F: FnMut(I::Item) -> U> FlatMap<I, U, F> {
|
||||
pub(in super::super) fn new(iter: I, f: F) -> FlatMap<I, U, F> {
|
||||
FlatMap { inner: FlattenCompat::new(iter.map(f)) }
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<I: Clone, U, F: Clone> Clone for FlatMap<I, U, F>
|
||||
where
|
||||
U: Clone + IntoIterator<IntoIter: Clone>,
|
||||
{
|
||||
fn clone(&self) -> Self {
|
||||
FlatMap { inner: self.inner.clone() }
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "core_impl_debug", since = "1.9.0")]
|
||||
impl<I: fmt::Debug, U, F> fmt::Debug for FlatMap<I, U, F>
|
||||
where
|
||||
U: IntoIterator<IntoIter: fmt::Debug>,
|
||||
{
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("FlatMap").field("inner", &self.inner).finish()
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<I: Iterator, U: IntoIterator, F> Iterator for FlatMap<I, U, F>
|
||||
where
|
||||
F: FnMut(I::Item) -> U,
|
||||
{
|
||||
type Item = U::Item;
|
||||
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<U::Item> {
|
||||
self.inner.next()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
self.inner.size_hint()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn try_fold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R
|
||||
where
|
||||
Self: Sized,
|
||||
Fold: FnMut(Acc, Self::Item) -> R,
|
||||
R: Try<Ok = Acc>,
|
||||
{
|
||||
self.inner.try_fold(init, fold)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn fold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc
|
||||
where
|
||||
Fold: FnMut(Acc, Self::Item) -> Acc,
|
||||
{
|
||||
self.inner.fold(init, fold)
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<I: DoubleEndedIterator, U, F> DoubleEndedIterator for FlatMap<I, U, F>
|
||||
where
|
||||
F: FnMut(I::Item) -> U,
|
||||
U: IntoIterator<IntoIter: DoubleEndedIterator>,
|
||||
{
|
||||
#[inline]
|
||||
fn next_back(&mut self) -> Option<U::Item> {
|
||||
self.inner.next_back()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn try_rfold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R
|
||||
where
|
||||
Self: Sized,
|
||||
Fold: FnMut(Acc, Self::Item) -> R,
|
||||
R: Try<Ok = Acc>,
|
||||
{
|
||||
self.inner.try_rfold(init, fold)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn rfold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc
|
||||
where
|
||||
Fold: FnMut(Acc, Self::Item) -> Acc,
|
||||
{
|
||||
self.inner.rfold(init, fold)
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "fused", since = "1.26.0")]
|
||||
impl<I, U, F> FusedIterator for FlatMap<I, U, F>
|
||||
where
|
||||
I: FusedIterator,
|
||||
U: IntoIterator,
|
||||
F: FnMut(I::Item) -> U,
|
||||
{
|
||||
}
|
||||
|
||||
/// An iterator that flattens one level of nesting in an iterator of things
|
||||
/// that can be turned into iterators.
|
||||
///
|
||||
/// This `struct` is created by the [`flatten`] method on [`Iterator`]. See its
|
||||
/// documentation for more.
|
||||
///
|
||||
/// [`flatten`]: Iterator::flatten
|
||||
/// [`Iterator`]: trait.Iterator.html
|
||||
#[must_use = "iterators are lazy and do nothing unless consumed"]
|
||||
#[stable(feature = "iterator_flatten", since = "1.29.0")]
|
||||
pub struct Flatten<I: Iterator<Item: IntoIterator>> {
|
||||
inner: FlattenCompat<I, <I::Item as IntoIterator>::IntoIter>,
|
||||
}
|
||||
|
||||
impl<I: Iterator<Item: IntoIterator>> Flatten<I> {
|
||||
pub(in super::super) fn new(iter: I) -> Flatten<I> {
|
||||
Flatten { inner: FlattenCompat::new(iter) }
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "iterator_flatten", since = "1.29.0")]
|
||||
impl<I, U> fmt::Debug for Flatten<I>
|
||||
where
|
||||
I: fmt::Debug + Iterator<Item: IntoIterator<IntoIter = U, Item = U::Item>>,
|
||||
U: fmt::Debug + Iterator,
|
||||
{
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("Flatten").field("inner", &self.inner).finish()
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "iterator_flatten", since = "1.29.0")]
|
||||
impl<I, U> Clone for Flatten<I>
|
||||
where
|
||||
I: Clone + Iterator<Item: IntoIterator<IntoIter = U, Item = U::Item>>,
|
||||
U: Clone + Iterator,
|
||||
{
|
||||
fn clone(&self) -> Self {
|
||||
Flatten { inner: self.inner.clone() }
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "iterator_flatten", since = "1.29.0")]
|
||||
impl<I, U> Iterator for Flatten<I>
|
||||
where
|
||||
I: Iterator<Item: IntoIterator<IntoIter = U, Item = U::Item>>,
|
||||
U: Iterator,
|
||||
{
|
||||
type Item = U::Item;
|
||||
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<U::Item> {
|
||||
self.inner.next()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
self.inner.size_hint()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn try_fold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R
|
||||
where
|
||||
Self: Sized,
|
||||
Fold: FnMut(Acc, Self::Item) -> R,
|
||||
R: Try<Ok = Acc>,
|
||||
{
|
||||
self.inner.try_fold(init, fold)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn fold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc
|
||||
where
|
||||
Fold: FnMut(Acc, Self::Item) -> Acc,
|
||||
{
|
||||
self.inner.fold(init, fold)
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "iterator_flatten", since = "1.29.0")]
|
||||
impl<I, U> DoubleEndedIterator for Flatten<I>
|
||||
where
|
||||
I: DoubleEndedIterator<Item: IntoIterator<IntoIter = U, Item = U::Item>>,
|
||||
U: DoubleEndedIterator,
|
||||
{
|
||||
#[inline]
|
||||
fn next_back(&mut self) -> Option<U::Item> {
|
||||
self.inner.next_back()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn try_rfold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R
|
||||
where
|
||||
Self: Sized,
|
||||
Fold: FnMut(Acc, Self::Item) -> R,
|
||||
R: Try<Ok = Acc>,
|
||||
{
|
||||
self.inner.try_rfold(init, fold)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn rfold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc
|
||||
where
|
||||
Fold: FnMut(Acc, Self::Item) -> Acc,
|
||||
{
|
||||
self.inner.rfold(init, fold)
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "iterator_flatten", since = "1.29.0")]
|
||||
impl<I, U> FusedIterator for Flatten<I>
|
||||
where
|
||||
I: FusedIterator<Item: IntoIterator<IntoIter = U, Item = U::Item>>,
|
||||
U: Iterator,
|
||||
{
|
||||
}
|
||||
|
||||
/// Real logic of both `Flatten` and `FlatMap` which simply delegate to
|
||||
/// this type.
|
||||
#[derive(Clone, Debug)]
|
||||
struct FlattenCompat<I, U> {
|
||||
iter: Fuse<I>,
|
||||
frontiter: Option<U>,
|
||||
backiter: Option<U>,
|
||||
}
|
||||
impl<I, U> FlattenCompat<I, U>
|
||||
where
|
||||
I: Iterator,
|
||||
{
|
||||
/// Adapts an iterator by flattening it, for use in `flatten()` and `flat_map()`.
|
||||
fn new(iter: I) -> FlattenCompat<I, U> {
|
||||
FlattenCompat { iter: iter.fuse(), frontiter: None, backiter: None }
|
||||
}
|
||||
}
|
||||
|
||||
impl<I, U> Iterator for FlattenCompat<I, U>
|
||||
where
|
||||
I: Iterator<Item: IntoIterator<IntoIter = U, Item = U::Item>>,
|
||||
U: Iterator,
|
||||
{
|
||||
type Item = U::Item;
|
||||
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<U::Item> {
|
||||
loop {
|
||||
if let Some(ref mut inner) = self.frontiter {
|
||||
match inner.next() {
|
||||
None => self.frontiter = None,
|
||||
elt @ Some(_) => return elt,
|
||||
}
|
||||
}
|
||||
match self.iter.next() {
|
||||
None => return self.backiter.as_mut()?.next(),
|
||||
Some(inner) => self.frontiter = Some(inner.into_iter()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
let (flo, fhi) = self.frontiter.as_ref().map_or((0, Some(0)), U::size_hint);
|
||||
let (blo, bhi) = self.backiter.as_ref().map_or((0, Some(0)), U::size_hint);
|
||||
let lo = flo.saturating_add(blo);
|
||||
match (self.iter.size_hint(), fhi, bhi) {
|
||||
((0, Some(0)), Some(a), Some(b)) => (lo, a.checked_add(b)),
|
||||
_ => (lo, None),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn try_fold<Acc, Fold, R>(&mut self, mut init: Acc, mut fold: Fold) -> R
|
||||
where
|
||||
Self: Sized,
|
||||
Fold: FnMut(Acc, Self::Item) -> R,
|
||||
R: Try<Ok = Acc>,
|
||||
{
|
||||
#[inline]
|
||||
fn flatten<'a, T: IntoIterator, Acc, R: Try<Ok = Acc>>(
|
||||
frontiter: &'a mut Option<T::IntoIter>,
|
||||
fold: &'a mut impl FnMut(Acc, T::Item) -> R,
|
||||
) -> impl FnMut(Acc, T) -> R + 'a {
|
||||
move |acc, x| {
|
||||
let mut mid = x.into_iter();
|
||||
let r = mid.try_fold(acc, &mut *fold);
|
||||
*frontiter = Some(mid);
|
||||
r
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(ref mut front) = self.frontiter {
|
||||
init = front.try_fold(init, &mut fold)?;
|
||||
}
|
||||
self.frontiter = None;
|
||||
|
||||
init = self.iter.try_fold(init, flatten(&mut self.frontiter, &mut fold))?;
|
||||
self.frontiter = None;
|
||||
|
||||
if let Some(ref mut back) = self.backiter {
|
||||
init = back.try_fold(init, &mut fold)?;
|
||||
}
|
||||
self.backiter = None;
|
||||
|
||||
try { init }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn fold<Acc, Fold>(self, init: Acc, ref mut fold: Fold) -> Acc
|
||||
where
|
||||
Fold: FnMut(Acc, Self::Item) -> Acc,
|
||||
{
|
||||
#[inline]
|
||||
fn flatten<U: Iterator, Acc>(
|
||||
fold: &mut impl FnMut(Acc, U::Item) -> Acc,
|
||||
) -> impl FnMut(Acc, U) -> Acc + '_ {
|
||||
move |acc, iter| iter.fold(acc, &mut *fold)
|
||||
}
|
||||
|
||||
self.frontiter
|
||||
.into_iter()
|
||||
.chain(self.iter.map(IntoIterator::into_iter))
|
||||
.chain(self.backiter)
|
||||
.fold(init, flatten(fold))
|
||||
}
|
||||
}
|
||||
|
||||
impl<I, U> DoubleEndedIterator for FlattenCompat<I, U>
|
||||
where
|
||||
I: DoubleEndedIterator<Item: IntoIterator<IntoIter = U, Item = U::Item>>,
|
||||
U: DoubleEndedIterator,
|
||||
{
|
||||
#[inline]
|
||||
fn next_back(&mut self) -> Option<U::Item> {
|
||||
loop {
|
||||
if let Some(ref mut inner) = self.backiter {
|
||||
match inner.next_back() {
|
||||
None => self.backiter = None,
|
||||
elt @ Some(_) => return elt,
|
||||
}
|
||||
}
|
||||
match self.iter.next_back() {
|
||||
None => return self.frontiter.as_mut()?.next_back(),
|
||||
next => self.backiter = next.map(IntoIterator::into_iter),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn try_rfold<Acc, Fold, R>(&mut self, mut init: Acc, mut fold: Fold) -> R
|
||||
where
|
||||
Self: Sized,
|
||||
Fold: FnMut(Acc, Self::Item) -> R,
|
||||
R: Try<Ok = Acc>,
|
||||
{
|
||||
#[inline]
|
||||
fn flatten<'a, T: IntoIterator, Acc, R: Try<Ok = Acc>>(
|
||||
backiter: &'a mut Option<T::IntoIter>,
|
||||
fold: &'a mut impl FnMut(Acc, T::Item) -> R,
|
||||
) -> impl FnMut(Acc, T) -> R + 'a
|
||||
where
|
||||
T::IntoIter: DoubleEndedIterator,
|
||||
{
|
||||
move |acc, x| {
|
||||
let mut mid = x.into_iter();
|
||||
let r = mid.try_rfold(acc, &mut *fold);
|
||||
*backiter = Some(mid);
|
||||
r
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(ref mut back) = self.backiter {
|
||||
init = back.try_rfold(init, &mut fold)?;
|
||||
}
|
||||
self.backiter = None;
|
||||
|
||||
init = self.iter.try_rfold(init, flatten(&mut self.backiter, &mut fold))?;
|
||||
self.backiter = None;
|
||||
|
||||
if let Some(ref mut front) = self.frontiter {
|
||||
init = front.try_rfold(init, &mut fold)?;
|
||||
}
|
||||
self.frontiter = None;
|
||||
|
||||
try { init }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn rfold<Acc, Fold>(self, init: Acc, ref mut fold: Fold) -> Acc
|
||||
where
|
||||
Fold: FnMut(Acc, Self::Item) -> Acc,
|
||||
{
|
||||
#[inline]
|
||||
fn flatten<U: DoubleEndedIterator, Acc>(
|
||||
fold: &mut impl FnMut(Acc, U::Item) -> Acc,
|
||||
) -> impl FnMut(Acc, U) -> Acc + '_ {
|
||||
move |acc, iter| iter.rfold(acc, &mut *fold)
|
||||
}
|
||||
|
||||
self.frontiter
|
||||
.into_iter()
|
||||
.chain(self.iter.map(IntoIterator::into_iter))
|
||||
.chain(self.backiter)
|
||||
.rfold(init, flatten(fold))
|
||||
}
|
||||
}
|
||||
540
libgrust/rustc-lib/core/src/iter/adapters/fuse.rs
Normal file
540
libgrust/rustc-lib/core/src/iter/adapters/fuse.rs
Normal file
@@ -0,0 +1,540 @@
|
||||
use super::InPlaceIterable;
|
||||
use crate::intrinsics;
|
||||
use crate::iter::adapters::zip::try_get_unchecked;
|
||||
use crate::iter::adapters::SourceIter;
|
||||
use crate::iter::TrustedRandomAccess;
|
||||
use crate::iter::{DoubleEndedIterator, ExactSizeIterator, FusedIterator, Iterator};
|
||||
use crate::ops::Try;
|
||||
|
||||
/// An iterator that yields `None` forever after the underlying iterator
|
||||
/// yields `None` once.
|
||||
///
|
||||
/// This `struct` is created by [`Iterator::fuse`]. See its documentation
|
||||
/// for more.
|
||||
#[derive(Clone, Debug)]
|
||||
#[must_use = "iterators are lazy and do nothing unless consumed"]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub struct Fuse<I> {
|
||||
// NOTE: for `I: FusedIterator`, this is always assumed `Some`!
|
||||
iter: Option<I>,
|
||||
}
|
||||
impl<I> Fuse<I> {
|
||||
pub(in crate::iter) fn new(iter: I) -> Fuse<I> {
|
||||
Fuse { iter: Some(iter) }
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "fused", since = "1.26.0")]
|
||||
impl<I> FusedIterator for Fuse<I> where I: Iterator {}
|
||||
|
||||
/// Fuse the iterator if the expression is `None`.
|
||||
macro_rules! fuse {
|
||||
($self:ident . iter . $($call:tt)+) => {
|
||||
match $self.iter {
|
||||
Some(ref mut iter) => match iter.$($call)+ {
|
||||
None => {
|
||||
$self.iter = None;
|
||||
None
|
||||
}
|
||||
item => item,
|
||||
},
|
||||
None => None,
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// NOTE: for `I: FusedIterator`, we assume that the iterator is always `Some`.
|
||||
// Implementing this as a directly-expanded macro helps codegen performance.
|
||||
macro_rules! unchecked {
|
||||
($self:ident) => {
|
||||
match $self {
|
||||
Fuse { iter: Some(iter) } => iter,
|
||||
// SAFETY: the specialized iterator never sets `None`
|
||||
Fuse { iter: None } => unsafe { intrinsics::unreachable() },
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Any implementation here is made internal to avoid exposing default fns outside this trait
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<I> Iterator for Fuse<I>
|
||||
where
|
||||
I: Iterator,
|
||||
{
|
||||
type Item = <I as Iterator>::Item;
|
||||
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
FuseImpl::next(self)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn nth(&mut self, n: usize) -> Option<I::Item> {
|
||||
FuseImpl::nth(self, n)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn last(self) -> Option<Self::Item> {
|
||||
FuseImpl::last(self)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn count(self) -> usize {
|
||||
FuseImpl::count(self)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
FuseImpl::size_hint(self)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn try_fold<Acc, Fold, R>(&mut self, acc: Acc, fold: Fold) -> R
|
||||
where
|
||||
Self: Sized,
|
||||
Fold: FnMut(Acc, Self::Item) -> R,
|
||||
R: Try<Ok = Acc>,
|
||||
{
|
||||
FuseImpl::try_fold(self, acc, fold)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn fold<Acc, Fold>(self, acc: Acc, fold: Fold) -> Acc
|
||||
where
|
||||
Fold: FnMut(Acc, Self::Item) -> Acc,
|
||||
{
|
||||
FuseImpl::fold(self, acc, fold)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn find<P>(&mut self, predicate: P) -> Option<Self::Item>
|
||||
where
|
||||
P: FnMut(&Self::Item) -> bool,
|
||||
{
|
||||
FuseImpl::find(self, predicate)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item
|
||||
where
|
||||
Self: TrustedRandomAccess,
|
||||
{
|
||||
match self.iter {
|
||||
// SAFETY: the caller must uphold the contract for
|
||||
// `Iterator::__iterator_get_unchecked`.
|
||||
Some(ref mut iter) => unsafe { try_get_unchecked(iter, idx) },
|
||||
// SAFETY: the caller asserts there is an item at `i`, so we're not exhausted.
|
||||
None => unsafe { intrinsics::unreachable() },
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<I> DoubleEndedIterator for Fuse<I>
|
||||
where
|
||||
I: DoubleEndedIterator,
|
||||
{
|
||||
#[inline]
|
||||
fn next_back(&mut self) -> Option<<I as Iterator>::Item> {
|
||||
FuseImpl::next_back(self)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn nth_back(&mut self, n: usize) -> Option<<I as Iterator>::Item> {
|
||||
FuseImpl::nth_back(self, n)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn try_rfold<Acc, Fold, R>(&mut self, acc: Acc, fold: Fold) -> R
|
||||
where
|
||||
Self: Sized,
|
||||
Fold: FnMut(Acc, Self::Item) -> R,
|
||||
R: Try<Ok = Acc>,
|
||||
{
|
||||
FuseImpl::try_rfold(self, acc, fold)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn rfold<Acc, Fold>(self, acc: Acc, fold: Fold) -> Acc
|
||||
where
|
||||
Fold: FnMut(Acc, Self::Item) -> Acc,
|
||||
{
|
||||
FuseImpl::rfold(self, acc, fold)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn rfind<P>(&mut self, predicate: P) -> Option<Self::Item>
|
||||
where
|
||||
P: FnMut(&Self::Item) -> bool,
|
||||
{
|
||||
FuseImpl::rfind(self, predicate)
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<I> ExactSizeIterator for Fuse<I>
|
||||
where
|
||||
I: ExactSizeIterator,
|
||||
{
|
||||
fn len(&self) -> usize {
|
||||
FuseImpl::len(self)
|
||||
}
|
||||
|
||||
fn is_empty(&self) -> bool {
|
||||
FuseImpl::is_empty(self)
|
||||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
#[unstable(feature = "trusted_random_access", issue = "none")]
|
||||
unsafe impl<I> TrustedRandomAccess for Fuse<I>
|
||||
where
|
||||
I: TrustedRandomAccess,
|
||||
{
|
||||
fn may_have_side_effect() -> bool {
|
||||
I::may_have_side_effect()
|
||||
}
|
||||
}
|
||||
|
||||
// Fuse specialization trait
|
||||
#[doc(hidden)]
|
||||
trait FuseImpl<I> {
|
||||
type Item;
|
||||
|
||||
// Functions specific to any normal Iterators
|
||||
fn next(&mut self) -> Option<Self::Item>;
|
||||
fn nth(&mut self, n: usize) -> Option<Self::Item>;
|
||||
fn last(self) -> Option<Self::Item>;
|
||||
fn count(self) -> usize;
|
||||
fn size_hint(&self) -> (usize, Option<usize>);
|
||||
fn try_fold<Acc, Fold, R>(&mut self, acc: Acc, fold: Fold) -> R
|
||||
where
|
||||
Self: Sized,
|
||||
Fold: FnMut(Acc, Self::Item) -> R,
|
||||
R: Try<Ok = Acc>;
|
||||
fn fold<Acc, Fold>(self, acc: Acc, fold: Fold) -> Acc
|
||||
where
|
||||
Fold: FnMut(Acc, Self::Item) -> Acc;
|
||||
fn find<P>(&mut self, predicate: P) -> Option<Self::Item>
|
||||
where
|
||||
P: FnMut(&Self::Item) -> bool;
|
||||
|
||||
// Functions specific to DoubleEndedIterators
|
||||
fn next_back(&mut self) -> Option<Self::Item>
|
||||
where
|
||||
I: DoubleEndedIterator;
|
||||
fn nth_back(&mut self, n: usize) -> Option<Self::Item>
|
||||
where
|
||||
I: DoubleEndedIterator;
|
||||
fn try_rfold<Acc, Fold, R>(&mut self, acc: Acc, fold: Fold) -> R
|
||||
where
|
||||
Self: Sized,
|
||||
Fold: FnMut(Acc, Self::Item) -> R,
|
||||
R: Try<Ok = Acc>,
|
||||
I: DoubleEndedIterator;
|
||||
fn rfold<Acc, Fold>(self, acc: Acc, fold: Fold) -> Acc
|
||||
where
|
||||
Fold: FnMut(Acc, Self::Item) -> Acc,
|
||||
I: DoubleEndedIterator;
|
||||
fn rfind<P>(&mut self, predicate: P) -> Option<Self::Item>
|
||||
where
|
||||
P: FnMut(&Self::Item) -> bool,
|
||||
I: DoubleEndedIterator;
|
||||
|
||||
// Functions specific to ExactSizeIterator
|
||||
fn len(&self) -> usize
|
||||
where
|
||||
I: ExactSizeIterator;
|
||||
fn is_empty(&self) -> bool
|
||||
where
|
||||
I: ExactSizeIterator;
|
||||
}
|
||||
|
||||
// General Fuse impl
|
||||
#[doc(hidden)]
|
||||
impl<I> FuseImpl<I> for Fuse<I>
|
||||
where
|
||||
I: Iterator,
|
||||
{
|
||||
type Item = <I as Iterator>::Item;
|
||||
|
||||
#[inline]
|
||||
default fn next(&mut self) -> Option<<I as Iterator>::Item> {
|
||||
fuse!(self.iter.next())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
default fn nth(&mut self, n: usize) -> Option<I::Item> {
|
||||
fuse!(self.iter.nth(n))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
default fn last(self) -> Option<I::Item> {
|
||||
match self.iter {
|
||||
Some(iter) => iter.last(),
|
||||
None => None,
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
default fn count(self) -> usize {
|
||||
match self.iter {
|
||||
Some(iter) => iter.count(),
|
||||
None => 0,
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
default fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
match self.iter {
|
||||
Some(ref iter) => iter.size_hint(),
|
||||
None => (0, Some(0)),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
default fn try_fold<Acc, Fold, R>(&mut self, mut acc: Acc, fold: Fold) -> R
|
||||
where
|
||||
Self: Sized,
|
||||
Fold: FnMut(Acc, Self::Item) -> R,
|
||||
R: Try<Ok = Acc>,
|
||||
{
|
||||
if let Some(ref mut iter) = self.iter {
|
||||
acc = iter.try_fold(acc, fold)?;
|
||||
self.iter = None;
|
||||
}
|
||||
try { acc }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
default fn fold<Acc, Fold>(self, mut acc: Acc, fold: Fold) -> Acc
|
||||
where
|
||||
Fold: FnMut(Acc, Self::Item) -> Acc,
|
||||
{
|
||||
if let Some(iter) = self.iter {
|
||||
acc = iter.fold(acc, fold);
|
||||
}
|
||||
acc
|
||||
}
|
||||
|
||||
#[inline]
|
||||
default fn find<P>(&mut self, predicate: P) -> Option<Self::Item>
|
||||
where
|
||||
P: FnMut(&Self::Item) -> bool,
|
||||
{
|
||||
fuse!(self.iter.find(predicate))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
default fn next_back(&mut self) -> Option<<I as Iterator>::Item>
|
||||
where
|
||||
I: DoubleEndedIterator,
|
||||
{
|
||||
fuse!(self.iter.next_back())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
default fn nth_back(&mut self, n: usize) -> Option<<I as Iterator>::Item>
|
||||
where
|
||||
I: DoubleEndedIterator,
|
||||
{
|
||||
fuse!(self.iter.nth_back(n))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
default fn try_rfold<Acc, Fold, R>(&mut self, mut acc: Acc, fold: Fold) -> R
|
||||
where
|
||||
Self: Sized,
|
||||
Fold: FnMut(Acc, Self::Item) -> R,
|
||||
R: Try<Ok = Acc>,
|
||||
I: DoubleEndedIterator,
|
||||
{
|
||||
if let Some(ref mut iter) = self.iter {
|
||||
acc = iter.try_rfold(acc, fold)?;
|
||||
self.iter = None;
|
||||
}
|
||||
try { acc }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
default fn rfold<Acc, Fold>(self, mut acc: Acc, fold: Fold) -> Acc
|
||||
where
|
||||
Fold: FnMut(Acc, Self::Item) -> Acc,
|
||||
I: DoubleEndedIterator,
|
||||
{
|
||||
if let Some(iter) = self.iter {
|
||||
acc = iter.rfold(acc, fold);
|
||||
}
|
||||
acc
|
||||
}
|
||||
|
||||
#[inline]
|
||||
default fn rfind<P>(&mut self, predicate: P) -> Option<Self::Item>
|
||||
where
|
||||
P: FnMut(&Self::Item) -> bool,
|
||||
I: DoubleEndedIterator,
|
||||
{
|
||||
fuse!(self.iter.rfind(predicate))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
default fn len(&self) -> usize
|
||||
where
|
||||
I: ExactSizeIterator,
|
||||
{
|
||||
match self.iter {
|
||||
Some(ref iter) => iter.len(),
|
||||
None => 0,
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
default fn is_empty(&self) -> bool
|
||||
where
|
||||
I: ExactSizeIterator,
|
||||
{
|
||||
match self.iter {
|
||||
Some(ref iter) => iter.is_empty(),
|
||||
None => true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
impl<I> FuseImpl<I> for Fuse<I>
|
||||
where
|
||||
I: FusedIterator,
|
||||
{
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<<I as Iterator>::Item> {
|
||||
unchecked!(self).next()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn nth(&mut self, n: usize) -> Option<I::Item> {
|
||||
unchecked!(self).nth(n)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn last(self) -> Option<I::Item> {
|
||||
unchecked!(self).last()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn count(self) -> usize {
|
||||
unchecked!(self).count()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
unchecked!(self).size_hint()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn try_fold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R
|
||||
where
|
||||
Self: Sized,
|
||||
Fold: FnMut(Acc, Self::Item) -> R,
|
||||
R: Try<Ok = Acc>,
|
||||
{
|
||||
unchecked!(self).try_fold(init, fold)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn fold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc
|
||||
where
|
||||
Fold: FnMut(Acc, Self::Item) -> Acc,
|
||||
{
|
||||
unchecked!(self).fold(init, fold)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn find<P>(&mut self, predicate: P) -> Option<Self::Item>
|
||||
where
|
||||
P: FnMut(&Self::Item) -> bool,
|
||||
{
|
||||
unchecked!(self).find(predicate)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn next_back(&mut self) -> Option<<I as Iterator>::Item>
|
||||
where
|
||||
I: DoubleEndedIterator,
|
||||
{
|
||||
unchecked!(self).next_back()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn nth_back(&mut self, n: usize) -> Option<<I as Iterator>::Item>
|
||||
where
|
||||
I: DoubleEndedIterator,
|
||||
{
|
||||
unchecked!(self).nth_back(n)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn try_rfold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R
|
||||
where
|
||||
Self: Sized,
|
||||
Fold: FnMut(Acc, Self::Item) -> R,
|
||||
R: Try<Ok = Acc>,
|
||||
I: DoubleEndedIterator,
|
||||
{
|
||||
unchecked!(self).try_rfold(init, fold)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn rfold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc
|
||||
where
|
||||
Fold: FnMut(Acc, Self::Item) -> Acc,
|
||||
I: DoubleEndedIterator,
|
||||
{
|
||||
unchecked!(self).rfold(init, fold)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn rfind<P>(&mut self, predicate: P) -> Option<Self::Item>
|
||||
where
|
||||
P: FnMut(&Self::Item) -> bool,
|
||||
I: DoubleEndedIterator,
|
||||
{
|
||||
unchecked!(self).rfind(predicate)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn len(&self) -> usize
|
||||
where
|
||||
I: ExactSizeIterator,
|
||||
{
|
||||
unchecked!(self).len()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn is_empty(&self) -> bool
|
||||
where
|
||||
I: ExactSizeIterator,
|
||||
{
|
||||
unchecked!(self).is_empty()
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(issue = "none", feature = "inplace_iteration")]
|
||||
unsafe impl<S: Iterator, I: FusedIterator> SourceIter for Fuse<I>
|
||||
where
|
||||
I: SourceIter<Source = S>,
|
||||
{
|
||||
type Source = S;
|
||||
|
||||
#[inline]
|
||||
unsafe fn as_inner(&mut self) -> &mut S {
|
||||
match self.iter {
|
||||
// SAFETY: unsafe function forwarding to unsafe function with the same requirements
|
||||
Some(ref mut iter) => unsafe { SourceIter::as_inner(iter) },
|
||||
// SAFETY: the specialized iterator never sets `None`
|
||||
None => unsafe { intrinsics::unreachable() },
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(issue = "none", feature = "inplace_iteration")]
|
||||
unsafe impl<I: InPlaceIterable> InPlaceIterable for Fuse<I> {}
|
||||
2968
libgrust/rustc-lib/core/src/iter/adapters/mod.rs
Normal file
2968
libgrust/rustc-lib/core/src/iter/adapters/mod.rs
Normal file
File diff suppressed because it is too large
Load Diff
465
libgrust/rustc-lib/core/src/iter/adapters/zip.rs
Normal file
465
libgrust/rustc-lib/core/src/iter/adapters/zip.rs
Normal file
@@ -0,0 +1,465 @@
|
||||
use crate::cmp;
|
||||
use crate::fmt::{self, Debug};
|
||||
|
||||
use super::super::{
|
||||
DoubleEndedIterator, ExactSizeIterator, FusedIterator, InPlaceIterable, Iterator, SourceIter,
|
||||
TrustedLen,
|
||||
};
|
||||
|
||||
/// An iterator that iterates two other iterators simultaneously.
|
||||
///
|
||||
/// This `struct` is created by [`Iterator::zip`]. See its documentation
|
||||
/// for more.
|
||||
#[derive(Clone)]
|
||||
#[must_use = "iterators are lazy and do nothing unless consumed"]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub struct Zip<A, B> {
|
||||
a: A,
|
||||
b: B,
|
||||
// index and len are only used by the specialized version of zip
|
||||
index: usize,
|
||||
len: usize,
|
||||
}
|
||||
impl<A: Iterator, B: Iterator> Zip<A, B> {
|
||||
pub(in super::super) fn new(a: A, b: B) -> Zip<A, B> {
|
||||
ZipImpl::new(a, b)
|
||||
}
|
||||
fn super_nth(&mut self, mut n: usize) -> Option<(A::Item, B::Item)> {
|
||||
while let Some(x) = Iterator::next(self) {
|
||||
if n == 0 {
|
||||
return Some(x);
|
||||
}
|
||||
n -= 1;
|
||||
}
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<A, B> Iterator for Zip<A, B>
|
||||
where
|
||||
A: Iterator,
|
||||
B: Iterator,
|
||||
{
|
||||
type Item = (A::Item, B::Item);
|
||||
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
ZipImpl::next(self)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
ZipImpl::size_hint(self)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn nth(&mut self, n: usize) -> Option<Self::Item> {
|
||||
ZipImpl::nth(self, n)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item
|
||||
where
|
||||
Self: TrustedRandomAccess,
|
||||
{
|
||||
// SAFETY: `ZipImpl::__iterator_get_unchecked` has same safety
|
||||
// requirements as `Iterator::__iterator_get_unchecked`.
|
||||
unsafe { ZipImpl::get_unchecked(self, idx) }
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<A, B> DoubleEndedIterator for Zip<A, B>
|
||||
where
|
||||
A: DoubleEndedIterator + ExactSizeIterator,
|
||||
B: DoubleEndedIterator + ExactSizeIterator,
|
||||
{
|
||||
#[inline]
|
||||
fn next_back(&mut self) -> Option<(A::Item, B::Item)> {
|
||||
ZipImpl::next_back(self)
|
||||
}
|
||||
}
|
||||
|
||||
// Zip specialization trait
|
||||
#[doc(hidden)]
|
||||
trait ZipImpl<A, B> {
|
||||
type Item;
|
||||
fn new(a: A, b: B) -> Self;
|
||||
fn next(&mut self) -> Option<Self::Item>;
|
||||
fn size_hint(&self) -> (usize, Option<usize>);
|
||||
fn nth(&mut self, n: usize) -> Option<Self::Item>;
|
||||
fn next_back(&mut self) -> Option<Self::Item>
|
||||
where
|
||||
A: DoubleEndedIterator + ExactSizeIterator,
|
||||
B: DoubleEndedIterator + ExactSizeIterator;
|
||||
// This has the same safety requirements as `Iterator::__iterator_get_unchecked`
|
||||
unsafe fn get_unchecked(&mut self, idx: usize) -> <Self as Iterator>::Item
|
||||
where
|
||||
Self: Iterator + TrustedRandomAccess;
|
||||
}
|
||||
|
||||
// General Zip impl
|
||||
#[doc(hidden)]
|
||||
impl<A, B> ZipImpl<A, B> for Zip<A, B>
|
||||
where
|
||||
A: Iterator,
|
||||
B: Iterator,
|
||||
{
|
||||
type Item = (A::Item, B::Item);
|
||||
default fn new(a: A, b: B) -> Self {
|
||||
Zip {
|
||||
a,
|
||||
b,
|
||||
index: 0, // unused
|
||||
len: 0, // unused
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
default fn next(&mut self) -> Option<(A::Item, B::Item)> {
|
||||
let x = self.a.next()?;
|
||||
let y = self.b.next()?;
|
||||
Some((x, y))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
default fn nth(&mut self, n: usize) -> Option<Self::Item> {
|
||||
self.super_nth(n)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
default fn next_back(&mut self) -> Option<(A::Item, B::Item)>
|
||||
where
|
||||
A: DoubleEndedIterator + ExactSizeIterator,
|
||||
B: DoubleEndedIterator + ExactSizeIterator,
|
||||
{
|
||||
let a_sz = self.a.len();
|
||||
let b_sz = self.b.len();
|
||||
if a_sz != b_sz {
|
||||
// Adjust a, b to equal length
|
||||
if a_sz > b_sz {
|
||||
for _ in 0..a_sz - b_sz {
|
||||
self.a.next_back();
|
||||
}
|
||||
} else {
|
||||
for _ in 0..b_sz - a_sz {
|
||||
self.b.next_back();
|
||||
}
|
||||
}
|
||||
}
|
||||
match (self.a.next_back(), self.b.next_back()) {
|
||||
(Some(x), Some(y)) => Some((x, y)),
|
||||
(None, None) => None,
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
default fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
let (a_lower, a_upper) = self.a.size_hint();
|
||||
let (b_lower, b_upper) = self.b.size_hint();
|
||||
|
||||
let lower = cmp::min(a_lower, b_lower);
|
||||
|
||||
let upper = match (a_upper, b_upper) {
|
||||
(Some(x), Some(y)) => Some(cmp::min(x, y)),
|
||||
(Some(x), None) => Some(x),
|
||||
(None, Some(y)) => Some(y),
|
||||
(None, None) => None,
|
||||
};
|
||||
|
||||
(lower, upper)
|
||||
}
|
||||
|
||||
default unsafe fn get_unchecked(&mut self, _idx: usize) -> <Self as Iterator>::Item
|
||||
where
|
||||
Self: TrustedRandomAccess,
|
||||
{
|
||||
unreachable!("Always specialized");
|
||||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
impl<A, B> ZipImpl<A, B> for Zip<A, B>
|
||||
where
|
||||
A: TrustedRandomAccess + Iterator,
|
||||
B: TrustedRandomAccess + Iterator,
|
||||
{
|
||||
fn new(a: A, b: B) -> Self {
|
||||
let len = cmp::min(a.size(), b.size());
|
||||
Zip { a, b, index: 0, len }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<(A::Item, B::Item)> {
|
||||
if self.index < self.len {
|
||||
let i = self.index;
|
||||
self.index += 1;
|
||||
// SAFETY: `i` is smaller than `self.len`, thus smaller than `self.a.len()` and `self.b.len()`
|
||||
unsafe {
|
||||
Some((self.a.__iterator_get_unchecked(i), self.b.__iterator_get_unchecked(i)))
|
||||
}
|
||||
} else if A::may_have_side_effect() && self.index < self.a.size() {
|
||||
// match the base implementation's potential side effects
|
||||
// SAFETY: we just checked that `self.index` < `self.a.len()`
|
||||
unsafe {
|
||||
self.a.__iterator_get_unchecked(self.index);
|
||||
}
|
||||
self.index += 1;
|
||||
None
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
let len = self.len - self.index;
|
||||
(len, Some(len))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn nth(&mut self, n: usize) -> Option<Self::Item> {
|
||||
let delta = cmp::min(n, self.len - self.index);
|
||||
let end = self.index + delta;
|
||||
while self.index < end {
|
||||
let i = self.index;
|
||||
self.index += 1;
|
||||
if A::may_have_side_effect() {
|
||||
// SAFETY: the usage of `cmp::min` to calculate `delta`
|
||||
// ensures that `end` is smaller than or equal to `self.len`,
|
||||
// so `i` is also smaller than `self.len`.
|
||||
unsafe {
|
||||
self.a.__iterator_get_unchecked(i);
|
||||
}
|
||||
}
|
||||
if B::may_have_side_effect() {
|
||||
// SAFETY: same as above.
|
||||
unsafe {
|
||||
self.b.__iterator_get_unchecked(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self.super_nth(n - delta)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn next_back(&mut self) -> Option<(A::Item, B::Item)>
|
||||
where
|
||||
A: DoubleEndedIterator + ExactSizeIterator,
|
||||
B: DoubleEndedIterator + ExactSizeIterator,
|
||||
{
|
||||
let a_side_effect = A::may_have_side_effect();
|
||||
let b_side_effect = B::may_have_side_effect();
|
||||
if a_side_effect || b_side_effect {
|
||||
let sz_a = self.a.size();
|
||||
let sz_b = self.b.size();
|
||||
// Adjust a, b to equal length, make sure that only the first call
|
||||
// of `next_back` does this, otherwise we will break the restriction
|
||||
// on calls to `self.next_back()` after calling `get_unchecked()`.
|
||||
if sz_a != sz_b {
|
||||
let sz_a = self.a.size();
|
||||
if a_side_effect && sz_a > self.len {
|
||||
for _ in 0..sz_a - cmp::max(self.len, self.index) {
|
||||
self.a.next_back();
|
||||
}
|
||||
}
|
||||
let sz_b = self.b.size();
|
||||
if b_side_effect && sz_b > self.len {
|
||||
for _ in 0..sz_b - self.len {
|
||||
self.b.next_back();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if self.index < self.len {
|
||||
self.len -= 1;
|
||||
let i = self.len;
|
||||
// SAFETY: `i` is smaller than the previous value of `self.len`,
|
||||
// which is also smaller than or equal to `self.a.len()` and `self.b.len()`
|
||||
unsafe {
|
||||
Some((self.a.__iterator_get_unchecked(i), self.b.__iterator_get_unchecked(i)))
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn get_unchecked(&mut self, idx: usize) -> <Self as Iterator>::Item {
|
||||
// SAFETY: the caller must uphold the contract for
|
||||
// `Iterator::__iterator_get_unchecked`.
|
||||
unsafe { (self.a.__iterator_get_unchecked(idx), self.b.__iterator_get_unchecked(idx)) }
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<A, B> ExactSizeIterator for Zip<A, B>
|
||||
where
|
||||
A: ExactSizeIterator,
|
||||
B: ExactSizeIterator,
|
||||
{
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
#[unstable(feature = "trusted_random_access", issue = "none")]
|
||||
unsafe impl<A, B> TrustedRandomAccess for Zip<A, B>
|
||||
where
|
||||
A: TrustedRandomAccess,
|
||||
B: TrustedRandomAccess,
|
||||
{
|
||||
fn may_have_side_effect() -> bool {
|
||||
A::may_have_side_effect() || B::may_have_side_effect()
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "fused", since = "1.26.0")]
|
||||
impl<A, B> FusedIterator for Zip<A, B>
|
||||
where
|
||||
A: FusedIterator,
|
||||
B: FusedIterator,
|
||||
{
|
||||
}
|
||||
|
||||
#[unstable(feature = "trusted_len", issue = "37572")]
|
||||
unsafe impl<A, B> TrustedLen for Zip<A, B>
|
||||
where
|
||||
A: TrustedLen,
|
||||
B: TrustedLen,
|
||||
{
|
||||
}
|
||||
|
||||
// Arbitrarily selects the left side of the zip iteration as extractable "source"
|
||||
// it would require negative trait bounds to be able to try both
|
||||
#[unstable(issue = "none", feature = "inplace_iteration")]
|
||||
unsafe impl<S, A, B> SourceIter for Zip<A, B>
|
||||
where
|
||||
A: SourceIter<Source = S>,
|
||||
B: Iterator,
|
||||
S: Iterator,
|
||||
{
|
||||
type Source = S;
|
||||
|
||||
#[inline]
|
||||
unsafe fn as_inner(&mut self) -> &mut S {
|
||||
// SAFETY: unsafe function forwarding to unsafe function with the same requirements
|
||||
unsafe { SourceIter::as_inner(&mut self.a) }
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(issue = "none", feature = "inplace_iteration")]
|
||||
// Limited to Item: Copy since interaction between Zip's use of TrustedRandomAccess
|
||||
// and Drop implementation of the source is unclear.
|
||||
//
|
||||
// An additional method returning the number of times the source has been logically advanced
|
||||
// (without calling next()) would be needed to properly drop the remainder of the source.
|
||||
unsafe impl<A: InPlaceIterable, B: Iterator> InPlaceIterable for Zip<A, B> where A::Item: Copy {}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<A: Debug, B: Debug> Debug for Zip<A, B> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
ZipFmt::fmt(self, f)
|
||||
}
|
||||
}
|
||||
|
||||
trait ZipFmt<A, B> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result;
|
||||
}
|
||||
|
||||
impl<A: Debug, B: Debug> ZipFmt<A, B> for Zip<A, B> {
|
||||
default fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("Zip").field("a", &self.a).field("b", &self.b).finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl<A: Debug + TrustedRandomAccess, B: Debug + TrustedRandomAccess> ZipFmt<A, B> for Zip<A, B> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
// It's *not safe* to call fmt on the contained iterators, since once
|
||||
// we start iterating they're in strange, potentially unsafe, states.
|
||||
f.debug_struct("Zip").finish()
|
||||
}
|
||||
}
|
||||
|
||||
/// An iterator whose items are random-accessible efficiently
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The iterator's `size_hint` must be exact and cheap to call.
|
||||
///
|
||||
/// `size` may not be overridden.
|
||||
///
|
||||
/// `<Self as Iterator>::__iterator_get_unchecked` must be safe to call
|
||||
/// provided the following conditions are met.
|
||||
///
|
||||
/// 1. `0 <= idx` and `idx < self.size()`.
|
||||
/// 2. If `self: !Clone`, then `get_unchecked` is never called with the same
|
||||
/// index on `self` more than once.
|
||||
/// 3. After `self.get_unchecked(idx)` has been called then `next_back` will
|
||||
/// only be called at most `self.size() - idx - 1` times.
|
||||
/// 4. After `get_unchecked` is called, then only the following methods will be
|
||||
/// called on `self`:
|
||||
/// * `std::clone::Clone::clone`
|
||||
/// * `std::iter::Iterator::size_hint()`
|
||||
/// * `std::iter::Iterator::next_back()`
|
||||
/// * `std::iter::Iterator::__iterator_get_unchecked()`
|
||||
/// * `std::iter::TrustedRandomAccess::size()`
|
||||
///
|
||||
/// Further, given that these conditions are met, it must guarantee that:
|
||||
///
|
||||
/// * It does not change the value returned from `size_hint`
|
||||
/// * It must be safe to call the methods listed above on `self` after calling
|
||||
/// `get_unchecked`, assuming that the required traits are implemented.
|
||||
/// * It must also be safe to drop `self` after calling `get_unchecked`.
|
||||
#[doc(hidden)]
|
||||
#[unstable(feature = "trusted_random_access", issue = "none")]
|
||||
#[rustc_specialization_trait]
|
||||
pub unsafe trait TrustedRandomAccess: Sized {
|
||||
// Convenience method.
|
||||
fn size(&self) -> usize
|
||||
where
|
||||
Self: Iterator,
|
||||
{
|
||||
self.size_hint().0
|
||||
}
|
||||
/// Returns `true` if getting an iterator element may have
|
||||
/// side effects. Remember to take inner iterators into account.
|
||||
fn may_have_side_effect() -> bool;
|
||||
}
|
||||
|
||||
/// Like `Iterator::__iterator_get_unchecked`, but doesn't require the compiler to
|
||||
/// know that `U: TrustedRandomAccess`.
|
||||
///
|
||||
/// ## Safety
|
||||
///
|
||||
/// Same requirements calling `get_unchecked` directly.
|
||||
#[doc(hidden)]
|
||||
pub(in crate::iter::adapters) unsafe fn try_get_unchecked<I>(it: &mut I, idx: usize) -> I::Item
|
||||
where
|
||||
I: Iterator,
|
||||
{
|
||||
// SAFETY: the caller must uphold the contract for
|
||||
// `Iterator::__iterator_get_unchecked`.
|
||||
unsafe { it.try_get_unchecked(idx) }
|
||||
}
|
||||
|
||||
unsafe trait SpecTrustedRandomAccess: Iterator {
|
||||
/// If `Self: TrustedRandomAccess`, it must be safe to call a
|
||||
/// `Iterator::__iterator_get_unchecked(self, index)`.
|
||||
unsafe fn try_get_unchecked(&mut self, index: usize) -> Self::Item;
|
||||
}
|
||||
|
||||
unsafe impl<I: Iterator> SpecTrustedRandomAccess for I {
|
||||
default unsafe fn try_get_unchecked(&mut self, _: usize) -> Self::Item {
|
||||
panic!("Should only be called on TrustedRandomAccess iterators");
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<I: Iterator + TrustedRandomAccess> SpecTrustedRandomAccess for I {
|
||||
unsafe fn try_get_unchecked(&mut self, index: usize) -> Self::Item {
|
||||
// SAFETY: the caller must uphold the contract for
|
||||
// `Iterator::__iterator_get_unchecked`.
|
||||
unsafe { self.__iterator_get_unchecked(index) }
|
||||
}
|
||||
}
|
||||
375
libgrust/rustc-lib/core/src/iter/mod.rs
Normal file
375
libgrust/rustc-lib/core/src/iter/mod.rs
Normal file
@@ -0,0 +1,375 @@
|
||||
//! Composable external iteration.
|
||||
//!
|
||||
//! If you've found yourself with a collection of some kind, and needed to
|
||||
//! perform an operation on the elements of said collection, you'll quickly run
|
||||
//! into 'iterators'. Iterators are heavily used in idiomatic Rust code, so
|
||||
//! it's worth becoming familiar with them.
|
||||
//!
|
||||
//! Before explaining more, let's talk about how this module is structured:
|
||||
//!
|
||||
//! # Organization
|
||||
//!
|
||||
//! This module is largely organized by type:
|
||||
//!
|
||||
//! * [Traits] are the core portion: these traits define what kind of iterators
|
||||
//! exist and what you can do with them. The methods of these traits are worth
|
||||
//! putting some extra study time into.
|
||||
//! * [Functions] provide some helpful ways to create some basic iterators.
|
||||
//! * [Structs] are often the return types of the various methods on this
|
||||
//! module's traits. You'll usually want to look at the method that creates
|
||||
//! the `struct`, rather than the `struct` itself. For more detail about why,
|
||||
//! see '[Implementing Iterator](#implementing-iterator)'.
|
||||
//!
|
||||
//! [Traits]: #traits
|
||||
//! [Functions]: #functions
|
||||
//! [Structs]: #structs
|
||||
//!
|
||||
//! That's it! Let's dig into iterators.
|
||||
//!
|
||||
//! # Iterator
|
||||
//!
|
||||
//! The heart and soul of this module is the [`Iterator`] trait. The core of
|
||||
//! [`Iterator`] looks like this:
|
||||
//!
|
||||
//! ```
|
||||
//! trait Iterator {
|
||||
//! type Item;
|
||||
//! fn next(&mut self) -> Option<Self::Item>;
|
||||
//! }
|
||||
//! ```
|
||||
//!
|
||||
//! An iterator has a method, [`next`], which when called, returns an
|
||||
//! [`Option`]`<Item>`. [`next`] will return [`Some(Item)`] as long as there
|
||||
//! are elements, and once they've all been exhausted, will return `None` to
|
||||
//! indicate that iteration is finished. Individual iterators may choose to
|
||||
//! resume iteration, and so calling [`next`] again may or may not eventually
|
||||
//! start returning [`Some(Item)`] again at some point (for example, see [`TryIter`]).
|
||||
//!
|
||||
//! [`Iterator`]'s full definition includes a number of other methods as well,
|
||||
//! but they are default methods, built on top of [`next`], and so you get
|
||||
//! them for free.
|
||||
//!
|
||||
//! Iterators are also composable, and it's common to chain them together to do
|
||||
//! more complex forms of processing. See the [Adapters](#adapters) section
|
||||
//! below for more details.
|
||||
//!
|
||||
//! [`Some(Item)`]: Some
|
||||
//! [`next`]: Iterator::next
|
||||
//! [`TryIter`]: ../../std/sync/mpsc/struct.TryIter.html
|
||||
//!
|
||||
//! # The three forms of iteration
|
||||
//!
|
||||
//! There are three common methods which can create iterators from a collection:
|
||||
//!
|
||||
//! * `iter()`, which iterates over `&T`.
|
||||
//! * `iter_mut()`, which iterates over `&mut T`.
|
||||
//! * `into_iter()`, which iterates over `T`.
|
||||
//!
|
||||
//! Various things in the standard library may implement one or more of the
|
||||
//! three, where appropriate.
|
||||
//!
|
||||
//! # Implementing Iterator
|
||||
//!
|
||||
//! Creating an iterator of your own involves two steps: creating a `struct` to
|
||||
//! hold the iterator's state, and then implementing [`Iterator`] for that `struct`.
|
||||
//! This is why there are so many `struct`s in this module: there is one for
|
||||
//! each iterator and iterator adapter.
|
||||
//!
|
||||
//! Let's make an iterator named `Counter` which counts from `1` to `5`:
|
||||
//!
|
||||
//! ```
|
||||
//! // First, the struct:
|
||||
//!
|
||||
//! /// An iterator which counts from one to five
|
||||
//! struct Counter {
|
||||
//! count: usize,
|
||||
//! }
|
||||
//!
|
||||
//! // we want our count to start at one, so let's add a new() method to help.
|
||||
//! // This isn't strictly necessary, but is convenient. Note that we start
|
||||
//! // `count` at zero, we'll see why in `next()`'s implementation below.
|
||||
//! impl Counter {
|
||||
//! fn new() -> Counter {
|
||||
//! Counter { count: 0 }
|
||||
//! }
|
||||
//! }
|
||||
//!
|
||||
//! // Then, we implement `Iterator` for our `Counter`:
|
||||
//!
|
||||
//! impl Iterator for Counter {
|
||||
//! // we will be counting with usize
|
||||
//! type Item = usize;
|
||||
//!
|
||||
//! // next() is the only required method
|
||||
//! fn next(&mut self) -> Option<Self::Item> {
|
||||
//! // Increment our count. This is why we started at zero.
|
||||
//! self.count += 1;
|
||||
//!
|
||||
//! // Check to see if we've finished counting or not.
|
||||
//! if self.count < 6 {
|
||||
//! Some(self.count)
|
||||
//! } else {
|
||||
//! None
|
||||
//! }
|
||||
//! }
|
||||
//! }
|
||||
//!
|
||||
//! // And now we can use it!
|
||||
//!
|
||||
//! let mut counter = Counter::new();
|
||||
//!
|
||||
//! assert_eq!(counter.next(), Some(1));
|
||||
//! assert_eq!(counter.next(), Some(2));
|
||||
//! assert_eq!(counter.next(), Some(3));
|
||||
//! assert_eq!(counter.next(), Some(4));
|
||||
//! assert_eq!(counter.next(), Some(5));
|
||||
//! assert_eq!(counter.next(), None);
|
||||
//! ```
|
||||
//!
|
||||
//! Calling [`next`] this way gets repetitive. Rust has a construct which can
|
||||
//! call [`next`] on your iterator, until it reaches `None`. Let's go over that
|
||||
//! next.
|
||||
//!
|
||||
//! Also note that `Iterator` provides a default implementation of methods such as `nth` and `fold`
|
||||
//! which call `next` internally. However, it is also possible to write a custom implementation of
|
||||
//! methods like `nth` and `fold` if an iterator can compute them more efficiently without calling
|
||||
//! `next`.
|
||||
//!
|
||||
//! # `for` loops and `IntoIterator`
|
||||
//!
|
||||
//! Rust's `for` loop syntax is actually sugar for iterators. Here's a basic
|
||||
//! example of `for`:
|
||||
//!
|
||||
//! ```
|
||||
//! let values = vec![1, 2, 3, 4, 5];
|
||||
//!
|
||||
//! for x in values {
|
||||
//! println!("{}", x);
|
||||
//! }
|
||||
//! ```
|
||||
//!
|
||||
//! This will print the numbers one through five, each on their own line. But
|
||||
//! you'll notice something here: we never called anything on our vector to
|
||||
//! produce an iterator. What gives?
|
||||
//!
|
||||
//! There's a trait in the standard library for converting something into an
|
||||
//! iterator: [`IntoIterator`]. This trait has one method, [`into_iter`],
|
||||
//! which converts the thing implementing [`IntoIterator`] into an iterator.
|
||||
//! Let's take a look at that `for` loop again, and what the compiler converts
|
||||
//! it into:
|
||||
//!
|
||||
//! [`into_iter`]: IntoIterator::into_iter
|
||||
//!
|
||||
//! ```
|
||||
//! let values = vec![1, 2, 3, 4, 5];
|
||||
//!
|
||||
//! for x in values {
|
||||
//! println!("{}", x);
|
||||
//! }
|
||||
//! ```
|
||||
//!
|
||||
//! Rust de-sugars this into:
|
||||
//!
|
||||
//! ```
|
||||
//! let values = vec![1, 2, 3, 4, 5];
|
||||
//! {
|
||||
//! let result = match IntoIterator::into_iter(values) {
|
||||
//! mut iter => loop {
|
||||
//! let next;
|
||||
//! match iter.next() {
|
||||
//! Some(val) => next = val,
|
||||
//! None => break,
|
||||
//! };
|
||||
//! let x = next;
|
||||
//! let () = { println!("{}", x); };
|
||||
//! },
|
||||
//! };
|
||||
//! result
|
||||
//! }
|
||||
//! ```
|
||||
//!
|
||||
//! First, we call `into_iter()` on the value. Then, we match on the iterator
|
||||
//! that returns, calling [`next`] over and over until we see a `None`. At
|
||||
//! that point, we `break` out of the loop, and we're done iterating.
|
||||
//!
|
||||
//! There's one more subtle bit here: the standard library contains an
|
||||
//! interesting implementation of [`IntoIterator`]:
|
||||
//!
|
||||
//! ```ignore (only-for-syntax-highlight)
|
||||
//! impl<I: Iterator> IntoIterator for I
|
||||
//! ```
|
||||
//!
|
||||
//! In other words, all [`Iterator`]s implement [`IntoIterator`], by just
|
||||
//! returning themselves. This means two things:
|
||||
//!
|
||||
//! 1. If you're writing an [`Iterator`], you can use it with a `for` loop.
|
||||
//! 2. If you're creating a collection, implementing [`IntoIterator`] for it
|
||||
//! will allow your collection to be used with the `for` loop.
|
||||
//!
|
||||
//! # Adapters
|
||||
//!
|
||||
//! Functions which take an [`Iterator`] and return another [`Iterator`] are
|
||||
//! often called 'iterator adapters', as they're a form of the 'adapter
|
||||
//! pattern'.
|
||||
//!
|
||||
//! Common iterator adapters include [`map`], [`take`], and [`filter`].
|
||||
//! For more, see their documentation.
|
||||
//!
|
||||
//! If an iterator adapter panics, the iterator will be in an unspecified (but
|
||||
//! memory safe) state. This state is also not guaranteed to stay the same
|
||||
//! across versions of Rust, so you should avoid relying on the exact values
|
||||
//! returned by an iterator which panicked.
|
||||
//!
|
||||
//! [`map`]: Iterator::map
|
||||
//! [`take`]: Iterator::take
|
||||
//! [`filter`]: Iterator::filter
|
||||
//!
|
||||
//! # Laziness
|
||||
//!
|
||||
//! Iterators (and iterator [adapters](#adapters)) are *lazy*. This means that
|
||||
//! just creating an iterator doesn't _do_ a whole lot. Nothing really happens
|
||||
//! until you call [`next`]. This is sometimes a source of confusion when
|
||||
//! creating an iterator solely for its side effects. For example, the [`map`]
|
||||
//! method calls a closure on each element it iterates over:
|
||||
//!
|
||||
//! ```
|
||||
//! # #![allow(unused_must_use)]
|
||||
//! let v = vec![1, 2, 3, 4, 5];
|
||||
//! v.iter().map(|x| println!("{}", x));
|
||||
//! ```
|
||||
//!
|
||||
//! This will not print any values, as we only created an iterator, rather than
|
||||
//! using it. The compiler will warn us about this kind of behavior:
|
||||
//!
|
||||
//! ```text
|
||||
//! warning: unused result that must be used: iterators are lazy and
|
||||
//! do nothing unless consumed
|
||||
//! ```
|
||||
//!
|
||||
//! The idiomatic way to write a [`map`] for its side effects is to use a
|
||||
//! `for` loop or call the [`for_each`] method:
|
||||
//!
|
||||
//! ```
|
||||
//! let v = vec![1, 2, 3, 4, 5];
|
||||
//!
|
||||
//! v.iter().for_each(|x| println!("{}", x));
|
||||
//! // or
|
||||
//! for x in &v {
|
||||
//! println!("{}", x);
|
||||
//! }
|
||||
//! ```
|
||||
//!
|
||||
//! [`map`]: Iterator::map
|
||||
//! [`for_each`]: Iterator::for_each
|
||||
//!
|
||||
//! Another common way to evaluate an iterator is to use the [`collect`]
|
||||
//! method to produce a new collection.
|
||||
//!
|
||||
//! [`collect`]: Iterator::collect
|
||||
//!
|
||||
//! # Infinity
|
||||
//!
|
||||
//! Iterators do not have to be finite. As an example, an open-ended range is
|
||||
//! an infinite iterator:
|
||||
//!
|
||||
//! ```
|
||||
//! let numbers = 0..;
|
||||
//! ```
|
||||
//!
|
||||
//! It is common to use the [`take`] iterator adapter to turn an infinite
|
||||
//! iterator into a finite one:
|
||||
//!
|
||||
//! ```
|
||||
//! let numbers = 0..;
|
||||
//! let five_numbers = numbers.take(5);
|
||||
//!
|
||||
//! for number in five_numbers {
|
||||
//! println!("{}", number);
|
||||
//! }
|
||||
//! ```
|
||||
//!
|
||||
//! This will print the numbers `0` through `4`, each on their own line.
|
||||
//!
|
||||
//! Bear in mind that methods on infinite iterators, even those for which a
|
||||
//! result can be determined mathematically in finite time, may not terminate.
|
||||
//! Specifically, methods such as [`min`], which in the general case require
|
||||
//! traversing every element in the iterator, are likely not to return
|
||||
//! successfully for any infinite iterators.
|
||||
//!
|
||||
//! ```no_run
|
||||
//! let ones = std::iter::repeat(1);
|
||||
//! let least = ones.min().unwrap(); // Oh no! An infinite loop!
|
||||
//! // `ones.min()` causes an infinite loop, so we won't reach this point!
|
||||
//! println!("The smallest number one is {}.", least);
|
||||
//! ```
|
||||
//!
|
||||
//! [`take`]: Iterator::take
|
||||
//! [`min`]: Iterator::min
|
||||
|
||||
#![stable(feature = "rust1", since = "1.0.0")]
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use self::traits::Iterator;
|
||||
|
||||
#[unstable(
|
||||
feature = "step_trait",
|
||||
reason = "likely to be replaced by finer-grained traits",
|
||||
issue = "42168"
|
||||
)]
|
||||
pub use self::range::Step;
|
||||
|
||||
#[stable(feature = "iter_empty", since = "1.2.0")]
|
||||
pub use self::sources::{empty, Empty};
|
||||
#[stable(feature = "iter_from_fn", since = "1.34.0")]
|
||||
pub use self::sources::{from_fn, FromFn};
|
||||
#[stable(feature = "iter_once", since = "1.2.0")]
|
||||
pub use self::sources::{once, Once};
|
||||
#[stable(feature = "iter_once_with", since = "1.43.0")]
|
||||
pub use self::sources::{once_with, OnceWith};
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use self::sources::{repeat, Repeat};
|
||||
#[stable(feature = "iterator_repeat_with", since = "1.28.0")]
|
||||
pub use self::sources::{repeat_with, RepeatWith};
|
||||
#[stable(feature = "iter_successors", since = "1.34.0")]
|
||||
pub use self::sources::{successors, Successors};
|
||||
|
||||
#[stable(feature = "fused", since = "1.26.0")]
|
||||
pub use self::traits::FusedIterator;
|
||||
#[unstable(feature = "trusted_len", issue = "37572")]
|
||||
pub use self::traits::TrustedLen;
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use self::traits::{DoubleEndedIterator, Extend, FromIterator, IntoIterator};
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use self::traits::{ExactSizeIterator, Product, Sum};
|
||||
|
||||
#[unstable(issue = "none", feature = "inplace_iteration")]
|
||||
pub use self::traits::InPlaceIterable;
|
||||
|
||||
#[stable(feature = "iter_cloned", since = "1.1.0")]
|
||||
pub use self::adapters::Cloned;
|
||||
#[stable(feature = "iter_copied", since = "1.36.0")]
|
||||
pub use self::adapters::Copied;
|
||||
#[stable(feature = "iterator_flatten", since = "1.29.0")]
|
||||
pub use self::adapters::Flatten;
|
||||
|
||||
#[unstable(feature = "iter_map_while", reason = "recently added", issue = "68537")]
|
||||
pub use self::adapters::MapWhile;
|
||||
#[unstable(issue = "none", feature = "inplace_iteration")]
|
||||
pub use self::adapters::SourceIter;
|
||||
#[stable(feature = "iterator_step_by", since = "1.28.0")]
|
||||
pub use self::adapters::StepBy;
|
||||
#[unstable(feature = "trusted_random_access", issue = "none")]
|
||||
pub use self::adapters::TrustedRandomAccess;
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use self::adapters::{Chain, Cycle, Enumerate, Filter, FilterMap, Map, Rev, Zip};
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use self::adapters::{FlatMap, Peekable, Scan, Skip, SkipWhile, Take, TakeWhile};
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use self::adapters::{Fuse, Inspect};
|
||||
|
||||
pub(crate) use self::adapters::process_results;
|
||||
|
||||
mod adapters;
|
||||
mod range;
|
||||
mod sources;
|
||||
mod traits;
|
||||
861
libgrust/rustc-lib/core/src/iter/range.rs
Normal file
861
libgrust/rustc-lib/core/src/iter/range.rs
Normal file
@@ -0,0 +1,861 @@
|
||||
use crate::char;
|
||||
use crate::convert::TryFrom;
|
||||
use crate::mem;
|
||||
use crate::ops::{self, Add, Sub, Try};
|
||||
|
||||
use super::{FusedIterator, TrustedLen};
|
||||
|
||||
/// Objects that have a notion of *successor* and *predecessor* operations.
|
||||
///
|
||||
/// The *successor* operation moves towards values that compare greater.
|
||||
/// The *predecessor* operation moves towards values that compare lesser.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// This trait is `unsafe` because its implementation must be correct for
|
||||
/// the safety of `unsafe trait TrustedLen` implementations, and the results
|
||||
/// of using this trait can otherwise be trusted by `unsafe` code to be correct
|
||||
/// and fulfill the listed obligations.
|
||||
#[unstable(feature = "step_trait", reason = "recently redesigned", issue = "42168")]
|
||||
pub unsafe trait Step: Clone + PartialOrd + Sized {
|
||||
/// Returns the number of *successor* steps required to get from `start` to `end`.
|
||||
///
|
||||
/// Returns `None` if the number of steps would overflow `usize`
|
||||
/// (or is infinite, or if `end` would never be reached).
|
||||
///
|
||||
/// # Invariants
|
||||
///
|
||||
/// For any `a`, `b`, and `n`:
|
||||
///
|
||||
/// * `steps_between(&a, &b) == Some(n)` if and only if `Step::forward_checked(&a, n) == Some(b)`
|
||||
/// * `steps_between(&a, &b) == Some(n)` if and only if `Step::backward_checked(&a, n) == Some(a)`
|
||||
/// * `steps_between(&a, &b) == Some(n)` only if `a <= b`
|
||||
/// * Corollary: `steps_between(&a, &b) == Some(0)` if and only if `a == b`
|
||||
/// * Note that `a <= b` does _not_ imply `steps_between(&a, &b) != None`;
|
||||
/// this is the case when it would require more than `usize::MAX` steps to get to `b`
|
||||
/// * `steps_between(&a, &b) == None` if `a > b`
|
||||
fn steps_between(start: &Self, end: &Self) -> Option<usize>;
|
||||
|
||||
/// Returns the value that would be obtained by taking the *successor*
|
||||
/// of `self` `count` times.
|
||||
///
|
||||
/// If this would overflow the range of values supported by `Self`, returns `None`.
|
||||
///
|
||||
/// # Invariants
|
||||
///
|
||||
/// For any `a`, `n`, and `m`:
|
||||
///
|
||||
/// * `Step::forward_checked(a, n).and_then(|x| Step::forward_checked(x, m)) == Step::forward_checked(a, m).and_then(|x| Step::forward_checked(x, n))`
|
||||
///
|
||||
/// For any `a`, `n`, and `m` where `n + m` does not overflow:
|
||||
///
|
||||
/// * `Step::forward_checked(a, n).and_then(|x| Step::forward_checked(x, m)) == Step::forward_checked(a, n + m)`
|
||||
///
|
||||
/// For any `a` and `n`:
|
||||
///
|
||||
/// * `Step::forward_checked(a, n) == (0..n).try_fold(a, |x, _| Step::forward_checked(&x, 1))`
|
||||
/// * Corollary: `Step::forward_checked(&a, 0) == Some(a)`
|
||||
#[unstable(feature = "step_trait_ext", reason = "recently added", issue = "42168")]
|
||||
fn forward_checked(start: Self, count: usize) -> Option<Self>;
|
||||
|
||||
/// Returns the value that would be obtained by taking the *successor*
|
||||
/// of `self` `count` times.
|
||||
///
|
||||
/// If this would overflow the range of values supported by `Self`,
|
||||
/// this function is allowed to panic, wrap, or saturate.
|
||||
/// The suggested behavior is to panic when debug assertions are enabled,
|
||||
/// and to wrap or saturate otherwise.
|
||||
///
|
||||
/// Unsafe code should not rely on the correctness of behavior after overflow.
|
||||
///
|
||||
/// # Invariants
|
||||
///
|
||||
/// For any `a`, `n`, and `m`, where no overflow occurs:
|
||||
///
|
||||
/// * `Step::forward(Step::forward(a, n), m) == Step::forward(a, n + m)`
|
||||
///
|
||||
/// For any `a` and `n`, where no overflow occurs:
|
||||
///
|
||||
/// * `Step::forward_checked(a, n) == Some(Step::forward(a, n))`
|
||||
/// * `Step::forward(a, n) == (0..n).fold(a, |x, _| Step::forward(x, 1))`
|
||||
/// * Corollary: `Step::forward(a, 0) == a`
|
||||
/// * `Step::forward(a, n) >= a`
|
||||
/// * `Step::backward(Step::forward(a, n), n) == a`
|
||||
#[unstable(feature = "step_trait_ext", reason = "recently added", issue = "42168")]
|
||||
fn forward(start: Self, count: usize) -> Self {
|
||||
Step::forward_checked(start, count).expect("overflow in `Step::forward`")
|
||||
}
|
||||
|
||||
/// Returns the value that would be obtained by taking the *successor*
|
||||
/// of `self` `count` times.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// It is undefined behavior for this operation to overflow the
|
||||
/// range of values supported by `Self`. If you cannot guarantee that this
|
||||
/// will not overflow, use `forward` or `forward_checked` instead.
|
||||
///
|
||||
/// # Invariants
|
||||
///
|
||||
/// For any `a`:
|
||||
///
|
||||
/// * if there exists `b` such that `b > a`, it is safe to call `Step::forward_unchecked(a, 1)`
|
||||
/// * if there exists `b`, `n` such that `steps_between(&a, &b) == Some(n)`,
|
||||
/// it is safe to call `Step::forward_unchecked(a, m)` for any `m <= n`.
|
||||
///
|
||||
/// For any `a` and `n`, where no overflow occurs:
|
||||
///
|
||||
/// * `Step::forward_unchecked(a, n)` is equivalent to `Step::forward(a, n)`
|
||||
#[unstable(feature = "unchecked_math", reason = "niche optimization path", issue = "none")]
|
||||
unsafe fn forward_unchecked(start: Self, count: usize) -> Self {
|
||||
Step::forward(start, count)
|
||||
}
|
||||
|
||||
/// Returns the value that would be obtained by taking the *successor*
|
||||
/// of `self` `count` times.
|
||||
///
|
||||
/// If this would overflow the range of values supported by `Self`, returns `None`.
|
||||
///
|
||||
/// # Invariants
|
||||
///
|
||||
/// For any `a`, `n`, and `m`:
|
||||
///
|
||||
/// * `Step::backward_checked(a, n).and_then(|x| Step::backward_checked(x, m)) == n.checked_add(m).and_then(|x| Step::backward_checked(a, x))`
|
||||
/// * `Step::backward_checked(a, n).and_then(|x| Step::backward_checked(x, m)) == try { Step::backward_checked(a, n.checked_add(m)?) }`
|
||||
///
|
||||
/// For any `a` and `n`:
|
||||
///
|
||||
/// * `Step::backward_checked(a, n) == (0..n).try_fold(a, |x, _| Step::backward_checked(&x, 1))`
|
||||
/// * Corollary: `Step::backward_checked(&a, 0) == Some(a)`
|
||||
#[unstable(feature = "step_trait_ext", reason = "recently added", issue = "42168")]
|
||||
fn backward_checked(start: Self, count: usize) -> Option<Self>;
|
||||
|
||||
/// Returns the value that would be obtained by taking the *predecessor*
|
||||
/// of `self` `count` times.
|
||||
///
|
||||
/// If this would overflow the range of values supported by `Self`,
|
||||
/// this function is allowed to panic, wrap, or saturate.
|
||||
/// The suggested behavior is to panic when debug assertions are enabled,
|
||||
/// and to wrap or saturate otherwise.
|
||||
///
|
||||
/// Unsafe code should not rely on the correctness of behavior after overflow.
|
||||
///
|
||||
/// # Invariants
|
||||
///
|
||||
/// For any `a`, `n`, and `m`, where no overflow occurs:
|
||||
///
|
||||
/// * `Step::backward(Step::backward(a, n), m) == Step::backward(a, n + m)`
|
||||
///
|
||||
/// For any `a` and `n`, where no overflow occurs:
|
||||
///
|
||||
/// * `Step::backward_checked(a, n) == Some(Step::backward(a, n))`
|
||||
/// * `Step::backward(a, n) == (0..n).fold(a, |x, _| Step::backward(x, 1))`
|
||||
/// * Corollary: `Step::backward(a, 0) == a`
|
||||
/// * `Step::backward(a, n) <= a`
|
||||
/// * `Step::forward(Step::backward(a, n), n) == a`
|
||||
#[unstable(feature = "step_trait_ext", reason = "recently added", issue = "42168")]
|
||||
fn backward(start: Self, count: usize) -> Self {
|
||||
Step::backward_checked(start, count).expect("overflow in `Step::backward`")
|
||||
}
|
||||
|
||||
/// Returns the value that would be obtained by taking the *predecessor*
|
||||
/// of `self` `count` times.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// It is undefined behavior for this operation to overflow the
|
||||
/// range of values supported by `Self`. If you cannot guarantee that this
|
||||
/// will not overflow, use `backward` or `backward_checked` instead.
|
||||
///
|
||||
/// # Invariants
|
||||
///
|
||||
/// For any `a`:
|
||||
///
|
||||
/// * if there exists `b` such that `b < a`, it is safe to call `Step::backward_unchecked(a, 1)`
|
||||
/// * if there exists `b`, `n` such that `steps_between(&b, &a) == Some(n)`,
|
||||
/// it is safe to call `Step::backward_unchecked(a, m)` for any `m <= n`.
|
||||
///
|
||||
/// For any `a` and `n`, where no overflow occurs:
|
||||
///
|
||||
/// * `Step::backward_unchecked(a, n)` is equivalent to `Step::backward(a, n)`
|
||||
#[unstable(feature = "unchecked_math", reason = "niche optimization path", issue = "none")]
|
||||
unsafe fn backward_unchecked(start: Self, count: usize) -> Self {
|
||||
Step::backward(start, count)
|
||||
}
|
||||
}
|
||||
|
||||
// These are still macro-generated because the integer literals resolve to different types.
|
||||
macro_rules! step_identical_methods {
|
||||
() => {
|
||||
#[inline]
|
||||
unsafe fn forward_unchecked(start: Self, n: usize) -> Self {
|
||||
// SAFETY: the caller has to guarantee that `start + n` doesn't overflow.
|
||||
unsafe { start.unchecked_add(n as Self) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn backward_unchecked(start: Self, n: usize) -> Self {
|
||||
// SAFETY: the caller has to guarantee that `start - n` doesn't overflow.
|
||||
unsafe { start.unchecked_sub(n as Self) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn forward(start: Self, n: usize) -> Self {
|
||||
// In debug builds, trigger a panic on overflow.
|
||||
// This should optimize completely out in release builds.
|
||||
if Self::forward_checked(start, n).is_none() {
|
||||
let _ = Add::add(Self::MAX, 1);
|
||||
}
|
||||
// Do wrapping math to allow e.g. `Step::forward(-128i8, 255)`.
|
||||
start.wrapping_add(n as Self)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn backward(start: Self, n: usize) -> Self {
|
||||
// In debug builds, trigger a panic on overflow.
|
||||
// This should optimize completely out in release builds.
|
||||
if Self::backward_checked(start, n).is_none() {
|
||||
let _ = Sub::sub(Self::MIN, 1);
|
||||
}
|
||||
// Do wrapping math to allow e.g. `Step::backward(127i8, 255)`.
|
||||
start.wrapping_sub(n as Self)
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! step_integer_impls {
|
||||
{
|
||||
narrower than or same width as usize:
|
||||
$( [ $u_narrower:ident $i_narrower:ident ] ),+;
|
||||
wider than usize:
|
||||
$( [ $u_wider:ident $i_wider:ident ] ),+;
|
||||
} => {
|
||||
$(
|
||||
#[allow(unreachable_patterns)]
|
||||
#[unstable(feature = "step_trait", reason = "recently redesigned", issue = "42168")]
|
||||
unsafe impl Step for $u_narrower {
|
||||
step_identical_methods!();
|
||||
|
||||
#[inline]
|
||||
fn steps_between(start: &Self, end: &Self) -> Option<usize> {
|
||||
if *start <= *end {
|
||||
// This relies on $u_narrower <= usize
|
||||
Some((*end - *start) as usize)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn forward_checked(start: Self, n: usize) -> Option<Self> {
|
||||
match Self::try_from(n) {
|
||||
Ok(n) => start.checked_add(n),
|
||||
Err(_) => None, // if n is out of range, `unsigned_start + n` is too
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn backward_checked(start: Self, n: usize) -> Option<Self> {
|
||||
match Self::try_from(n) {
|
||||
Ok(n) => start.checked_sub(n),
|
||||
Err(_) => None, // if n is out of range, `unsigned_start - n` is too
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(unreachable_patterns)]
|
||||
#[unstable(feature = "step_trait", reason = "recently redesigned", issue = "42168")]
|
||||
unsafe impl Step for $i_narrower {
|
||||
step_identical_methods!();
|
||||
|
||||
#[inline]
|
||||
fn steps_between(start: &Self, end: &Self) -> Option<usize> {
|
||||
if *start <= *end {
|
||||
// This relies on $i_narrower <= usize
|
||||
//
|
||||
// Casting to isize extends the width but preserves the sign.
|
||||
// Use wrapping_sub in isize space and cast to usize to compute
|
||||
// the difference that may not fit inside the range of isize.
|
||||
Some((*end as isize).wrapping_sub(*start as isize) as usize)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn forward_checked(start: Self, n: usize) -> Option<Self> {
|
||||
match $u_narrower::try_from(n) {
|
||||
Ok(n) => {
|
||||
// Wrapping handles cases like
|
||||
// `Step::forward(-120_i8, 200) == Some(80_i8)`,
|
||||
// even though 200 is out of range for i8.
|
||||
let wrapped = start.wrapping_add(n as Self);
|
||||
if wrapped >= start {
|
||||
Some(wrapped)
|
||||
} else {
|
||||
None // Addition overflowed
|
||||
}
|
||||
}
|
||||
// If n is out of range of e.g. u8,
|
||||
// then it is bigger than the entire range for i8 is wide
|
||||
// so `any_i8 + n` necessarily overflows i8.
|
||||
Err(_) => None,
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn backward_checked(start: Self, n: usize) -> Option<Self> {
|
||||
match $u_narrower::try_from(n) {
|
||||
Ok(n) => {
|
||||
// Wrapping handles cases like
|
||||
// `Step::forward(-120_i8, 200) == Some(80_i8)`,
|
||||
// even though 200 is out of range for i8.
|
||||
let wrapped = start.wrapping_sub(n as Self);
|
||||
if wrapped <= start {
|
||||
Some(wrapped)
|
||||
} else {
|
||||
None // Subtraction overflowed
|
||||
}
|
||||
}
|
||||
// If n is out of range of e.g. u8,
|
||||
// then it is bigger than the entire range for i8 is wide
|
||||
// so `any_i8 - n` necessarily overflows i8.
|
||||
Err(_) => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
)+
|
||||
|
||||
$(
|
||||
#[allow(unreachable_patterns)]
|
||||
#[unstable(feature = "step_trait", reason = "recently redesigned", issue = "42168")]
|
||||
unsafe impl Step for $u_wider {
|
||||
step_identical_methods!();
|
||||
|
||||
#[inline]
|
||||
fn steps_between(start: &Self, end: &Self) -> Option<usize> {
|
||||
if *start <= *end {
|
||||
usize::try_from(*end - *start).ok()
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn forward_checked(start: Self, n: usize) -> Option<Self> {
|
||||
start.checked_add(n as Self)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn backward_checked(start: Self, n: usize) -> Option<Self> {
|
||||
start.checked_sub(n as Self)
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(unreachable_patterns)]
|
||||
#[unstable(feature = "step_trait", reason = "recently redesigned", issue = "42168")]
|
||||
unsafe impl Step for $i_wider {
|
||||
step_identical_methods!();
|
||||
|
||||
#[inline]
|
||||
fn steps_between(start: &Self, end: &Self) -> Option<usize> {
|
||||
if *start <= *end {
|
||||
match end.checked_sub(*start) {
|
||||
Some(result) => usize::try_from(result).ok(),
|
||||
// If the difference is too big for e.g. i128,
|
||||
// it's also gonna be too big for usize with fewer bits.
|
||||
None => None,
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn forward_checked(start: Self, n: usize) -> Option<Self> {
|
||||
start.checked_add(n as Self)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn backward_checked(start: Self, n: usize) -> Option<Self> {
|
||||
start.checked_sub(n as Self)
|
||||
}
|
||||
}
|
||||
)+
|
||||
};
|
||||
}
|
||||
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
step_integer_impls! {
|
||||
narrower than or same width as usize: [u8 i8], [u16 i16], [u32 i32], [u64 i64], [usize isize];
|
||||
wider than usize: [u128 i128];
|
||||
}
|
||||
|
||||
#[cfg(target_pointer_width = "32")]
|
||||
step_integer_impls! {
|
||||
narrower than or same width as usize: [u8 i8], [u16 i16], [u32 i32], [usize isize];
|
||||
wider than usize: [u64 i64], [u128 i128];
|
||||
}
|
||||
|
||||
#[cfg(target_pointer_width = "16")]
|
||||
step_integer_impls! {
|
||||
narrower than or same width as usize: [u8 i8], [u16 i16], [usize isize];
|
||||
wider than usize: [u32 i32], [u64 i64], [u128 i128];
|
||||
}
|
||||
|
||||
#[unstable(feature = "step_trait", reason = "recently redesigned", issue = "42168")]
|
||||
unsafe impl Step for char {
|
||||
#[inline]
|
||||
fn steps_between(&start: &char, &end: &char) -> Option<usize> {
|
||||
let start = start as u32;
|
||||
let end = end as u32;
|
||||
if start <= end {
|
||||
let count = end - start;
|
||||
if start < 0xD800 && 0xE000 <= end {
|
||||
usize::try_from(count - 0x800).ok()
|
||||
} else {
|
||||
usize::try_from(count).ok()
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn forward_checked(start: char, count: usize) -> Option<char> {
|
||||
let start = start as u32;
|
||||
let mut res = Step::forward_checked(start, count)?;
|
||||
if start < 0xD800 && 0xD800 <= res {
|
||||
res = Step::forward_checked(res, 0x800)?;
|
||||
}
|
||||
if res <= char::MAX as u32 {
|
||||
// SAFETY: res is a valid unicode scalar
|
||||
// (below 0x110000 and not in 0xD800..0xE000)
|
||||
Some(unsafe { char::from_u32_unchecked(res) })
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn backward_checked(start: char, count: usize) -> Option<char> {
|
||||
let start = start as u32;
|
||||
let mut res = Step::backward_checked(start, count)?;
|
||||
if start >= 0xE000 && 0xE000 > res {
|
||||
res = Step::backward_checked(res, 0x800)?;
|
||||
}
|
||||
// SAFETY: res is a valid unicode scalar
|
||||
// (below 0x110000 and not in 0xD800..0xE000)
|
||||
Some(unsafe { char::from_u32_unchecked(res) })
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn forward_unchecked(start: char, count: usize) -> char {
|
||||
let start = start as u32;
|
||||
// SAFETY: the caller must guarantee that this doesn't overflow
|
||||
// the range of values for a char.
|
||||
let mut res = unsafe { Step::forward_unchecked(start, count) };
|
||||
if start < 0xD800 && 0xD800 <= res {
|
||||
// SAFETY: the caller must guarantee that this doesn't overflow
|
||||
// the range of values for a char.
|
||||
res = unsafe { Step::forward_unchecked(res, 0x800) };
|
||||
}
|
||||
// SAFETY: because of the previous contract, this is guaranteed
|
||||
// by the caller to be a valid char.
|
||||
unsafe { char::from_u32_unchecked(res) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe fn backward_unchecked(start: char, count: usize) -> char {
|
||||
let start = start as u32;
|
||||
// SAFETY: the caller must guarantee that this doesn't overflow
|
||||
// the range of values for a char.
|
||||
let mut res = unsafe { Step::backward_unchecked(start, count) };
|
||||
if start >= 0xE000 && 0xE000 > res {
|
||||
// SAFETY: the caller must guarantee that this doesn't overflow
|
||||
// the range of values for a char.
|
||||
res = unsafe { Step::backward_unchecked(res, 0x800) };
|
||||
}
|
||||
// SAFETY: because of the previous contract, this is guaranteed
|
||||
// by the caller to be a valid char.
|
||||
unsafe { char::from_u32_unchecked(res) }
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! range_exact_iter_impl {
|
||||
($($t:ty)*) => ($(
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl ExactSizeIterator for ops::Range<$t> { }
|
||||
)*)
|
||||
}
|
||||
|
||||
macro_rules! range_incl_exact_iter_impl {
|
||||
($($t:ty)*) => ($(
|
||||
#[stable(feature = "inclusive_range", since = "1.26.0")]
|
||||
impl ExactSizeIterator for ops::RangeInclusive<$t> { }
|
||||
)*)
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<A: Step> Iterator for ops::Range<A> {
|
||||
type Item = A;
|
||||
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<A> {
|
||||
if self.start < self.end {
|
||||
// SAFETY: just checked precondition
|
||||
let n = unsafe { Step::forward_unchecked(self.start.clone(), 1) };
|
||||
Some(mem::replace(&mut self.start, n))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
if self.start < self.end {
|
||||
let hint = Step::steps_between(&self.start, &self.end);
|
||||
(hint.unwrap_or(usize::MAX), hint)
|
||||
} else {
|
||||
(0, Some(0))
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn nth(&mut self, n: usize) -> Option<A> {
|
||||
if let Some(plus_n) = Step::forward_checked(self.start.clone(), n) {
|
||||
if plus_n < self.end {
|
||||
// SAFETY: just checked precondition
|
||||
self.start = unsafe { Step::forward_unchecked(plus_n.clone(), 1) };
|
||||
return Some(plus_n);
|
||||
}
|
||||
}
|
||||
|
||||
self.start = self.end.clone();
|
||||
None
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn last(mut self) -> Option<A> {
|
||||
self.next_back()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn min(mut self) -> Option<A> {
|
||||
self.next()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn max(mut self) -> Option<A> {
|
||||
self.next_back()
|
||||
}
|
||||
}
|
||||
|
||||
// These macros generate `ExactSizeIterator` impls for various range types.
|
||||
//
|
||||
// * `ExactSizeIterator::len` is required to always return an exact `usize`,
|
||||
// so no range can be longer than `usize::MAX`.
|
||||
// * For integer types in `Range<_>` this is the case for types narrower than or as wide as `usize`.
|
||||
// For integer types in `RangeInclusive<_>`
|
||||
// this is the case for types *strictly narrower* than `usize`
|
||||
// since e.g. `(0..=u64::MAX).len()` would be `u64::MAX + 1`.
|
||||
range_exact_iter_impl! {
|
||||
usize u8 u16
|
||||
isize i8 i16
|
||||
|
||||
// These are incorect per the reasoning above,
|
||||
// but removing them would be a breaking change as they were stabilized in Rust 1.0.0.
|
||||
// So e.g. `(0..66_000_u32).len()` for example will compile without error or warnings
|
||||
// on 16-bit platforms, but continue to give a wrong result.
|
||||
u32
|
||||
i32
|
||||
}
|
||||
range_incl_exact_iter_impl! {
|
||||
u8
|
||||
i8
|
||||
|
||||
// These are incorect per the reasoning above,
|
||||
// but removing them would be a breaking change as they were stabilized in Rust 1.26.0.
|
||||
// So e.g. `(0..=u16::MAX).len()` for example will compile without error or warnings
|
||||
// on 16-bit platforms, but continue to give a wrong result.
|
||||
u16
|
||||
i16
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<A: Step> DoubleEndedIterator for ops::Range<A> {
|
||||
#[inline]
|
||||
fn next_back(&mut self) -> Option<A> {
|
||||
if self.start < self.end {
|
||||
// SAFETY: just checked precondition
|
||||
self.end = unsafe { Step::backward_unchecked(self.end.clone(), 1) };
|
||||
Some(self.end.clone())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn nth_back(&mut self, n: usize) -> Option<A> {
|
||||
if let Some(minus_n) = Step::backward_checked(self.end.clone(), n) {
|
||||
if minus_n > self.start {
|
||||
// SAFETY: just checked precondition
|
||||
self.end = unsafe { Step::backward_unchecked(minus_n, 1) };
|
||||
return Some(self.end.clone());
|
||||
}
|
||||
}
|
||||
|
||||
self.end = self.start.clone();
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "trusted_len", issue = "37572")]
|
||||
unsafe impl<A: Step> TrustedLen for ops::Range<A> {}
|
||||
|
||||
#[stable(feature = "fused", since = "1.26.0")]
|
||||
impl<A: Step> FusedIterator for ops::Range<A> {}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<A: Step> Iterator for ops::RangeFrom<A> {
|
||||
type Item = A;
|
||||
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<A> {
|
||||
let n = Step::forward(self.start.clone(), 1);
|
||||
Some(mem::replace(&mut self.start, n))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
(usize::MAX, None)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn nth(&mut self, n: usize) -> Option<A> {
|
||||
let plus_n = Step::forward(self.start.clone(), n);
|
||||
self.start = Step::forward(plus_n.clone(), 1);
|
||||
Some(plus_n)
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "fused", since = "1.26.0")]
|
||||
impl<A: Step> FusedIterator for ops::RangeFrom<A> {}
|
||||
|
||||
#[unstable(feature = "trusted_len", issue = "37572")]
|
||||
unsafe impl<A: Step> TrustedLen for ops::RangeFrom<A> {}
|
||||
|
||||
#[stable(feature = "inclusive_range", since = "1.26.0")]
|
||||
impl<A: Step> Iterator for ops::RangeInclusive<A> {
|
||||
type Item = A;
|
||||
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<A> {
|
||||
if self.is_empty() {
|
||||
return None;
|
||||
}
|
||||
let is_iterating = self.start < self.end;
|
||||
Some(if is_iterating {
|
||||
// SAFETY: just checked precondition
|
||||
let n = unsafe { Step::forward_unchecked(self.start.clone(), 1) };
|
||||
mem::replace(&mut self.start, n)
|
||||
} else {
|
||||
self.exhausted = true;
|
||||
self.start.clone()
|
||||
})
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
if self.is_empty() {
|
||||
return (0, Some(0));
|
||||
}
|
||||
|
||||
match Step::steps_between(&self.start, &self.end) {
|
||||
Some(hint) => (hint.saturating_add(1), hint.checked_add(1)),
|
||||
None => (usize::MAX, None),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn nth(&mut self, n: usize) -> Option<A> {
|
||||
if self.is_empty() {
|
||||
return None;
|
||||
}
|
||||
|
||||
if let Some(plus_n) = Step::forward_checked(self.start.clone(), n) {
|
||||
use crate::cmp::Ordering::*;
|
||||
|
||||
match plus_n.partial_cmp(&self.end) {
|
||||
Some(Less) => {
|
||||
self.start = Step::forward(plus_n.clone(), 1);
|
||||
return Some(plus_n);
|
||||
}
|
||||
Some(Equal) => {
|
||||
self.start = plus_n.clone();
|
||||
self.exhausted = true;
|
||||
return Some(plus_n);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
self.start = self.end.clone();
|
||||
self.exhausted = true;
|
||||
None
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn try_fold<B, F, R>(&mut self, init: B, mut f: F) -> R
|
||||
where
|
||||
Self: Sized,
|
||||
F: FnMut(B, Self::Item) -> R,
|
||||
R: Try<Ok = B>,
|
||||
{
|
||||
if self.is_empty() {
|
||||
return try { init };
|
||||
}
|
||||
|
||||
let mut accum = init;
|
||||
|
||||
while self.start < self.end {
|
||||
// SAFETY: just checked precondition
|
||||
let n = unsafe { Step::forward_unchecked(self.start.clone(), 1) };
|
||||
let n = mem::replace(&mut self.start, n);
|
||||
accum = f(accum, n)?;
|
||||
}
|
||||
|
||||
self.exhausted = true;
|
||||
|
||||
if self.start == self.end {
|
||||
accum = f(accum, self.start.clone())?;
|
||||
}
|
||||
|
||||
try { accum }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn fold<B, F>(mut self, init: B, f: F) -> B
|
||||
where
|
||||
Self: Sized,
|
||||
F: FnMut(B, Self::Item) -> B,
|
||||
{
|
||||
#[inline]
|
||||
fn ok<B, T>(mut f: impl FnMut(B, T) -> B) -> impl FnMut(B, T) -> Result<B, !> {
|
||||
move |acc, x| Ok(f(acc, x))
|
||||
}
|
||||
|
||||
self.try_fold(init, ok(f)).unwrap()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn last(mut self) -> Option<A> {
|
||||
self.next_back()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn min(mut self) -> Option<A> {
|
||||
self.next()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn max(mut self) -> Option<A> {
|
||||
self.next_back()
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "inclusive_range", since = "1.26.0")]
|
||||
impl<A: Step> DoubleEndedIterator for ops::RangeInclusive<A> {
|
||||
#[inline]
|
||||
fn next_back(&mut self) -> Option<A> {
|
||||
if self.is_empty() {
|
||||
return None;
|
||||
}
|
||||
let is_iterating = self.start < self.end;
|
||||
Some(if is_iterating {
|
||||
// SAFETY: just checked precondition
|
||||
let n = unsafe { Step::backward_unchecked(self.end.clone(), 1) };
|
||||
mem::replace(&mut self.end, n)
|
||||
} else {
|
||||
self.exhausted = true;
|
||||
self.end.clone()
|
||||
})
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn nth_back(&mut self, n: usize) -> Option<A> {
|
||||
if self.is_empty() {
|
||||
return None;
|
||||
}
|
||||
|
||||
if let Some(minus_n) = Step::backward_checked(self.end.clone(), n) {
|
||||
use crate::cmp::Ordering::*;
|
||||
|
||||
match minus_n.partial_cmp(&self.start) {
|
||||
Some(Greater) => {
|
||||
self.end = Step::backward(minus_n.clone(), 1);
|
||||
return Some(minus_n);
|
||||
}
|
||||
Some(Equal) => {
|
||||
self.end = minus_n.clone();
|
||||
self.exhausted = true;
|
||||
return Some(minus_n);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
self.end = self.start.clone();
|
||||
self.exhausted = true;
|
||||
None
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn try_rfold<B, F, R>(&mut self, init: B, mut f: F) -> R
|
||||
where
|
||||
Self: Sized,
|
||||
F: FnMut(B, Self::Item) -> R,
|
||||
R: Try<Ok = B>,
|
||||
{
|
||||
if self.is_empty() {
|
||||
return try { init };
|
||||
}
|
||||
|
||||
let mut accum = init;
|
||||
|
||||
while self.start < self.end {
|
||||
// SAFETY: just checked precondition
|
||||
let n = unsafe { Step::backward_unchecked(self.end.clone(), 1) };
|
||||
let n = mem::replace(&mut self.end, n);
|
||||
accum = f(accum, n)?;
|
||||
}
|
||||
|
||||
self.exhausted = true;
|
||||
|
||||
if self.start == self.end {
|
||||
accum = f(accum, self.start.clone())?;
|
||||
}
|
||||
|
||||
try { accum }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn rfold<B, F>(mut self, init: B, f: F) -> B
|
||||
where
|
||||
Self: Sized,
|
||||
F: FnMut(B, Self::Item) -> B,
|
||||
{
|
||||
#[inline]
|
||||
fn ok<B, T>(mut f: impl FnMut(B, T) -> B) -> impl FnMut(B, T) -> Result<B, !> {
|
||||
move |acc, x| Ok(f(acc, x))
|
||||
}
|
||||
|
||||
self.try_rfold(init, ok(f)).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "trusted_len", issue = "37572")]
|
||||
unsafe impl<A: Step> TrustedLen for ops::RangeInclusive<A> {}
|
||||
|
||||
#[stable(feature = "fused", since = "1.26.0")]
|
||||
impl<A: Step> FusedIterator for ops::RangeInclusive<A> {}
|
||||
625
libgrust/rustc-lib/core/src/iter/sources.rs
Normal file
625
libgrust/rustc-lib/core/src/iter/sources.rs
Normal file
@@ -0,0 +1,625 @@
|
||||
use crate::fmt;
|
||||
use crate::marker;
|
||||
|
||||
use super::{FusedIterator, TrustedLen};
|
||||
|
||||
/// An iterator that repeats an element endlessly.
|
||||
///
|
||||
/// This `struct` is created by the [`repeat()`] function. See its documentation for more.
|
||||
#[derive(Clone, Debug)]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub struct Repeat<A> {
|
||||
element: A,
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<A: Clone> Iterator for Repeat<A> {
|
||||
type Item = A;
|
||||
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<A> {
|
||||
Some(self.element.clone())
|
||||
}
|
||||
#[inline]
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
(usize::MAX, None)
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<A: Clone> DoubleEndedIterator for Repeat<A> {
|
||||
#[inline]
|
||||
fn next_back(&mut self) -> Option<A> {
|
||||
Some(self.element.clone())
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "fused", since = "1.26.0")]
|
||||
impl<A: Clone> FusedIterator for Repeat<A> {}
|
||||
|
||||
#[unstable(feature = "trusted_len", issue = "37572")]
|
||||
unsafe impl<A: Clone> TrustedLen for Repeat<A> {}
|
||||
|
||||
/// Creates a new iterator that endlessly repeats a single element.
|
||||
///
|
||||
/// The `repeat()` function repeats a single value over and over again.
|
||||
///
|
||||
/// Infinite iterators like `repeat()` are often used with adapters like
|
||||
/// [`Iterator::take()`], in order to make them finite.
|
||||
///
|
||||
/// If the element type of the iterator you need does not implement `Clone`,
|
||||
/// or if you do not want to keep the repeated element in memory, you can
|
||||
/// instead use the [`repeat_with()`] function.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// use std::iter;
|
||||
///
|
||||
/// // the number four 4ever:
|
||||
/// let mut fours = iter::repeat(4);
|
||||
///
|
||||
/// assert_eq!(Some(4), fours.next());
|
||||
/// assert_eq!(Some(4), fours.next());
|
||||
/// assert_eq!(Some(4), fours.next());
|
||||
/// assert_eq!(Some(4), fours.next());
|
||||
/// assert_eq!(Some(4), fours.next());
|
||||
///
|
||||
/// // yup, still four
|
||||
/// assert_eq!(Some(4), fours.next());
|
||||
/// ```
|
||||
///
|
||||
/// Going finite with [`Iterator::take()`]:
|
||||
///
|
||||
/// ```
|
||||
/// use std::iter;
|
||||
///
|
||||
/// // that last example was too many fours. Let's only have four fours.
|
||||
/// let mut four_fours = iter::repeat(4).take(4);
|
||||
///
|
||||
/// assert_eq!(Some(4), four_fours.next());
|
||||
/// assert_eq!(Some(4), four_fours.next());
|
||||
/// assert_eq!(Some(4), four_fours.next());
|
||||
/// assert_eq!(Some(4), four_fours.next());
|
||||
///
|
||||
/// // ... and now we're done
|
||||
/// assert_eq!(None, four_fours.next());
|
||||
/// ```
|
||||
#[inline]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn repeat<T: Clone>(elt: T) -> Repeat<T> {
|
||||
Repeat { element: elt }
|
||||
}
|
||||
|
||||
/// An iterator that repeats elements of type `A` endlessly by
|
||||
/// applying the provided closure `F: FnMut() -> A`.
|
||||
///
|
||||
/// This `struct` is created by the [`repeat_with()`] function.
|
||||
/// See its documentation for more.
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
#[stable(feature = "iterator_repeat_with", since = "1.28.0")]
|
||||
pub struct RepeatWith<F> {
|
||||
repeater: F,
|
||||
}
|
||||
|
||||
#[stable(feature = "iterator_repeat_with", since = "1.28.0")]
|
||||
impl<A, F: FnMut() -> A> Iterator for RepeatWith<F> {
|
||||
type Item = A;
|
||||
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<A> {
|
||||
Some((self.repeater)())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
(usize::MAX, None)
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "iterator_repeat_with", since = "1.28.0")]
|
||||
impl<A, F: FnMut() -> A> FusedIterator for RepeatWith<F> {}
|
||||
|
||||
#[unstable(feature = "trusted_len", issue = "37572")]
|
||||
unsafe impl<A, F: FnMut() -> A> TrustedLen for RepeatWith<F> {}
|
||||
|
||||
/// Creates a new iterator that repeats elements of type `A` endlessly by
|
||||
/// applying the provided closure, the repeater, `F: FnMut() -> A`.
|
||||
///
|
||||
/// The `repeat_with()` function calls the repeater over and over again.
|
||||
///
|
||||
/// Infinite iterators like `repeat_with()` are often used with adapters like
|
||||
/// [`Iterator::take()`], in order to make them finite.
|
||||
///
|
||||
/// If the element type of the iterator you need implements [`Clone`], and
|
||||
/// it is OK to keep the source element in memory, you should instead use
|
||||
/// the [`repeat()`] function.
|
||||
///
|
||||
/// An iterator produced by `repeat_with()` is not a [`DoubleEndedIterator`].
|
||||
/// If you need `repeat_with()` to return a [`DoubleEndedIterator`],
|
||||
/// please open a GitHub issue explaining your use case.
|
||||
///
|
||||
/// [`DoubleEndedIterator`]: crate::iter::DoubleEndedIterator
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// use std::iter;
|
||||
///
|
||||
/// // let's assume we have some value of a type that is not `Clone`
|
||||
/// // or which don't want to have in memory just yet because it is expensive:
|
||||
/// #[derive(PartialEq, Debug)]
|
||||
/// struct Expensive;
|
||||
///
|
||||
/// // a particular value forever:
|
||||
/// let mut things = iter::repeat_with(|| Expensive);
|
||||
///
|
||||
/// assert_eq!(Some(Expensive), things.next());
|
||||
/// assert_eq!(Some(Expensive), things.next());
|
||||
/// assert_eq!(Some(Expensive), things.next());
|
||||
/// assert_eq!(Some(Expensive), things.next());
|
||||
/// assert_eq!(Some(Expensive), things.next());
|
||||
/// ```
|
||||
///
|
||||
/// Using mutation and going finite:
|
||||
///
|
||||
/// ```rust
|
||||
/// use std::iter;
|
||||
///
|
||||
/// // From the zeroth to the third power of two:
|
||||
/// let mut curr = 1;
|
||||
/// let mut pow2 = iter::repeat_with(|| { let tmp = curr; curr *= 2; tmp })
|
||||
/// .take(4);
|
||||
///
|
||||
/// assert_eq!(Some(1), pow2.next());
|
||||
/// assert_eq!(Some(2), pow2.next());
|
||||
/// assert_eq!(Some(4), pow2.next());
|
||||
/// assert_eq!(Some(8), pow2.next());
|
||||
///
|
||||
/// // ... and now we're done
|
||||
/// assert_eq!(None, pow2.next());
|
||||
/// ```
|
||||
#[inline]
|
||||
#[stable(feature = "iterator_repeat_with", since = "1.28.0")]
|
||||
pub fn repeat_with<A, F: FnMut() -> A>(repeater: F) -> RepeatWith<F> {
|
||||
RepeatWith { repeater }
|
||||
}
|
||||
|
||||
/// An iterator that yields nothing.
|
||||
///
|
||||
/// This `struct` is created by the [`empty()`] function. See its documentation for more.
|
||||
#[stable(feature = "iter_empty", since = "1.2.0")]
|
||||
pub struct Empty<T>(marker::PhantomData<T>);
|
||||
|
||||
#[stable(feature = "iter_empty_send_sync", since = "1.42.0")]
|
||||
unsafe impl<T> Send for Empty<T> {}
|
||||
#[stable(feature = "iter_empty_send_sync", since = "1.42.0")]
|
||||
unsafe impl<T> Sync for Empty<T> {}
|
||||
|
||||
#[stable(feature = "core_impl_debug", since = "1.9.0")]
|
||||
impl<T> fmt::Debug for Empty<T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.pad("Empty")
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "iter_empty", since = "1.2.0")]
|
||||
impl<T> Iterator for Empty<T> {
|
||||
type Item = T;
|
||||
|
||||
fn next(&mut self) -> Option<T> {
|
||||
None
|
||||
}
|
||||
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
(0, Some(0))
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "iter_empty", since = "1.2.0")]
|
||||
impl<T> DoubleEndedIterator for Empty<T> {
|
||||
fn next_back(&mut self) -> Option<T> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "iter_empty", since = "1.2.0")]
|
||||
impl<T> ExactSizeIterator for Empty<T> {
|
||||
fn len(&self) -> usize {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "trusted_len", issue = "37572")]
|
||||
unsafe impl<T> TrustedLen for Empty<T> {}
|
||||
|
||||
#[stable(feature = "fused", since = "1.26.0")]
|
||||
impl<T> FusedIterator for Empty<T> {}
|
||||
|
||||
// not #[derive] because that adds a Clone bound on T,
|
||||
// which isn't necessary.
|
||||
#[stable(feature = "iter_empty", since = "1.2.0")]
|
||||
impl<T> Clone for Empty<T> {
|
||||
fn clone(&self) -> Empty<T> {
|
||||
Empty(marker::PhantomData)
|
||||
}
|
||||
}
|
||||
|
||||
// not #[derive] because that adds a Default bound on T,
|
||||
// which isn't necessary.
|
||||
#[stable(feature = "iter_empty", since = "1.2.0")]
|
||||
impl<T> Default for Empty<T> {
|
||||
fn default() -> Empty<T> {
|
||||
Empty(marker::PhantomData)
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates an iterator that yields nothing.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// use std::iter;
|
||||
///
|
||||
/// // this could have been an iterator over i32, but alas, it's just not.
|
||||
/// let mut nope = iter::empty::<i32>();
|
||||
///
|
||||
/// assert_eq!(None, nope.next());
|
||||
/// ```
|
||||
#[stable(feature = "iter_empty", since = "1.2.0")]
|
||||
#[rustc_const_stable(feature = "const_iter_empty", since = "1.32.0")]
|
||||
pub const fn empty<T>() -> Empty<T> {
|
||||
Empty(marker::PhantomData)
|
||||
}
|
||||
|
||||
/// An iterator that yields an element exactly once.
|
||||
///
|
||||
/// This `struct` is created by the [`once()`] function. See its documentation for more.
|
||||
#[derive(Clone, Debug)]
|
||||
#[stable(feature = "iter_once", since = "1.2.0")]
|
||||
pub struct Once<T> {
|
||||
inner: crate::option::IntoIter<T>,
|
||||
}
|
||||
|
||||
#[stable(feature = "iter_once", since = "1.2.0")]
|
||||
impl<T> Iterator for Once<T> {
|
||||
type Item = T;
|
||||
|
||||
fn next(&mut self) -> Option<T> {
|
||||
self.inner.next()
|
||||
}
|
||||
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
self.inner.size_hint()
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "iter_once", since = "1.2.0")]
|
||||
impl<T> DoubleEndedIterator for Once<T> {
|
||||
fn next_back(&mut self) -> Option<T> {
|
||||
self.inner.next_back()
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "iter_once", since = "1.2.0")]
|
||||
impl<T> ExactSizeIterator for Once<T> {
|
||||
fn len(&self) -> usize {
|
||||
self.inner.len()
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "trusted_len", issue = "37572")]
|
||||
unsafe impl<T> TrustedLen for Once<T> {}
|
||||
|
||||
#[stable(feature = "fused", since = "1.26.0")]
|
||||
impl<T> FusedIterator for Once<T> {}
|
||||
|
||||
/// Creates an iterator that yields an element exactly once.
|
||||
///
|
||||
/// This is commonly used to adapt a single value into a [`chain()`] of other
|
||||
/// kinds of iteration. Maybe you have an iterator that covers almost
|
||||
/// everything, but you need an extra special case. Maybe you have a function
|
||||
/// which works on iterators, but you only need to process one value.
|
||||
///
|
||||
/// [`chain()`]: Iterator::chain
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// use std::iter;
|
||||
///
|
||||
/// // one is the loneliest number
|
||||
/// let mut one = iter::once(1);
|
||||
///
|
||||
/// assert_eq!(Some(1), one.next());
|
||||
///
|
||||
/// // just one, that's all we get
|
||||
/// assert_eq!(None, one.next());
|
||||
/// ```
|
||||
///
|
||||
/// Chaining together with another iterator. Let's say that we want to iterate
|
||||
/// over each file of the `.foo` directory, but also a configuration file,
|
||||
/// `.foorc`:
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::iter;
|
||||
/// use std::fs;
|
||||
/// use std::path::PathBuf;
|
||||
///
|
||||
/// let dirs = fs::read_dir(".foo").unwrap();
|
||||
///
|
||||
/// // we need to convert from an iterator of DirEntry-s to an iterator of
|
||||
/// // PathBufs, so we use map
|
||||
/// let dirs = dirs.map(|file| file.unwrap().path());
|
||||
///
|
||||
/// // now, our iterator just for our config file
|
||||
/// let config = iter::once(PathBuf::from(".foorc"));
|
||||
///
|
||||
/// // chain the two iterators together into one big iterator
|
||||
/// let files = dirs.chain(config);
|
||||
///
|
||||
/// // this will give us all of the files in .foo as well as .foorc
|
||||
/// for f in files {
|
||||
/// println!("{:?}", f);
|
||||
/// }
|
||||
/// ```
|
||||
#[stable(feature = "iter_once", since = "1.2.0")]
|
||||
pub fn once<T>(value: T) -> Once<T> {
|
||||
Once { inner: Some(value).into_iter() }
|
||||
}
|
||||
|
||||
/// An iterator that yields a single element of type `A` by
|
||||
/// applying the provided closure `F: FnOnce() -> A`.
|
||||
///
|
||||
/// This `struct` is created by the [`once_with()`] function.
|
||||
/// See its documentation for more.
|
||||
#[derive(Clone, Debug)]
|
||||
#[stable(feature = "iter_once_with", since = "1.43.0")]
|
||||
pub struct OnceWith<F> {
|
||||
gen: Option<F>,
|
||||
}
|
||||
|
||||
#[stable(feature = "iter_once_with", since = "1.43.0")]
|
||||
impl<A, F: FnOnce() -> A> Iterator for OnceWith<F> {
|
||||
type Item = A;
|
||||
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<A> {
|
||||
let f = self.gen.take()?;
|
||||
Some(f())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
self.gen.iter().size_hint()
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "iter_once_with", since = "1.43.0")]
|
||||
impl<A, F: FnOnce() -> A> DoubleEndedIterator for OnceWith<F> {
|
||||
fn next_back(&mut self) -> Option<A> {
|
||||
self.next()
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "iter_once_with", since = "1.43.0")]
|
||||
impl<A, F: FnOnce() -> A> ExactSizeIterator for OnceWith<F> {
|
||||
fn len(&self) -> usize {
|
||||
self.gen.iter().len()
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "iter_once_with", since = "1.43.0")]
|
||||
impl<A, F: FnOnce() -> A> FusedIterator for OnceWith<F> {}
|
||||
|
||||
#[stable(feature = "iter_once_with", since = "1.43.0")]
|
||||
unsafe impl<A, F: FnOnce() -> A> TrustedLen for OnceWith<F> {}
|
||||
|
||||
/// Creates an iterator that lazily generates a value exactly once by invoking
|
||||
/// the provided closure.
|
||||
///
|
||||
/// This is commonly used to adapt a single value generator into a [`chain()`] of
|
||||
/// other kinds of iteration. Maybe you have an iterator that covers almost
|
||||
/// everything, but you need an extra special case. Maybe you have a function
|
||||
/// which works on iterators, but you only need to process one value.
|
||||
///
|
||||
/// Unlike [`once()`], this function will lazily generate the value on request.
|
||||
///
|
||||
/// [`chain()`]: Iterator::chain
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// use std::iter;
|
||||
///
|
||||
/// // one is the loneliest number
|
||||
/// let mut one = iter::once_with(|| 1);
|
||||
///
|
||||
/// assert_eq!(Some(1), one.next());
|
||||
///
|
||||
/// // just one, that's all we get
|
||||
/// assert_eq!(None, one.next());
|
||||
/// ```
|
||||
///
|
||||
/// Chaining together with another iterator. Let's say that we want to iterate
|
||||
/// over each file of the `.foo` directory, but also a configuration file,
|
||||
/// `.foorc`:
|
||||
///
|
||||
/// ```no_run
|
||||
/// use std::iter;
|
||||
/// use std::fs;
|
||||
/// use std::path::PathBuf;
|
||||
///
|
||||
/// let dirs = fs::read_dir(".foo").unwrap();
|
||||
///
|
||||
/// // we need to convert from an iterator of DirEntry-s to an iterator of
|
||||
/// // PathBufs, so we use map
|
||||
/// let dirs = dirs.map(|file| file.unwrap().path());
|
||||
///
|
||||
/// // now, our iterator just for our config file
|
||||
/// let config = iter::once_with(|| PathBuf::from(".foorc"));
|
||||
///
|
||||
/// // chain the two iterators together into one big iterator
|
||||
/// let files = dirs.chain(config);
|
||||
///
|
||||
/// // this will give us all of the files in .foo as well as .foorc
|
||||
/// for f in files {
|
||||
/// println!("{:?}", f);
|
||||
/// }
|
||||
/// ```
|
||||
#[inline]
|
||||
#[stable(feature = "iter_once_with", since = "1.43.0")]
|
||||
pub fn once_with<A, F: FnOnce() -> A>(gen: F) -> OnceWith<F> {
|
||||
OnceWith { gen: Some(gen) }
|
||||
}
|
||||
|
||||
/// Creates a new iterator where each iteration calls the provided closure
|
||||
/// `F: FnMut() -> Option<T>`.
|
||||
///
|
||||
/// This allows creating a custom iterator with any behavior
|
||||
/// without using the more verbose syntax of creating a dedicated type
|
||||
/// and implementing the [`Iterator`] trait for it.
|
||||
///
|
||||
/// Note that the `FromFn` iterator doesn’t make assumptions about the behavior of the closure,
|
||||
/// and therefore conservatively does not implement [`FusedIterator`],
|
||||
/// or override [`Iterator::size_hint()`] from its default `(0, None)`.
|
||||
///
|
||||
/// The closure can use captures and its environment to track state across iterations. Depending on
|
||||
/// how the iterator is used, this may require specifying the [`move`] keyword on the closure.
|
||||
///
|
||||
/// [`move`]: ../../std/keyword.move.html
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Let’s re-implement the counter iterator from the [module-level documentation]:
|
||||
///
|
||||
/// [module-level documentation]: super
|
||||
///
|
||||
/// ```
|
||||
/// let mut count = 0;
|
||||
/// let counter = std::iter::from_fn(move || {
|
||||
/// // Increment our count. This is why we started at zero.
|
||||
/// count += 1;
|
||||
///
|
||||
/// // Check to see if we've finished counting or not.
|
||||
/// if count < 6 {
|
||||
/// Some(count)
|
||||
/// } else {
|
||||
/// None
|
||||
/// }
|
||||
/// });
|
||||
/// assert_eq!(counter.collect::<Vec<_>>(), &[1, 2, 3, 4, 5]);
|
||||
/// ```
|
||||
#[inline]
|
||||
#[stable(feature = "iter_from_fn", since = "1.34.0")]
|
||||
pub fn from_fn<T, F>(f: F) -> FromFn<F>
|
||||
where
|
||||
F: FnMut() -> Option<T>,
|
||||
{
|
||||
FromFn(f)
|
||||
}
|
||||
|
||||
/// An iterator where each iteration calls the provided closure `F: FnMut() -> Option<T>`.
|
||||
///
|
||||
/// This `struct` is created by the [`iter::from_fn()`] function.
|
||||
/// See its documentation for more.
|
||||
///
|
||||
/// [`iter::from_fn()`]: from_fn
|
||||
#[derive(Clone)]
|
||||
#[stable(feature = "iter_from_fn", since = "1.34.0")]
|
||||
pub struct FromFn<F>(F);
|
||||
|
||||
#[stable(feature = "iter_from_fn", since = "1.34.0")]
|
||||
impl<T, F> Iterator for FromFn<F>
|
||||
where
|
||||
F: FnMut() -> Option<T>,
|
||||
{
|
||||
type Item = T;
|
||||
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
(self.0)()
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "iter_from_fn", since = "1.34.0")]
|
||||
impl<F> fmt::Debug for FromFn<F> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("FromFn").finish()
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a new iterator where each successive item is computed based on the preceding one.
|
||||
///
|
||||
/// The iterator starts with the given first item (if any)
|
||||
/// and calls the given `FnMut(&T) -> Option<T>` closure to compute each item’s successor.
|
||||
///
|
||||
/// ```
|
||||
/// use std::iter::successors;
|
||||
///
|
||||
/// let powers_of_10 = successors(Some(1_u16), |n| n.checked_mul(10));
|
||||
/// assert_eq!(powers_of_10.collect::<Vec<_>>(), &[1, 10, 100, 1_000, 10_000]);
|
||||
/// ```
|
||||
#[stable(feature = "iter_successors", since = "1.34.0")]
|
||||
pub fn successors<T, F>(first: Option<T>, succ: F) -> Successors<T, F>
|
||||
where
|
||||
F: FnMut(&T) -> Option<T>,
|
||||
{
|
||||
// If this function returned `impl Iterator<Item=T>`
|
||||
// it could be based on `unfold` and not need a dedicated type.
|
||||
// However having a named `Successors<T, F>` type allows it to be `Clone` when `T` and `F` are.
|
||||
Successors { next: first, succ }
|
||||
}
|
||||
|
||||
/// An new iterator where each successive item is computed based on the preceding one.
|
||||
///
|
||||
/// This `struct` is created by the [`iter::successors()`] function.
|
||||
/// See its documentation for more.
|
||||
///
|
||||
/// [`iter::successors()`]: successors
|
||||
#[derive(Clone)]
|
||||
#[stable(feature = "iter_successors", since = "1.34.0")]
|
||||
pub struct Successors<T, F> {
|
||||
next: Option<T>,
|
||||
succ: F,
|
||||
}
|
||||
|
||||
#[stable(feature = "iter_successors", since = "1.34.0")]
|
||||
impl<T, F> Iterator for Successors<T, F>
|
||||
where
|
||||
F: FnMut(&T) -> Option<T>,
|
||||
{
|
||||
type Item = T;
|
||||
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
let item = self.next.take()?;
|
||||
self.next = (self.succ)(&item);
|
||||
Some(item)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
if self.next.is_some() { (1, None) } else { (0, Some(0)) }
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "iter_successors", since = "1.34.0")]
|
||||
impl<T, F> FusedIterator for Successors<T, F> where F: FnMut(&T) -> Option<T> {}
|
||||
|
||||
#[stable(feature = "iter_successors", since = "1.34.0")]
|
||||
impl<T: fmt::Debug, F> fmt::Debug for Successors<T, F> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("Successors").field("next", &self.next).finish()
|
||||
}
|
||||
}
|
||||
203
libgrust/rustc-lib/core/src/iter/traits/accum.rs
Normal file
203
libgrust/rustc-lib/core/src/iter/traits/accum.rs
Normal file
@@ -0,0 +1,203 @@
|
||||
use crate::iter;
|
||||
use crate::num::Wrapping;
|
||||
use crate::ops::{Add, Mul};
|
||||
|
||||
/// Trait to represent types that can be created by summing up an iterator.
|
||||
///
|
||||
/// This trait is used to implement the [`sum()`] method on iterators. Types which
|
||||
/// implement the trait can be generated by the [`sum()`] method. Like
|
||||
/// [`FromIterator`] this trait should rarely be called directly and instead
|
||||
/// interacted with through [`Iterator::sum()`].
|
||||
///
|
||||
/// [`sum()`]: Sum::sum
|
||||
/// [`FromIterator`]: iter::FromIterator
|
||||
#[stable(feature = "iter_arith_traits", since = "1.12.0")]
|
||||
pub trait Sum<A = Self>: Sized {
|
||||
/// Method which takes an iterator and generates `Self` from the elements by
|
||||
/// "summing up" the items.
|
||||
#[stable(feature = "iter_arith_traits", since = "1.12.0")]
|
||||
fn sum<I: Iterator<Item = A>>(iter: I) -> Self;
|
||||
}
|
||||
|
||||
/// Trait to represent types that can be created by multiplying elements of an
|
||||
/// iterator.
|
||||
///
|
||||
/// This trait is used to implement the [`product()`] method on iterators. Types
|
||||
/// which implement the trait can be generated by the [`product()`] method. Like
|
||||
/// [`FromIterator`] this trait should rarely be called directly and instead
|
||||
/// interacted with through [`Iterator::product()`].
|
||||
///
|
||||
/// [`product()`]: Product::product
|
||||
/// [`FromIterator`]: iter::FromIterator
|
||||
#[stable(feature = "iter_arith_traits", since = "1.12.0")]
|
||||
pub trait Product<A = Self>: Sized {
|
||||
/// Method which takes an iterator and generates `Self` from the elements by
|
||||
/// multiplying the items.
|
||||
#[stable(feature = "iter_arith_traits", since = "1.12.0")]
|
||||
fn product<I: Iterator<Item = A>>(iter: I) -> Self;
|
||||
}
|
||||
|
||||
// N.B., explicitly use Add and Mul here to inherit overflow checks
|
||||
macro_rules! integer_sum_product {
|
||||
(@impls $zero:expr, $one:expr, #[$attr:meta], $($a:ty)*) => ($(
|
||||
#[$attr]
|
||||
impl Sum for $a {
|
||||
fn sum<I: Iterator<Item=Self>>(iter: I) -> Self {
|
||||
iter.fold($zero, Add::add)
|
||||
}
|
||||
}
|
||||
|
||||
#[$attr]
|
||||
impl Product for $a {
|
||||
fn product<I: Iterator<Item=Self>>(iter: I) -> Self {
|
||||
iter.fold($one, Mul::mul)
|
||||
}
|
||||
}
|
||||
|
||||
#[$attr]
|
||||
impl<'a> Sum<&'a $a> for $a {
|
||||
fn sum<I: Iterator<Item=&'a Self>>(iter: I) -> Self {
|
||||
iter.fold($zero, Add::add)
|
||||
}
|
||||
}
|
||||
|
||||
#[$attr]
|
||||
impl<'a> Product<&'a $a> for $a {
|
||||
fn product<I: Iterator<Item=&'a Self>>(iter: I) -> Self {
|
||||
iter.fold($one, Mul::mul)
|
||||
}
|
||||
}
|
||||
)*);
|
||||
($($a:ty)*) => (
|
||||
integer_sum_product!(@impls 0, 1,
|
||||
#[stable(feature = "iter_arith_traits", since = "1.12.0")],
|
||||
$($a)*);
|
||||
integer_sum_product!(@impls Wrapping(0), Wrapping(1),
|
||||
#[stable(feature = "wrapping_iter_arith", since = "1.14.0")],
|
||||
$(Wrapping<$a>)*);
|
||||
);
|
||||
}
|
||||
|
||||
macro_rules! float_sum_product {
|
||||
($($a:ident)*) => ($(
|
||||
#[stable(feature = "iter_arith_traits", since = "1.12.0")]
|
||||
impl Sum for $a {
|
||||
fn sum<I: Iterator<Item=Self>>(iter: I) -> Self {
|
||||
iter.fold(0.0, Add::add)
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "iter_arith_traits", since = "1.12.0")]
|
||||
impl Product for $a {
|
||||
fn product<I: Iterator<Item=Self>>(iter: I) -> Self {
|
||||
iter.fold(1.0, Mul::mul)
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "iter_arith_traits", since = "1.12.0")]
|
||||
impl<'a> Sum<&'a $a> for $a {
|
||||
fn sum<I: Iterator<Item=&'a Self>>(iter: I) -> Self {
|
||||
iter.fold(0.0, Add::add)
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "iter_arith_traits", since = "1.12.0")]
|
||||
impl<'a> Product<&'a $a> for $a {
|
||||
fn product<I: Iterator<Item=&'a Self>>(iter: I) -> Self {
|
||||
iter.fold(1.0, Mul::mul)
|
||||
}
|
||||
}
|
||||
)*)
|
||||
}
|
||||
|
||||
integer_sum_product! { i8 i16 i32 i64 i128 isize u8 u16 u32 u64 u128 usize }
|
||||
float_sum_product! { f32 f64 }
|
||||
|
||||
#[stable(feature = "iter_arith_traits_result", since = "1.16.0")]
|
||||
impl<T, U, E> Sum<Result<U, E>> for Result<T, E>
|
||||
where
|
||||
T: Sum<U>,
|
||||
{
|
||||
/// Takes each element in the [`Iterator`]: if it is an [`Err`], no further
|
||||
/// elements are taken, and the [`Err`] is returned. Should no [`Err`]
|
||||
/// occur, the sum of all elements is returned.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// This sums up every integer in a vector, rejecting the sum if a negative
|
||||
/// element is encountered:
|
||||
///
|
||||
/// ```
|
||||
/// let v = vec![1, 2];
|
||||
/// let res: Result<i32, &'static str> = v.iter().map(|&x: &i32|
|
||||
/// if x < 0 { Err("Negative element found") }
|
||||
/// else { Ok(x) }
|
||||
/// ).sum();
|
||||
/// assert_eq!(res, Ok(3));
|
||||
/// ```
|
||||
fn sum<I>(iter: I) -> Result<T, E>
|
||||
where
|
||||
I: Iterator<Item = Result<U, E>>,
|
||||
{
|
||||
iter::process_results(iter, |i| i.sum())
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "iter_arith_traits_result", since = "1.16.0")]
|
||||
impl<T, U, E> Product<Result<U, E>> for Result<T, E>
|
||||
where
|
||||
T: Product<U>,
|
||||
{
|
||||
/// Takes each element in the [`Iterator`]: if it is an [`Err`], no further
|
||||
/// elements are taken, and the [`Err`] is returned. Should no [`Err`]
|
||||
/// occur, the product of all elements is returned.
|
||||
fn product<I>(iter: I) -> Result<T, E>
|
||||
where
|
||||
I: Iterator<Item = Result<U, E>>,
|
||||
{
|
||||
iter::process_results(iter, |i| i.product())
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "iter_arith_traits_option", since = "1.37.0")]
|
||||
impl<T, U> Sum<Option<U>> for Option<T>
|
||||
where
|
||||
T: Sum<U>,
|
||||
{
|
||||
/// Takes each element in the [`Iterator`]: if it is a [`None`], no further
|
||||
/// elements are taken, and the [`None`] is returned. Should no [`None`]
|
||||
/// occur, the sum of all elements is returned.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// This sums up the position of the character 'a' in a vector of strings,
|
||||
/// if a word did not have the character 'a' the operation returns `None`:
|
||||
///
|
||||
/// ```
|
||||
/// let words = vec!["have", "a", "great", "day"];
|
||||
/// let total: Option<usize> = words.iter().map(|w| w.find('a')).sum();
|
||||
/// assert_eq!(total, Some(5));
|
||||
/// ```
|
||||
fn sum<I>(iter: I) -> Option<T>
|
||||
where
|
||||
I: Iterator<Item = Option<U>>,
|
||||
{
|
||||
iter.map(|x| x.ok_or(())).sum::<Result<_, _>>().ok()
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "iter_arith_traits_option", since = "1.37.0")]
|
||||
impl<T, U> Product<Option<U>> for Option<T>
|
||||
where
|
||||
T: Product<U>,
|
||||
{
|
||||
/// Takes each element in the [`Iterator`]: if it is a [`None`], no further
|
||||
/// elements are taken, and the [`None`] is returned. Should no [`None`]
|
||||
/// occur, the product of all elements is returned.
|
||||
fn product<I>(iter: I) -> Option<T>
|
||||
where
|
||||
I: Iterator<Item = Option<U>>,
|
||||
{
|
||||
iter.map(|x| x.ok_or(())).product::<Result<_, _>>().ok()
|
||||
}
|
||||
}
|
||||
359
libgrust/rustc-lib/core/src/iter/traits/collect.rs
Normal file
359
libgrust/rustc-lib/core/src/iter/traits/collect.rs
Normal file
@@ -0,0 +1,359 @@
|
||||
/// Conversion from an [`Iterator`].
|
||||
///
|
||||
/// By implementing `FromIterator` for a type, you define how it will be
|
||||
/// created from an iterator. This is common for types which describe a
|
||||
/// collection of some kind.
|
||||
///
|
||||
/// [`FromIterator::from_iter()`] is rarely called explicitly, and is instead
|
||||
/// used through [`Iterator::collect()`] method. See [`Iterator::collect()`]'s
|
||||
/// documentation for more examples.
|
||||
///
|
||||
/// See also: [`IntoIterator`].
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// use std::iter::FromIterator;
|
||||
///
|
||||
/// let five_fives = std::iter::repeat(5).take(5);
|
||||
///
|
||||
/// let v = Vec::from_iter(five_fives);
|
||||
///
|
||||
/// assert_eq!(v, vec![5, 5, 5, 5, 5]);
|
||||
/// ```
|
||||
///
|
||||
/// Using [`Iterator::collect()`] to implicitly use `FromIterator`:
|
||||
///
|
||||
/// ```
|
||||
/// let five_fives = std::iter::repeat(5).take(5);
|
||||
///
|
||||
/// let v: Vec<i32> = five_fives.collect();
|
||||
///
|
||||
/// assert_eq!(v, vec![5, 5, 5, 5, 5]);
|
||||
/// ```
|
||||
///
|
||||
/// Implementing `FromIterator` for your type:
|
||||
///
|
||||
/// ```
|
||||
/// use std::iter::FromIterator;
|
||||
///
|
||||
/// // A sample collection, that's just a wrapper over Vec<T>
|
||||
/// #[derive(Debug)]
|
||||
/// struct MyCollection(Vec<i32>);
|
||||
///
|
||||
/// // Let's give it some methods so we can create one and add things
|
||||
/// // to it.
|
||||
/// impl MyCollection {
|
||||
/// fn new() -> MyCollection {
|
||||
/// MyCollection(Vec::new())
|
||||
/// }
|
||||
///
|
||||
/// fn add(&mut self, elem: i32) {
|
||||
/// self.0.push(elem);
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// // and we'll implement FromIterator
|
||||
/// impl FromIterator<i32> for MyCollection {
|
||||
/// fn from_iter<I: IntoIterator<Item=i32>>(iter: I) -> Self {
|
||||
/// let mut c = MyCollection::new();
|
||||
///
|
||||
/// for i in iter {
|
||||
/// c.add(i);
|
||||
/// }
|
||||
///
|
||||
/// c
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// // Now we can make a new iterator...
|
||||
/// let iter = (0..5).into_iter();
|
||||
///
|
||||
/// // ... and make a MyCollection out of it
|
||||
/// let c = MyCollection::from_iter(iter);
|
||||
///
|
||||
/// assert_eq!(c.0, vec![0, 1, 2, 3, 4]);
|
||||
///
|
||||
/// // collect works too!
|
||||
///
|
||||
/// let iter = (0..5).into_iter();
|
||||
/// let c: MyCollection = iter.collect();
|
||||
///
|
||||
/// assert_eq!(c.0, vec![0, 1, 2, 3, 4]);
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_on_unimplemented(
|
||||
message = "a value of type `{Self}` cannot be built from an iterator \
|
||||
over elements of type `{A}`",
|
||||
label = "value of type `{Self}` cannot be built from `std::iter::Iterator<Item={A}>`"
|
||||
)]
|
||||
pub trait FromIterator<A>: Sized {
|
||||
/// Creates a value from an iterator.
|
||||
///
|
||||
/// See the [module-level documentation] for more.
|
||||
///
|
||||
/// [module-level documentation]: crate::iter
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// use std::iter::FromIterator;
|
||||
///
|
||||
/// let five_fives = std::iter::repeat(5).take(5);
|
||||
///
|
||||
/// let v = Vec::from_iter(five_fives);
|
||||
///
|
||||
/// assert_eq!(v, vec![5, 5, 5, 5, 5]);
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
fn from_iter<T: IntoIterator<Item = A>>(iter: T) -> Self;
|
||||
}
|
||||
|
||||
/// Conversion into an [`Iterator`].
|
||||
///
|
||||
/// By implementing `IntoIterator` for a type, you define how it will be
|
||||
/// converted to an iterator. This is common for types which describe a
|
||||
/// collection of some kind.
|
||||
///
|
||||
/// One benefit of implementing `IntoIterator` is that your type will [work
|
||||
/// with Rust's `for` loop syntax](crate::iter#for-loops-and-intoiterator).
|
||||
///
|
||||
/// See also: [`FromIterator`].
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// let v = vec![1, 2, 3];
|
||||
/// let mut iter = v.into_iter();
|
||||
///
|
||||
/// assert_eq!(Some(1), iter.next());
|
||||
/// assert_eq!(Some(2), iter.next());
|
||||
/// assert_eq!(Some(3), iter.next());
|
||||
/// assert_eq!(None, iter.next());
|
||||
/// ```
|
||||
/// Implementing `IntoIterator` for your type:
|
||||
///
|
||||
/// ```
|
||||
/// // A sample collection, that's just a wrapper over Vec<T>
|
||||
/// #[derive(Debug)]
|
||||
/// struct MyCollection(Vec<i32>);
|
||||
///
|
||||
/// // Let's give it some methods so we can create one and add things
|
||||
/// // to it.
|
||||
/// impl MyCollection {
|
||||
/// fn new() -> MyCollection {
|
||||
/// MyCollection(Vec::new())
|
||||
/// }
|
||||
///
|
||||
/// fn add(&mut self, elem: i32) {
|
||||
/// self.0.push(elem);
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// // and we'll implement IntoIterator
|
||||
/// impl IntoIterator for MyCollection {
|
||||
/// type Item = i32;
|
||||
/// type IntoIter = std::vec::IntoIter<Self::Item>;
|
||||
///
|
||||
/// fn into_iter(self) -> Self::IntoIter {
|
||||
/// self.0.into_iter()
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// // Now we can make a new collection...
|
||||
/// let mut c = MyCollection::new();
|
||||
///
|
||||
/// // ... add some stuff to it ...
|
||||
/// c.add(0);
|
||||
/// c.add(1);
|
||||
/// c.add(2);
|
||||
///
|
||||
/// // ... and then turn it into an Iterator:
|
||||
/// for (i, n) in c.into_iter().enumerate() {
|
||||
/// assert_eq!(i as i32, n);
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// It is common to use `IntoIterator` as a trait bound. This allows
|
||||
/// the input collection type to change, so long as it is still an
|
||||
/// iterator. Additional bounds can be specified by restricting on
|
||||
/// `Item`:
|
||||
///
|
||||
/// ```rust
|
||||
/// fn collect_as_strings<T>(collection: T) -> Vec<String>
|
||||
/// where
|
||||
/// T: IntoIterator,
|
||||
/// T::Item: std::fmt::Debug,
|
||||
/// {
|
||||
/// collection
|
||||
/// .into_iter()
|
||||
/// .map(|item| format!("{:?}", item))
|
||||
/// .collect()
|
||||
/// }
|
||||
/// ```
|
||||
#[rustc_diagnostic_item = "IntoIterator"]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub trait IntoIterator {
|
||||
/// The type of the elements being iterated over.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
type Item;
|
||||
|
||||
/// Which kind of iterator are we turning this into?
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
type IntoIter: Iterator<Item = Self::Item>;
|
||||
|
||||
/// Creates an iterator from a value.
|
||||
///
|
||||
/// See the [module-level documentation] for more.
|
||||
///
|
||||
/// [module-level documentation]: crate::iter
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// let v = vec![1, 2, 3];
|
||||
/// let mut iter = v.into_iter();
|
||||
///
|
||||
/// assert_eq!(Some(1), iter.next());
|
||||
/// assert_eq!(Some(2), iter.next());
|
||||
/// assert_eq!(Some(3), iter.next());
|
||||
/// assert_eq!(None, iter.next());
|
||||
/// ```
|
||||
#[lang = "into_iter"]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
fn into_iter(self) -> Self::IntoIter;
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<I: Iterator> IntoIterator for I {
|
||||
type Item = I::Item;
|
||||
type IntoIter = I;
|
||||
|
||||
fn into_iter(self) -> I {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
/// Extend a collection with the contents of an iterator.
|
||||
///
|
||||
/// Iterators produce a series of values, and collections can also be thought
|
||||
/// of as a series of values. The `Extend` trait bridges this gap, allowing you
|
||||
/// to extend a collection by including the contents of that iterator. When
|
||||
/// extending a collection with an already existing key, that entry is updated
|
||||
/// or, in the case of collections that permit multiple entries with equal
|
||||
/// keys, that entry is inserted.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// // You can extend a String with some chars:
|
||||
/// let mut message = String::from("The first three letters are: ");
|
||||
///
|
||||
/// message.extend(&['a', 'b', 'c']);
|
||||
///
|
||||
/// assert_eq!("abc", &message[29..32]);
|
||||
/// ```
|
||||
///
|
||||
/// Implementing `Extend`:
|
||||
///
|
||||
/// ```
|
||||
/// // A sample collection, that's just a wrapper over Vec<T>
|
||||
/// #[derive(Debug)]
|
||||
/// struct MyCollection(Vec<i32>);
|
||||
///
|
||||
/// // Let's give it some methods so we can create one and add things
|
||||
/// // to it.
|
||||
/// impl MyCollection {
|
||||
/// fn new() -> MyCollection {
|
||||
/// MyCollection(Vec::new())
|
||||
/// }
|
||||
///
|
||||
/// fn add(&mut self, elem: i32) {
|
||||
/// self.0.push(elem);
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// // since MyCollection has a list of i32s, we implement Extend for i32
|
||||
/// impl Extend<i32> for MyCollection {
|
||||
///
|
||||
/// // This is a bit simpler with the concrete type signature: we can call
|
||||
/// // extend on anything which can be turned into an Iterator which gives
|
||||
/// // us i32s. Because we need i32s to put into MyCollection.
|
||||
/// fn extend<T: IntoIterator<Item=i32>>(&mut self, iter: T) {
|
||||
///
|
||||
/// // The implementation is very straightforward: loop through the
|
||||
/// // iterator, and add() each element to ourselves.
|
||||
/// for elem in iter {
|
||||
/// self.add(elem);
|
||||
/// }
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// let mut c = MyCollection::new();
|
||||
///
|
||||
/// c.add(5);
|
||||
/// c.add(6);
|
||||
/// c.add(7);
|
||||
///
|
||||
/// // let's extend our collection with three more numbers
|
||||
/// c.extend(vec![1, 2, 3]);
|
||||
///
|
||||
/// // we've added these elements onto the end
|
||||
/// assert_eq!("MyCollection([5, 6, 7, 1, 2, 3])", format!("{:?}", c));
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub trait Extend<A> {
|
||||
/// Extends a collection with the contents of an iterator.
|
||||
///
|
||||
/// As this is the only required method for this trait, the [trait-level] docs
|
||||
/// contain more details.
|
||||
///
|
||||
/// [trait-level]: Extend
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// // You can extend a String with some chars:
|
||||
/// let mut message = String::from("abc");
|
||||
///
|
||||
/// message.extend(['d', 'e', 'f'].iter());
|
||||
///
|
||||
/// assert_eq!("abcdef", &message);
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
fn extend<T: IntoIterator<Item = A>>(&mut self, iter: T);
|
||||
|
||||
/// Extends a collection with exactly one element.
|
||||
#[unstable(feature = "extend_one", issue = "72631")]
|
||||
fn extend_one(&mut self, item: A) {
|
||||
self.extend(Some(item));
|
||||
}
|
||||
|
||||
/// Reserves capacity in a collection for the given number of additional elements.
|
||||
///
|
||||
/// The default implementation does nothing.
|
||||
#[unstable(feature = "extend_one", issue = "72631")]
|
||||
fn extend_reserve(&mut self, additional: usize) {
|
||||
let _ = additional;
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "extend_for_unit", since = "1.28.0")]
|
||||
impl Extend<()> for () {
|
||||
fn extend<T: IntoIterator<Item = ()>>(&mut self, iter: T) {
|
||||
iter.into_iter().for_each(drop)
|
||||
}
|
||||
fn extend_one(&mut self, _item: ()) {}
|
||||
}
|
||||
363
libgrust/rustc-lib/core/src/iter/traits/double_ended.rs
Normal file
363
libgrust/rustc-lib/core/src/iter/traits/double_ended.rs
Normal file
@@ -0,0 +1,363 @@
|
||||
use crate::ops::{ControlFlow, Try};
|
||||
|
||||
/// An iterator able to yield elements from both ends.
|
||||
///
|
||||
/// Something that implements `DoubleEndedIterator` has one extra capability
|
||||
/// over something that implements [`Iterator`]: the ability to also take
|
||||
/// `Item`s from the back, as well as the front.
|
||||
///
|
||||
/// It is important to note that both back and forth work on the same range,
|
||||
/// and do not cross: iteration is over when they meet in the middle.
|
||||
///
|
||||
/// In a similar fashion to the [`Iterator`] protocol, once a
|
||||
/// `DoubleEndedIterator` returns [`None`] from a [`next_back()`], calling it
|
||||
/// again may or may not ever return [`Some`] again. [`next()`] and
|
||||
/// [`next_back()`] are interchangeable for this purpose.
|
||||
///
|
||||
/// [`next_back()`]: DoubleEndedIterator::next_back
|
||||
/// [`next()`]: Iterator::next
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// let numbers = vec![1, 2, 3, 4, 5, 6];
|
||||
///
|
||||
/// let mut iter = numbers.iter();
|
||||
///
|
||||
/// assert_eq!(Some(&1), iter.next());
|
||||
/// assert_eq!(Some(&6), iter.next_back());
|
||||
/// assert_eq!(Some(&5), iter.next_back());
|
||||
/// assert_eq!(Some(&2), iter.next());
|
||||
/// assert_eq!(Some(&3), iter.next());
|
||||
/// assert_eq!(Some(&4), iter.next());
|
||||
/// assert_eq!(None, iter.next());
|
||||
/// assert_eq!(None, iter.next_back());
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub trait DoubleEndedIterator: Iterator {
|
||||
/// Removes and returns an element from the end of the iterator.
|
||||
///
|
||||
/// Returns `None` when there are no more elements.
|
||||
///
|
||||
/// The [trait-level] docs contain more details.
|
||||
///
|
||||
/// [trait-level]: DoubleEndedIterator
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// let numbers = vec![1, 2, 3, 4, 5, 6];
|
||||
///
|
||||
/// let mut iter = numbers.iter();
|
||||
///
|
||||
/// assert_eq!(Some(&1), iter.next());
|
||||
/// assert_eq!(Some(&6), iter.next_back());
|
||||
/// assert_eq!(Some(&5), iter.next_back());
|
||||
/// assert_eq!(Some(&2), iter.next());
|
||||
/// assert_eq!(Some(&3), iter.next());
|
||||
/// assert_eq!(Some(&4), iter.next());
|
||||
/// assert_eq!(None, iter.next());
|
||||
/// assert_eq!(None, iter.next_back());
|
||||
/// ```
|
||||
///
|
||||
/// # Remarks
|
||||
///
|
||||
/// The elements yielded by `DoubleEndedIterator`'s methods may differ from
|
||||
/// the ones yielded by [`Iterator`]'s methods:
|
||||
///
|
||||
/// ```
|
||||
/// let vec = vec![(1, 'a'), (1, 'b'), (1, 'c'), (2, 'a'), (2, 'b')];
|
||||
/// let uniq_by_fst_comp = || {
|
||||
/// let mut seen = std::collections::HashSet::new();
|
||||
/// vec.iter().copied().filter(move |x| seen.insert(x.0))
|
||||
/// };
|
||||
///
|
||||
/// assert_eq!(uniq_by_fst_comp().last(), Some((2, 'a')));
|
||||
/// assert_eq!(uniq_by_fst_comp().next_back(), Some((2, 'b')));
|
||||
///
|
||||
/// assert_eq!(
|
||||
/// uniq_by_fst_comp().fold(vec![], |mut v, x| {v.push(x); v}),
|
||||
/// vec![(1, 'a'), (2, 'a')]
|
||||
/// );
|
||||
/// assert_eq!(
|
||||
/// uniq_by_fst_comp().rfold(vec![], |mut v, x| {v.push(x); v}),
|
||||
/// vec![(2, 'b'), (1, 'c')]
|
||||
/// );
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
fn next_back(&mut self) -> Option<Self::Item>;
|
||||
|
||||
/// Advances the iterator from the back by `n` elements.
|
||||
///
|
||||
/// `advance_back_by` is the reverse version of [`advance_by`]. This method will
|
||||
/// eagerly skip `n` elements starting from the back by calling [`next_back`] up
|
||||
/// to `n` times until [`None`] is encountered.
|
||||
///
|
||||
/// `advance_back_by(n)` will return [`Ok(())`] if the iterator successfully advances by
|
||||
/// `n` elements, or [`Err(k)`] if [`None`] is encountered, where `k` is the number of
|
||||
/// elements the iterator is advanced by before running out of elements (i.e. the length
|
||||
/// of the iterator). Note that `k` is always less than `n`.
|
||||
///
|
||||
/// Calling `advance_back_by(0)` does not consume any elements and always returns [`Ok(())`].
|
||||
///
|
||||
/// [`advance_by`]: Iterator::advance_by
|
||||
/// [`next_back`]: DoubleEndedIterator::next_back
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(iter_advance_by)]
|
||||
///
|
||||
/// let a = [3, 4, 5, 6];
|
||||
/// let mut iter = a.iter();
|
||||
///
|
||||
/// assert_eq!(iter.advance_back_by(2), Ok(()));
|
||||
/// assert_eq!(iter.next_back(), Some(&4));
|
||||
/// assert_eq!(iter.advance_back_by(0), Ok(()));
|
||||
/// assert_eq!(iter.advance_back_by(100), Err(1)); // only `&3` was skipped
|
||||
/// ```
|
||||
///
|
||||
/// [`Ok(())`]: Ok
|
||||
/// [`Err(k)`]: Err
|
||||
#[inline]
|
||||
#[unstable(feature = "iter_advance_by", reason = "recently added", issue = "77404")]
|
||||
fn advance_back_by(&mut self, n: usize) -> Result<(), usize> {
|
||||
for i in 0..n {
|
||||
self.next_back().ok_or(i)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Returns the `n`th element from the end of the iterator.
|
||||
///
|
||||
/// This is essentially the reversed version of [`Iterator::nth()`].
|
||||
/// Although like most indexing operations, the count starts from zero, so
|
||||
/// `nth_back(0)` returns the first value from the end, `nth_back(1)` the
|
||||
/// second, and so on.
|
||||
///
|
||||
/// Note that all elements between the end and the returned element will be
|
||||
/// consumed, including the returned element. This also means that calling
|
||||
/// `nth_back(0)` multiple times on the same iterator will return different
|
||||
/// elements.
|
||||
///
|
||||
/// `nth_back()` will return [`None`] if `n` is greater than or equal to the
|
||||
/// length of the iterator.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// let a = [1, 2, 3];
|
||||
/// assert_eq!(a.iter().nth_back(2), Some(&1));
|
||||
/// ```
|
||||
///
|
||||
/// Calling `nth_back()` multiple times doesn't rewind the iterator:
|
||||
///
|
||||
/// ```
|
||||
/// let a = [1, 2, 3];
|
||||
///
|
||||
/// let mut iter = a.iter();
|
||||
///
|
||||
/// assert_eq!(iter.nth_back(1), Some(&2));
|
||||
/// assert_eq!(iter.nth_back(1), None);
|
||||
/// ```
|
||||
///
|
||||
/// Returning `None` if there are less than `n + 1` elements:
|
||||
///
|
||||
/// ```
|
||||
/// let a = [1, 2, 3];
|
||||
/// assert_eq!(a.iter().nth_back(10), None);
|
||||
/// ```
|
||||
#[inline]
|
||||
#[stable(feature = "iter_nth_back", since = "1.37.0")]
|
||||
fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
|
||||
self.advance_back_by(n).ok()?;
|
||||
self.next_back()
|
||||
}
|
||||
|
||||
/// This is the reverse version of [`Iterator::try_fold()`]: it takes
|
||||
/// elements starting from the back of the iterator.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// let a = ["1", "2", "3"];
|
||||
/// let sum = a.iter()
|
||||
/// .map(|&s| s.parse::<i32>())
|
||||
/// .try_rfold(0, |acc, x| x.and_then(|y| Ok(acc + y)));
|
||||
/// assert_eq!(sum, Ok(6));
|
||||
/// ```
|
||||
///
|
||||
/// Short-circuiting:
|
||||
///
|
||||
/// ```
|
||||
/// let a = ["1", "rust", "3"];
|
||||
/// let mut it = a.iter();
|
||||
/// let sum = it
|
||||
/// .by_ref()
|
||||
/// .map(|&s| s.parse::<i32>())
|
||||
/// .try_rfold(0, |acc, x| x.and_then(|y| Ok(acc + y)));
|
||||
/// assert!(sum.is_err());
|
||||
///
|
||||
/// // Because it short-circuited, the remaining elements are still
|
||||
/// // available through the iterator.
|
||||
/// assert_eq!(it.next_back(), Some(&"1"));
|
||||
/// ```
|
||||
#[inline]
|
||||
#[stable(feature = "iterator_try_fold", since = "1.27.0")]
|
||||
fn try_rfold<B, F, R>(&mut self, init: B, mut f: F) -> R
|
||||
where
|
||||
Self: Sized,
|
||||
F: FnMut(B, Self::Item) -> R,
|
||||
R: Try<Ok = B>,
|
||||
{
|
||||
let mut accum = init;
|
||||
while let Some(x) = self.next_back() {
|
||||
accum = f(accum, x)?;
|
||||
}
|
||||
try { accum }
|
||||
}
|
||||
|
||||
/// An iterator method that reduces the iterator's elements to a single,
|
||||
/// final value, starting from the back.
|
||||
///
|
||||
/// This is the reverse version of [`Iterator::fold()`]: it takes elements
|
||||
/// starting from the back of the iterator.
|
||||
///
|
||||
/// `rfold()` takes two arguments: an initial value, and a closure with two
|
||||
/// arguments: an 'accumulator', and an element. The closure returns the value that
|
||||
/// the accumulator should have for the next iteration.
|
||||
///
|
||||
/// The initial value is the value the accumulator will have on the first
|
||||
/// call.
|
||||
///
|
||||
/// After applying this closure to every element of the iterator, `rfold()`
|
||||
/// returns the accumulator.
|
||||
///
|
||||
/// This operation is sometimes called 'reduce' or 'inject'.
|
||||
///
|
||||
/// Folding is useful whenever you have a collection of something, and want
|
||||
/// to produce a single value from it.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// let a = [1, 2, 3];
|
||||
///
|
||||
/// // the sum of all of the elements of a
|
||||
/// let sum = a.iter()
|
||||
/// .rfold(0, |acc, &x| acc + x);
|
||||
///
|
||||
/// assert_eq!(sum, 6);
|
||||
/// ```
|
||||
///
|
||||
/// This example builds a string, starting with an initial value
|
||||
/// and continuing with each element from the back until the front:
|
||||
///
|
||||
/// ```
|
||||
/// let numbers = [1, 2, 3, 4, 5];
|
||||
///
|
||||
/// let zero = "0".to_string();
|
||||
///
|
||||
/// let result = numbers.iter().rfold(zero, |acc, &x| {
|
||||
/// format!("({} + {})", x, acc)
|
||||
/// });
|
||||
///
|
||||
/// assert_eq!(result, "(1 + (2 + (3 + (4 + (5 + 0)))))");
|
||||
/// ```
|
||||
#[inline]
|
||||
#[stable(feature = "iter_rfold", since = "1.27.0")]
|
||||
fn rfold<B, F>(mut self, init: B, mut f: F) -> B
|
||||
where
|
||||
Self: Sized,
|
||||
F: FnMut(B, Self::Item) -> B,
|
||||
{
|
||||
let mut accum = init;
|
||||
while let Some(x) = self.next_back() {
|
||||
accum = f(accum, x);
|
||||
}
|
||||
accum
|
||||
}
|
||||
|
||||
/// Searches for an element of an iterator from the back that satisfies a predicate.
|
||||
///
|
||||
/// `rfind()` takes a closure that returns `true` or `false`. It applies
|
||||
/// this closure to each element of the iterator, starting at the end, and if any
|
||||
/// of them return `true`, then `rfind()` returns [`Some(element)`]. If they all return
|
||||
/// `false`, it returns [`None`].
|
||||
///
|
||||
/// `rfind()` is short-circuiting; in other words, it will stop processing
|
||||
/// as soon as the closure returns `true`.
|
||||
///
|
||||
/// Because `rfind()` takes a reference, and many iterators iterate over
|
||||
/// references, this leads to a possibly confusing situation where the
|
||||
/// argument is a double reference. You can see this effect in the
|
||||
/// examples below, with `&&x`.
|
||||
///
|
||||
/// [`Some(element)`]: Some
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// let a = [1, 2, 3];
|
||||
///
|
||||
/// assert_eq!(a.iter().rfind(|&&x| x == 2), Some(&2));
|
||||
///
|
||||
/// assert_eq!(a.iter().rfind(|&&x| x == 5), None);
|
||||
/// ```
|
||||
///
|
||||
/// Stopping at the first `true`:
|
||||
///
|
||||
/// ```
|
||||
/// let a = [1, 2, 3];
|
||||
///
|
||||
/// let mut iter = a.iter();
|
||||
///
|
||||
/// assert_eq!(iter.rfind(|&&x| x == 2), Some(&2));
|
||||
///
|
||||
/// // we can still use `iter`, as there are more elements.
|
||||
/// assert_eq!(iter.next_back(), Some(&1));
|
||||
/// ```
|
||||
#[inline]
|
||||
#[stable(feature = "iter_rfind", since = "1.27.0")]
|
||||
fn rfind<P>(&mut self, predicate: P) -> Option<Self::Item>
|
||||
where
|
||||
Self: Sized,
|
||||
P: FnMut(&Self::Item) -> bool,
|
||||
{
|
||||
#[inline]
|
||||
fn check<T>(mut predicate: impl FnMut(&T) -> bool) -> impl FnMut((), T) -> ControlFlow<T> {
|
||||
move |(), x| {
|
||||
if predicate(&x) { ControlFlow::Break(x) } else { ControlFlow::CONTINUE }
|
||||
}
|
||||
}
|
||||
|
||||
self.try_rfold((), check(predicate)).break_value()
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<'a, I: DoubleEndedIterator + ?Sized> DoubleEndedIterator for &'a mut I {
|
||||
fn next_back(&mut self) -> Option<I::Item> {
|
||||
(**self).next_back()
|
||||
}
|
||||
fn advance_back_by(&mut self, n: usize) -> Result<(), usize> {
|
||||
(**self).advance_back_by(n)
|
||||
}
|
||||
fn nth_back(&mut self, n: usize) -> Option<I::Item> {
|
||||
(**self).nth_back(n)
|
||||
}
|
||||
}
|
||||
141
libgrust/rustc-lib/core/src/iter/traits/exact_size.rs
Normal file
141
libgrust/rustc-lib/core/src/iter/traits/exact_size.rs
Normal file
@@ -0,0 +1,141 @@
|
||||
/// An iterator that knows its exact length.
|
||||
///
|
||||
/// Many [`Iterator`]s don't know how many times they will iterate, but some do.
|
||||
/// If an iterator knows how many times it can iterate, providing access to
|
||||
/// that information can be useful. For example, if you want to iterate
|
||||
/// backwards, a good start is to know where the end is.
|
||||
///
|
||||
/// When implementing an `ExactSizeIterator`, you must also implement
|
||||
/// [`Iterator`]. When doing so, the implementation of [`Iterator::size_hint`]
|
||||
/// *must* return the exact size of the iterator.
|
||||
///
|
||||
/// The [`len`] method has a default implementation, so you usually shouldn't
|
||||
/// implement it. However, you may be able to provide a more performant
|
||||
/// implementation than the default, so overriding it in this case makes sense.
|
||||
///
|
||||
/// [`len`]: ExactSizeIterator::len
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// // a finite range knows exactly how many times it will iterate
|
||||
/// let five = 0..5;
|
||||
///
|
||||
/// assert_eq!(5, five.len());
|
||||
/// ```
|
||||
///
|
||||
/// In the [module-level docs], we implemented an [`Iterator`], `Counter`.
|
||||
/// Let's implement `ExactSizeIterator` for it as well:
|
||||
///
|
||||
/// [module-level docs]: crate::iter
|
||||
///
|
||||
/// ```
|
||||
/// # struct Counter {
|
||||
/// # count: usize,
|
||||
/// # }
|
||||
/// # impl Counter {
|
||||
/// # fn new() -> Counter {
|
||||
/// # Counter { count: 0 }
|
||||
/// # }
|
||||
/// # }
|
||||
/// # impl Iterator for Counter {
|
||||
/// # type Item = usize;
|
||||
/// # fn next(&mut self) -> Option<Self::Item> {
|
||||
/// # self.count += 1;
|
||||
/// # if self.count < 6 {
|
||||
/// # Some(self.count)
|
||||
/// # } else {
|
||||
/// # None
|
||||
/// # }
|
||||
/// # }
|
||||
/// # }
|
||||
/// impl ExactSizeIterator for Counter {
|
||||
/// // We can easily calculate the remaining number of iterations.
|
||||
/// fn len(&self) -> usize {
|
||||
/// 5 - self.count
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// // And now we can use it!
|
||||
///
|
||||
/// let counter = Counter::new();
|
||||
///
|
||||
/// assert_eq!(5, counter.len());
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub trait ExactSizeIterator: Iterator {
|
||||
/// Returns the exact length of the iterator.
|
||||
///
|
||||
/// The implementation ensures that the iterator will return exactly `len()`
|
||||
/// more times a [`Some(T)`] value, before returning [`None`].
|
||||
/// This method has a default implementation, so you usually should not
|
||||
/// implement it directly. However, if you can provide a more efficient
|
||||
/// implementation, you can do so. See the [trait-level] docs for an
|
||||
/// example.
|
||||
///
|
||||
/// This function has the same safety guarantees as the
|
||||
/// [`Iterator::size_hint`] function.
|
||||
///
|
||||
/// [trait-level]: ExactSizeIterator
|
||||
/// [`Some(T)`]: Some
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// // a finite range knows exactly how many times it will iterate
|
||||
/// let five = 0..5;
|
||||
///
|
||||
/// assert_eq!(5, five.len());
|
||||
/// ```
|
||||
#[inline]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
fn len(&self) -> usize {
|
||||
let (lower, upper) = self.size_hint();
|
||||
// Note: This assertion is overly defensive, but it checks the invariant
|
||||
// guaranteed by the trait. If this trait were rust-internal,
|
||||
// we could use debug_assert!; assert_eq! will check all Rust user
|
||||
// implementations too.
|
||||
assert_eq!(upper, Some(lower));
|
||||
lower
|
||||
}
|
||||
|
||||
/// Returns `true` if the iterator is empty.
|
||||
///
|
||||
/// This method has a default implementation using
|
||||
/// [`ExactSizeIterator::len()`], so you don't need to implement it yourself.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage:
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(exact_size_is_empty)]
|
||||
///
|
||||
/// let mut one_element = std::iter::once(0);
|
||||
/// assert!(!one_element.is_empty());
|
||||
///
|
||||
/// assert_eq!(one_element.next(), Some(0));
|
||||
/// assert!(one_element.is_empty());
|
||||
///
|
||||
/// assert_eq!(one_element.next(), None);
|
||||
/// ```
|
||||
#[inline]
|
||||
#[unstable(feature = "exact_size_is_empty", issue = "35428")]
|
||||
fn is_empty(&self) -> bool {
|
||||
self.len() == 0
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<I: ExactSizeIterator + ?Sized> ExactSizeIterator for &mut I {
|
||||
fn len(&self) -> usize {
|
||||
(**self).len()
|
||||
}
|
||||
fn is_empty(&self) -> bool {
|
||||
(**self).is_empty()
|
||||
}
|
||||
}
|
||||
3303
libgrust/rustc-lib/core/src/iter/traits/iterator.rs
Normal file
3303
libgrust/rustc-lib/core/src/iter/traits/iterator.rs
Normal file
File diff suppressed because it is too large
Load Diff
56
libgrust/rustc-lib/core/src/iter/traits/marker.rs
Normal file
56
libgrust/rustc-lib/core/src/iter/traits/marker.rs
Normal file
@@ -0,0 +1,56 @@
|
||||
/// An iterator that always continues to yield `None` when exhausted.
|
||||
///
|
||||
/// Calling next on a fused iterator that has returned `None` once is guaranteed
|
||||
/// to return [`None`] again. This trait should be implemented by all iterators
|
||||
/// that behave this way because it allows optimizing [`Iterator::fuse()`].
|
||||
///
|
||||
/// Note: In general, you should not use `FusedIterator` in generic bounds if
|
||||
/// you need a fused iterator. Instead, you should just call [`Iterator::fuse()`]
|
||||
/// on the iterator. If the iterator is already fused, the additional [`Fuse`]
|
||||
/// wrapper will be a no-op with no performance penalty.
|
||||
///
|
||||
/// [`Fuse`]: crate::iter::Fuse
|
||||
#[stable(feature = "fused", since = "1.26.0")]
|
||||
#[rustc_unsafe_specialization_marker]
|
||||
pub trait FusedIterator: Iterator {}
|
||||
|
||||
#[stable(feature = "fused", since = "1.26.0")]
|
||||
impl<I: FusedIterator + ?Sized> FusedIterator for &mut I {}
|
||||
|
||||
/// An iterator that reports an accurate length using size_hint.
|
||||
///
|
||||
/// The iterator reports a size hint where it is either exact
|
||||
/// (lower bound is equal to upper bound), or the upper bound is [`None`].
|
||||
/// The upper bound must only be [`None`] if the actual iterator length is
|
||||
/// larger than [`usize::MAX`]. In that case, the lower bound must be
|
||||
/// [`usize::MAX`], resulting in a [`Iterator::size_hint()`] of
|
||||
/// `(usize::MAX, None)`.
|
||||
///
|
||||
/// The iterator must produce exactly the number of elements it reported
|
||||
/// or diverge before reaching the end.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// This trait must only be implemented when the contract is upheld. Consumers
|
||||
/// of this trait must inspect [`Iterator::size_hint()`]’s upper bound.
|
||||
///
|
||||
/// [`usize::MAX`]: crate::usize::MAX
|
||||
#[unstable(feature = "trusted_len", issue = "37572")]
|
||||
#[rustc_unsafe_specialization_marker]
|
||||
pub unsafe trait TrustedLen: Iterator {}
|
||||
|
||||
#[unstable(feature = "trusted_len", issue = "37572")]
|
||||
unsafe impl<I: TrustedLen + ?Sized> TrustedLen for &mut I {}
|
||||
|
||||
/// An iterator that when yielding an item will have taken at least one element
|
||||
/// from its underlying [`SourceIter`].
|
||||
///
|
||||
/// Calling [`next()`] guarantees that at least one value of the iterator's underlying source
|
||||
/// has been moved out and the result of the iterator chain could be inserted in its place,
|
||||
/// assuming structural constraints of the source allow such an insertion.
|
||||
/// In other words this trait indicates that an iterator pipeline can be collected in place.
|
||||
///
|
||||
/// [`SourceIter`]: crate::iter::SourceIter
|
||||
/// [`next()`]: Iterator::next
|
||||
#[unstable(issue = "none", feature = "inplace_iteration")]
|
||||
pub unsafe trait InPlaceIterable: Iterator {}
|
||||
17
libgrust/rustc-lib/core/src/iter/traits/mod.rs
Normal file
17
libgrust/rustc-lib/core/src/iter/traits/mod.rs
Normal file
@@ -0,0 +1,17 @@
|
||||
mod accum;
|
||||
mod collect;
|
||||
mod double_ended;
|
||||
mod exact_size;
|
||||
mod iterator;
|
||||
mod marker;
|
||||
|
||||
pub use self::accum::{Product, Sum};
|
||||
pub use self::collect::{Extend, FromIterator, IntoIterator};
|
||||
pub use self::double_ended::DoubleEndedIterator;
|
||||
pub use self::exact_size::ExactSizeIterator;
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use self::iterator::Iterator;
|
||||
#[unstable(issue = "none", feature = "inplace_iteration")]
|
||||
pub use self::marker::InPlaceIterable;
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use self::marker::{FusedIterator, TrustedLen};
|
||||
379
libgrust/rustc-lib/core/src/lazy.rs
Normal file
379
libgrust/rustc-lib/core/src/lazy.rs
Normal file
@@ -0,0 +1,379 @@
|
||||
//! Lazy values and one-time initialization of static data.
|
||||
|
||||
use crate::cell::{Cell, UnsafeCell};
|
||||
use crate::fmt;
|
||||
use crate::mem;
|
||||
use crate::ops::Deref;
|
||||
|
||||
/// A cell which can be written to only once.
|
||||
///
|
||||
/// Unlike `RefCell`, a `OnceCell` only provides shared `&T` references to its value.
|
||||
/// Unlike `Cell`, a `OnceCell` doesn't require copying or replacing the value to access it.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(once_cell)]
|
||||
///
|
||||
/// use std::lazy::OnceCell;
|
||||
///
|
||||
/// let cell = OnceCell::new();
|
||||
/// assert!(cell.get().is_none());
|
||||
///
|
||||
/// let value: &String = cell.get_or_init(|| {
|
||||
/// "Hello, World!".to_string()
|
||||
/// });
|
||||
/// assert_eq!(value, "Hello, World!");
|
||||
/// assert!(cell.get().is_some());
|
||||
/// ```
|
||||
#[unstable(feature = "once_cell", issue = "74465")]
|
||||
pub struct OnceCell<T> {
|
||||
// Invariant: written to at most once.
|
||||
inner: UnsafeCell<Option<T>>,
|
||||
}
|
||||
|
||||
#[unstable(feature = "once_cell", issue = "74465")]
|
||||
impl<T> Default for OnceCell<T> {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "once_cell", issue = "74465")]
|
||||
impl<T: fmt::Debug> fmt::Debug for OnceCell<T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self.get() {
|
||||
Some(v) => f.debug_tuple("OnceCell").field(v).finish(),
|
||||
None => f.write_str("OnceCell(Uninit)"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "once_cell", issue = "74465")]
|
||||
impl<T: Clone> Clone for OnceCell<T> {
|
||||
fn clone(&self) -> OnceCell<T> {
|
||||
let res = OnceCell::new();
|
||||
if let Some(value) = self.get() {
|
||||
match res.set(value.clone()) {
|
||||
Ok(()) => (),
|
||||
Err(_) => unreachable!(),
|
||||
}
|
||||
}
|
||||
res
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "once_cell", issue = "74465")]
|
||||
impl<T: PartialEq> PartialEq for OnceCell<T> {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.get() == other.get()
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "once_cell", issue = "74465")]
|
||||
impl<T: Eq> Eq for OnceCell<T> {}
|
||||
|
||||
#[unstable(feature = "once_cell", issue = "74465")]
|
||||
impl<T> From<T> for OnceCell<T> {
|
||||
fn from(value: T) -> Self {
|
||||
OnceCell { inner: UnsafeCell::new(Some(value)) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> OnceCell<T> {
|
||||
/// Creates a new empty cell.
|
||||
#[unstable(feature = "once_cell", issue = "74465")]
|
||||
pub const fn new() -> OnceCell<T> {
|
||||
OnceCell { inner: UnsafeCell::new(None) }
|
||||
}
|
||||
|
||||
/// Gets the reference to the underlying value.
|
||||
///
|
||||
/// Returns `None` if the cell is empty.
|
||||
#[unstable(feature = "once_cell", issue = "74465")]
|
||||
pub fn get(&self) -> Option<&T> {
|
||||
// SAFETY: Safe due to `inner`'s invariant
|
||||
unsafe { &*self.inner.get() }.as_ref()
|
||||
}
|
||||
|
||||
/// Gets the mutable reference to the underlying value.
|
||||
///
|
||||
/// Returns `None` if the cell is empty.
|
||||
#[unstable(feature = "once_cell", issue = "74465")]
|
||||
pub fn get_mut(&mut self) -> Option<&mut T> {
|
||||
// SAFETY: Safe because we have unique access
|
||||
unsafe { &mut *self.inner.get() }.as_mut()
|
||||
}
|
||||
|
||||
/// Sets the contents of the cell to `value`.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// This method returns `Ok(())` if the cell was empty and `Err(value)` if
|
||||
/// it was full.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(once_cell)]
|
||||
///
|
||||
/// use std::lazy::OnceCell;
|
||||
///
|
||||
/// let cell = OnceCell::new();
|
||||
/// assert!(cell.get().is_none());
|
||||
///
|
||||
/// assert_eq!(cell.set(92), Ok(()));
|
||||
/// assert_eq!(cell.set(62), Err(62));
|
||||
///
|
||||
/// assert!(cell.get().is_some());
|
||||
/// ```
|
||||
#[unstable(feature = "once_cell", issue = "74465")]
|
||||
pub fn set(&self, value: T) -> Result<(), T> {
|
||||
// SAFETY: Safe because we cannot have overlapping mutable borrows
|
||||
let slot = unsafe { &*self.inner.get() };
|
||||
if slot.is_some() {
|
||||
return Err(value);
|
||||
}
|
||||
|
||||
// SAFETY: This is the only place where we set the slot, no races
|
||||
// due to reentrancy/concurrency are possible, and we've
|
||||
// checked that slot is currently `None`, so this write
|
||||
// maintains the `inner`'s invariant.
|
||||
let slot = unsafe { &mut *self.inner.get() };
|
||||
*slot = Some(value);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Gets the contents of the cell, initializing it with `f`
|
||||
/// if the cell was empty.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// If `f` panics, the panic is propagated to the caller, and the cell
|
||||
/// remains uninitialized.
|
||||
///
|
||||
/// It is an error to reentrantly initialize the cell from `f`. Doing
|
||||
/// so results in a panic.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(once_cell)]
|
||||
///
|
||||
/// use std::lazy::OnceCell;
|
||||
///
|
||||
/// let cell = OnceCell::new();
|
||||
/// let value = cell.get_or_init(|| 92);
|
||||
/// assert_eq!(value, &92);
|
||||
/// let value = cell.get_or_init(|| unreachable!());
|
||||
/// assert_eq!(value, &92);
|
||||
/// ```
|
||||
#[unstable(feature = "once_cell", issue = "74465")]
|
||||
pub fn get_or_init<F>(&self, f: F) -> &T
|
||||
where
|
||||
F: FnOnce() -> T,
|
||||
{
|
||||
match self.get_or_try_init(|| Ok::<T, !>(f())) {
|
||||
Ok(val) => val,
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets the contents of the cell, initializing it with `f` if
|
||||
/// the cell was empty. If the cell was empty and `f` failed, an
|
||||
/// error is returned.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// If `f` panics, the panic is propagated to the caller, and the cell
|
||||
/// remains uninitialized.
|
||||
///
|
||||
/// It is an error to reentrantly initialize the cell from `f`. Doing
|
||||
/// so results in a panic.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(once_cell)]
|
||||
///
|
||||
/// use std::lazy::OnceCell;
|
||||
///
|
||||
/// let cell = OnceCell::new();
|
||||
/// assert_eq!(cell.get_or_try_init(|| Err(())), Err(()));
|
||||
/// assert!(cell.get().is_none());
|
||||
/// let value = cell.get_or_try_init(|| -> Result<i32, ()> {
|
||||
/// Ok(92)
|
||||
/// });
|
||||
/// assert_eq!(value, Ok(&92));
|
||||
/// assert_eq!(cell.get(), Some(&92))
|
||||
/// ```
|
||||
#[unstable(feature = "once_cell", issue = "74465")]
|
||||
pub fn get_or_try_init<F, E>(&self, f: F) -> Result<&T, E>
|
||||
where
|
||||
F: FnOnce() -> Result<T, E>,
|
||||
{
|
||||
if let Some(val) = self.get() {
|
||||
return Ok(val);
|
||||
}
|
||||
let val = f()?;
|
||||
// Note that *some* forms of reentrant initialization might lead to
|
||||
// UB (see `reentrant_init` test). I believe that just removing this
|
||||
// `assert`, while keeping `set/get` would be sound, but it seems
|
||||
// better to panic, rather than to silently use an old value.
|
||||
assert!(self.set(val).is_ok(), "reentrant init");
|
||||
Ok(self.get().unwrap())
|
||||
}
|
||||
|
||||
/// Consumes the cell, returning the wrapped value.
|
||||
///
|
||||
/// Returns `None` if the cell was empty.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(once_cell)]
|
||||
///
|
||||
/// use std::lazy::OnceCell;
|
||||
///
|
||||
/// let cell: OnceCell<String> = OnceCell::new();
|
||||
/// assert_eq!(cell.into_inner(), None);
|
||||
///
|
||||
/// let cell = OnceCell::new();
|
||||
/// cell.set("hello".to_string()).unwrap();
|
||||
/// assert_eq!(cell.into_inner(), Some("hello".to_string()));
|
||||
/// ```
|
||||
#[unstable(feature = "once_cell", issue = "74465")]
|
||||
pub fn into_inner(self) -> Option<T> {
|
||||
// Because `into_inner` takes `self` by value, the compiler statically verifies
|
||||
// that it is not currently borrowed. So it is safe to move out `Option<T>`.
|
||||
self.inner.into_inner()
|
||||
}
|
||||
|
||||
/// Takes the value out of this `OnceCell`, moving it back to an uninitialized state.
|
||||
///
|
||||
/// Has no effect and returns `None` if the `OnceCell` hasn't been initialized.
|
||||
///
|
||||
/// Safety is guaranteed by requiring a mutable reference.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(once_cell)]
|
||||
///
|
||||
/// use std::lazy::OnceCell;
|
||||
///
|
||||
/// let mut cell: OnceCell<String> = OnceCell::new();
|
||||
/// assert_eq!(cell.take(), None);
|
||||
///
|
||||
/// let mut cell = OnceCell::new();
|
||||
/// cell.set("hello".to_string()).unwrap();
|
||||
/// assert_eq!(cell.take(), Some("hello".to_string()));
|
||||
/// assert_eq!(cell.get(), None);
|
||||
/// ```
|
||||
#[unstable(feature = "once_cell", issue = "74465")]
|
||||
pub fn take(&mut self) -> Option<T> {
|
||||
mem::take(self).into_inner()
|
||||
}
|
||||
}
|
||||
|
||||
/// A value which is initialized on the first access.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(once_cell)]
|
||||
///
|
||||
/// use std::lazy::Lazy;
|
||||
///
|
||||
/// let lazy: Lazy<i32> = Lazy::new(|| {
|
||||
/// println!("initializing");
|
||||
/// 92
|
||||
/// });
|
||||
/// println!("ready");
|
||||
/// println!("{}", *lazy);
|
||||
/// println!("{}", *lazy);
|
||||
///
|
||||
/// // Prints:
|
||||
/// // ready
|
||||
/// // initializing
|
||||
/// // 92
|
||||
/// // 92
|
||||
/// ```
|
||||
#[unstable(feature = "once_cell", issue = "74465")]
|
||||
pub struct Lazy<T, F = fn() -> T> {
|
||||
cell: OnceCell<T>,
|
||||
init: Cell<Option<F>>,
|
||||
}
|
||||
|
||||
#[unstable(feature = "once_cell", issue = "74465")]
|
||||
impl<T: fmt::Debug, F> fmt::Debug for Lazy<T, F> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("Lazy").field("cell", &self.cell).field("init", &"..").finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, F> Lazy<T, F> {
|
||||
/// Creates a new lazy value with the given initializing function.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(once_cell)]
|
||||
///
|
||||
/// # fn main() {
|
||||
/// use std::lazy::Lazy;
|
||||
///
|
||||
/// let hello = "Hello, World!".to_string();
|
||||
///
|
||||
/// let lazy = Lazy::new(|| hello.to_uppercase());
|
||||
///
|
||||
/// assert_eq!(&*lazy, "HELLO, WORLD!");
|
||||
/// # }
|
||||
/// ```
|
||||
#[unstable(feature = "once_cell", issue = "74465")]
|
||||
pub const fn new(init: F) -> Lazy<T, F> {
|
||||
Lazy { cell: OnceCell::new(), init: Cell::new(Some(init)) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<T, F: FnOnce() -> T> Lazy<T, F> {
|
||||
/// Forces the evaluation of this lazy value and returns a reference to
|
||||
/// the result.
|
||||
///
|
||||
/// This is equivalent to the `Deref` impl, but is explicit.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(once_cell)]
|
||||
///
|
||||
/// use std::lazy::Lazy;
|
||||
///
|
||||
/// let lazy = Lazy::new(|| 92);
|
||||
///
|
||||
/// assert_eq!(Lazy::force(&lazy), &92);
|
||||
/// assert_eq!(&*lazy, &92);
|
||||
/// ```
|
||||
#[unstable(feature = "once_cell", issue = "74465")]
|
||||
pub fn force(this: &Lazy<T, F>) -> &T {
|
||||
this.cell.get_or_init(|| match this.init.take() {
|
||||
Some(f) => f(),
|
||||
None => panic!("`Lazy` instance has previously been poisoned"),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "once_cell", issue = "74465")]
|
||||
impl<T, F: FnOnce() -> T> Deref for Lazy<T, F> {
|
||||
type Target = T;
|
||||
fn deref(&self) -> &T {
|
||||
Lazy::force(self)
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "once_cell", issue = "74465")]
|
||||
impl<T: Default> Default for Lazy<T> {
|
||||
/// Creates a new lazy value using `Default` as the initializing function.
|
||||
fn default() -> Lazy<T> {
|
||||
Lazy::new(T::default)
|
||||
}
|
||||
}
|
||||
300
libgrust/rustc-lib/core/src/lib.rs
Normal file
300
libgrust/rustc-lib/core/src/lib.rs
Normal file
@@ -0,0 +1,300 @@
|
||||
//! # The Rust Core Library
|
||||
//!
|
||||
//! The Rust Core Library is the dependency-free[^free] foundation of [The
|
||||
//! Rust Standard Library](../std/index.html). It is the portable glue
|
||||
//! between the language and its libraries, defining the intrinsic and
|
||||
//! primitive building blocks of all Rust code. It links to no
|
||||
//! upstream libraries, no system libraries, and no libc.
|
||||
//!
|
||||
//! [^free]: Strictly speaking, there are some symbols which are needed but
|
||||
//! they aren't always necessary.
|
||||
//!
|
||||
//! The core library is *minimal*: it isn't even aware of heap allocation,
|
||||
//! nor does it provide concurrency or I/O. These things require
|
||||
//! platform integration, and this library is platform-agnostic.
|
||||
//!
|
||||
//! # How to use the core library
|
||||
//!
|
||||
//! Please note that all of these details are currently not considered stable.
|
||||
//!
|
||||
// FIXME: Fill me in with more detail when the interface settles
|
||||
//! This library is built on the assumption of a few existing symbols:
|
||||
//!
|
||||
//! * `memcpy`, `memcmp`, `memset` - These are core memory routines which are
|
||||
//! often generated by LLVM. Additionally, this library can make explicit
|
||||
//! calls to these functions. Their signatures are the same as found in C.
|
||||
//! These functions are often provided by the system libc, but can also be
|
||||
//! provided by the [compiler-builtins crate](https://crates.io/crates/compiler_builtins).
|
||||
//!
|
||||
//! * `rust_begin_panic` - This function takes four arguments, a
|
||||
//! `fmt::Arguments`, a `&'static str`, and two `u32`'s. These four arguments
|
||||
//! dictate the panic message, the file at which panic was invoked, and the
|
||||
//! line and column inside the file. It is up to consumers of this core
|
||||
//! library to define this panic function; it is only required to never
|
||||
//! return. This requires a `lang` attribute named `panic_impl`.
|
||||
//!
|
||||
//! * `rust_eh_personality` - is used by the failure mechanisms of the
|
||||
//! compiler. This is often mapped to GCC's personality function, but crates
|
||||
//! which do not trigger a panic can be assured that this function is never
|
||||
//! called. The `lang` attribute is called `eh_personality`.
|
||||
|
||||
// Since libcore defines many fundamental lang items, all tests live in a
|
||||
// separate crate, libcoretest, to avoid bizarre issues.
|
||||
//
|
||||
// Here we explicitly #[cfg]-out this whole crate when testing. If we don't do
|
||||
// this, both the generated test artifact and the linked libtest (which
|
||||
// transitively includes libcore) will both define the same set of lang items,
|
||||
// and this will cause the E0152 "found duplicate lang item" error. See
|
||||
// discussion in #50466 for details.
|
||||
//
|
||||
// This cfg won't affect doc tests.
|
||||
#![cfg(not(test))]
|
||||
#![stable(feature = "core", since = "1.6.0")]
|
||||
#![doc(
|
||||
html_root_url = "https://doc.rust-lang.org/nightly/",
|
||||
html_playground_url = "https://play.rust-lang.org/",
|
||||
issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/",
|
||||
test(no_crate_inject, attr(deny(warnings))),
|
||||
test(attr(allow(dead_code, deprecated, unused_variables, unused_mut)))
|
||||
)]
|
||||
#![no_core]
|
||||
#![warn(deprecated_in_future)]
|
||||
#![warn(missing_docs)]
|
||||
#![warn(missing_debug_implementations)]
|
||||
#![allow(explicit_outlives_requirements)]
|
||||
#![allow(incomplete_features)]
|
||||
#![cfg_attr(not(bootstrap), feature(rustc_allow_const_fn_unstable))]
|
||||
#![feature(allow_internal_unstable)]
|
||||
#![feature(arbitrary_self_types)]
|
||||
#![feature(asm)]
|
||||
#![feature(cfg_target_has_atomic)]
|
||||
#![feature(const_alloc_layout)]
|
||||
#![feature(const_discriminant)]
|
||||
#![feature(const_cell_into_inner)]
|
||||
#![feature(const_checked_int_methods)]
|
||||
#![feature(const_euclidean_int_methods)]
|
||||
#![feature(const_float_classify)]
|
||||
#![feature(const_float_bits_conv)]
|
||||
#![feature(const_overflowing_int_methods)]
|
||||
#![feature(const_int_unchecked_arith)]
|
||||
#![feature(const_mut_refs)]
|
||||
#![feature(const_int_pow)]
|
||||
#![feature(constctlz)]
|
||||
#![feature(const_panic)]
|
||||
#![feature(const_pin)]
|
||||
#![feature(const_fn)]
|
||||
#![feature(const_fn_union)]
|
||||
#![cfg_attr(not(bootstrap), feature(const_impl_trait))]
|
||||
#![feature(const_fn_floating_point_arithmetic)]
|
||||
#![feature(const_fn_fn_ptr_basics)]
|
||||
#![feature(const_generics)]
|
||||
#![feature(const_option)]
|
||||
#![feature(const_precise_live_drops)]
|
||||
#![feature(const_ptr_offset)]
|
||||
#![feature(const_ptr_offset_from)]
|
||||
#![feature(const_raw_ptr_comparison)]
|
||||
#![feature(const_slice_from_raw_parts)]
|
||||
#![feature(const_slice_ptr_len)]
|
||||
#![feature(const_size_of_val)]
|
||||
#![feature(const_align_of_val)]
|
||||
#![feature(const_type_id)]
|
||||
#![feature(const_type_name)]
|
||||
#![feature(const_likely)]
|
||||
#![feature(const_unreachable_unchecked)]
|
||||
#![feature(custom_inner_attributes)]
|
||||
#![feature(decl_macro)]
|
||||
#![feature(doc_cfg)]
|
||||
#![feature(doc_spotlight)]
|
||||
#![feature(duration_consts_2)]
|
||||
#![feature(duration_saturating_ops)]
|
||||
#![feature(extern_types)]
|
||||
#![feature(fundamental)]
|
||||
#![feature(intrinsics)]
|
||||
#![feature(lang_items)]
|
||||
#![feature(link_llvm_intrinsics)]
|
||||
#![feature(llvm_asm)]
|
||||
#![feature(negative_impls)]
|
||||
#![feature(never_type)]
|
||||
#![feature(nll)]
|
||||
#![feature(exhaustive_patterns)]
|
||||
#![feature(no_core)]
|
||||
#![feature(optin_builtin_traits)]
|
||||
#![feature(or_patterns)]
|
||||
#![feature(prelude_import)]
|
||||
#![feature(repr_simd, platform_intrinsics)]
|
||||
#![feature(rustc_attrs)]
|
||||
#![feature(simd_ffi)]
|
||||
#![feature(min_specialization)]
|
||||
#![feature(staged_api)]
|
||||
#![feature(std_internals)]
|
||||
#![feature(stmt_expr_attributes)]
|
||||
#![feature(str_split_as_str)]
|
||||
#![feature(str_split_inclusive_as_str)]
|
||||
#![feature(transparent_unions)]
|
||||
#![feature(try_blocks)]
|
||||
#![feature(unboxed_closures)]
|
||||
#![cfg_attr(not(bootstrap), feature(unsized_fn_params))]
|
||||
#![cfg_attr(bootstrap, feature(unsized_locals))]
|
||||
#![cfg_attr(bootstrap, feature(untagged_unions))]
|
||||
#![feature(unwind_attributes)]
|
||||
#![feature(variant_count)]
|
||||
#![feature(tbm_target_feature)]
|
||||
#![feature(sse4a_target_feature)]
|
||||
#![feature(arm_target_feature)]
|
||||
#![feature(powerpc_target_feature)]
|
||||
#![feature(mips_target_feature)]
|
||||
#![feature(aarch64_target_feature)]
|
||||
#![feature(wasm_target_feature)]
|
||||
#![feature(avx512_target_feature)]
|
||||
#![feature(cmpxchg16b_target_feature)]
|
||||
#![feature(rtm_target_feature)]
|
||||
#![feature(f16c_target_feature)]
|
||||
#![feature(hexagon_target_feature)]
|
||||
#![feature(const_fn_transmute)]
|
||||
#![feature(abi_unadjusted)]
|
||||
#![feature(adx_target_feature)]
|
||||
#![feature(external_doc)]
|
||||
#![feature(associated_type_bounds)]
|
||||
#![feature(const_caller_location)]
|
||||
#![feature(slice_ptr_get)]
|
||||
#![feature(no_niche)] // rust-lang/rust#68303
|
||||
#![feature(unsafe_block_in_unsafe_fn)]
|
||||
#![feature(int_error_matching)]
|
||||
#![deny(unsafe_op_in_unsafe_fn)]
|
||||
|
||||
#[prelude_import]
|
||||
#[allow(unused)]
|
||||
use prelude::v1::*;
|
||||
|
||||
#[cfg(not(test))] // See #65860
|
||||
#[macro_use]
|
||||
mod macros;
|
||||
|
||||
#[macro_use]
|
||||
mod internal_macros;
|
||||
|
||||
#[path = "num/shells/int_macros.rs"]
|
||||
#[macro_use]
|
||||
mod int_macros;
|
||||
|
||||
#[path = "num/shells/i128.rs"]
|
||||
pub mod i128;
|
||||
#[path = "num/shells/i16.rs"]
|
||||
pub mod i16;
|
||||
#[path = "num/shells/i32.rs"]
|
||||
pub mod i32;
|
||||
#[path = "num/shells/i64.rs"]
|
||||
pub mod i64;
|
||||
#[path = "num/shells/i8.rs"]
|
||||
pub mod i8;
|
||||
#[path = "num/shells/isize.rs"]
|
||||
pub mod isize;
|
||||
|
||||
#[path = "num/shells/u128.rs"]
|
||||
pub mod u128;
|
||||
#[path = "num/shells/u16.rs"]
|
||||
pub mod u16;
|
||||
#[path = "num/shells/u32.rs"]
|
||||
pub mod u32;
|
||||
#[path = "num/shells/u64.rs"]
|
||||
pub mod u64;
|
||||
#[path = "num/shells/u8.rs"]
|
||||
pub mod u8;
|
||||
#[path = "num/shells/usize.rs"]
|
||||
pub mod usize;
|
||||
|
||||
#[path = "num/f32.rs"]
|
||||
pub mod f32;
|
||||
#[path = "num/f64.rs"]
|
||||
pub mod f64;
|
||||
|
||||
#[macro_use]
|
||||
pub mod num;
|
||||
|
||||
/* The libcore prelude, not as all-encompassing as the libstd prelude */
|
||||
|
||||
pub mod prelude;
|
||||
|
||||
/* Core modules for ownership management */
|
||||
|
||||
pub mod hint;
|
||||
pub mod intrinsics;
|
||||
pub mod mem;
|
||||
pub mod ptr;
|
||||
|
||||
/* Core language traits */
|
||||
|
||||
pub mod borrow;
|
||||
pub mod clone;
|
||||
pub mod cmp;
|
||||
pub mod convert;
|
||||
pub mod default;
|
||||
pub mod marker;
|
||||
pub mod ops;
|
||||
|
||||
/* Core types and methods on primitives */
|
||||
|
||||
pub mod any;
|
||||
pub mod array;
|
||||
pub mod ascii;
|
||||
pub mod cell;
|
||||
pub mod char;
|
||||
pub mod ffi;
|
||||
pub mod iter;
|
||||
#[unstable(feature = "once_cell", issue = "74465")]
|
||||
pub mod lazy;
|
||||
pub mod option;
|
||||
pub mod panic;
|
||||
pub mod panicking;
|
||||
pub mod pin;
|
||||
pub mod raw;
|
||||
pub mod result;
|
||||
pub mod sync;
|
||||
|
||||
pub mod fmt;
|
||||
pub mod hash;
|
||||
pub mod slice;
|
||||
pub mod str;
|
||||
pub mod time;
|
||||
|
||||
pub mod unicode;
|
||||
|
||||
/* Async */
|
||||
pub mod future;
|
||||
pub mod task;
|
||||
|
||||
/* Heap memory allocator trait */
|
||||
#[allow(missing_docs)]
|
||||
pub mod alloc;
|
||||
|
||||
// note: does not need to be public
|
||||
mod bool;
|
||||
mod tuple;
|
||||
mod unit;
|
||||
|
||||
#[stable(feature = "core_primitive", since = "1.43.0")]
|
||||
pub mod primitive;
|
||||
|
||||
// Pull in the `core_arch` crate directly into libcore. The contents of
|
||||
// `core_arch` are in a different repository: rust-lang/stdarch.
|
||||
//
|
||||
// `core_arch` depends on libcore, but the contents of this module are
|
||||
// set up in such a way that directly pulling it here works such that the
|
||||
// crate uses the this crate as its libcore.
|
||||
#[path = "../../stdarch/crates/core_arch/src/mod.rs"]
|
||||
#[allow(
|
||||
missing_docs,
|
||||
missing_debug_implementations,
|
||||
dead_code,
|
||||
unused_imports,
|
||||
unsafe_op_in_unsafe_fn
|
||||
)]
|
||||
#[cfg_attr(not(bootstrap), allow(non_autolinks))]
|
||||
// FIXME: This annotation should be moved into rust-lang/stdarch after clashing_extern_declarations is
|
||||
// merged. It currently cannot because bootstrap fails as the lint hasn't been defined yet.
|
||||
#[allow(clashing_extern_declarations)]
|
||||
#[unstable(feature = "stdsimd", issue = "48556")]
|
||||
mod core_arch;
|
||||
|
||||
#[stable(feature = "simd_arch", since = "1.27.0")]
|
||||
pub use core_arch::arch;
|
||||
1376
libgrust/rustc-lib/core/src/macros/mod.rs
Normal file
1376
libgrust/rustc-lib/core/src/macros/mod.rs
Normal file
File diff suppressed because it is too large
Load Diff
47
libgrust/rustc-lib/core/src/macros/panic.md
Normal file
47
libgrust/rustc-lib/core/src/macros/panic.md
Normal file
@@ -0,0 +1,47 @@
|
||||
Panics the current thread.
|
||||
|
||||
This allows a program to terminate immediately and provide feedback
|
||||
to the caller of the program. `panic!` should be used when a program reaches
|
||||
an unrecoverable state.
|
||||
|
||||
This macro is the perfect way to assert conditions in example code and in
|
||||
tests. `panic!` is closely tied with the `unwrap` method of both
|
||||
[`Option`][ounwrap] and [`Result`][runwrap] enums. Both implementations call
|
||||
`panic!` when they are set to [`None`] or [`Err`] variants.
|
||||
|
||||
This macro is used to inject panic into a Rust thread, causing the thread to
|
||||
panic entirely. Each thread's panic can be reaped as the [`Box`]`<`[`Any`]`>` type,
|
||||
and the single-argument form of the `panic!` macro will be the value which
|
||||
is transmitted.
|
||||
|
||||
[`Result`] enum is often a better solution for recovering from errors than
|
||||
using the `panic!` macro. This macro should be used to avoid proceeding using
|
||||
incorrect values, such as from external sources. Detailed information about
|
||||
error handling is found in the [book].
|
||||
|
||||
The multi-argument form of this macro panics with a string and has the
|
||||
[`format!`] syntax for building a string.
|
||||
|
||||
See also the macro [`compile_error!`], for raising errors during compilation.
|
||||
|
||||
[ounwrap]: Option::unwrap
|
||||
[runwrap]: Result::unwrap
|
||||
[`Box`]: ../std/boxed/struct.Box.html
|
||||
[`Any`]: crate::any::Any
|
||||
[`format!`]: ../std/macro.format.html
|
||||
[book]: ../book/ch09-00-error-handling.html
|
||||
|
||||
# Current implementation
|
||||
|
||||
If the main thread panics it will terminate all your threads and end your
|
||||
program with code `101`.
|
||||
|
||||
# Examples
|
||||
|
||||
```should_panic
|
||||
# #![allow(unreachable_code)]
|
||||
panic!();
|
||||
panic!("this is a terrible mistake!");
|
||||
panic!(4); // panic with the value of 4 to be collected elsewhere
|
||||
panic!("this is a {} {message}", "fancy", message = "message");
|
||||
```
|
||||
830
libgrust/rustc-lib/core/src/marker.rs
Normal file
830
libgrust/rustc-lib/core/src/marker.rs
Normal file
@@ -0,0 +1,830 @@
|
||||
//! Primitive traits and types representing basic properties of types.
|
||||
//!
|
||||
//! Rust types can be classified in various useful ways according to
|
||||
//! their intrinsic properties. These classifications are represented
|
||||
//! as traits.
|
||||
|
||||
#![stable(feature = "rust1", since = "1.0.0")]
|
||||
|
||||
use crate::cell::UnsafeCell;
|
||||
use crate::cmp;
|
||||
use crate::fmt::Debug;
|
||||
use crate::hash::Hash;
|
||||
use crate::hash::Hasher;
|
||||
|
||||
/// Types that can be transferred across thread boundaries.
|
||||
///
|
||||
/// This trait is automatically implemented when the compiler determines it's
|
||||
/// appropriate.
|
||||
///
|
||||
/// An example of a non-`Send` type is the reference-counting pointer
|
||||
/// [`rc::Rc`][`Rc`]. If two threads attempt to clone [`Rc`]s that point to the same
|
||||
/// reference-counted value, they might try to update the reference count at the
|
||||
/// same time, which is [undefined behavior][ub] because [`Rc`] doesn't use atomic
|
||||
/// operations. Its cousin [`sync::Arc`][arc] does use atomic operations (incurring
|
||||
/// some overhead) and thus is `Send`.
|
||||
///
|
||||
/// See [the Nomicon](../../nomicon/send-and-sync.html) for more details.
|
||||
///
|
||||
/// [`Rc`]: ../../std/rc/struct.Rc.html
|
||||
/// [arc]: ../../std/sync/struct.Arc.html
|
||||
/// [ub]: ../../reference/behavior-considered-undefined.html
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[cfg_attr(not(test), rustc_diagnostic_item = "send_trait")]
|
||||
#[rustc_on_unimplemented(
|
||||
message = "`{Self}` cannot be sent between threads safely",
|
||||
label = "`{Self}` cannot be sent between threads safely"
|
||||
)]
|
||||
pub unsafe auto trait Send {
|
||||
// empty.
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: ?Sized> !Send for *const T {}
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: ?Sized> !Send for *mut T {}
|
||||
|
||||
/// Types with a constant size known at compile time.
|
||||
///
|
||||
/// All type parameters have an implicit bound of `Sized`. The special syntax
|
||||
/// `?Sized` can be used to remove this bound if it's not appropriate.
|
||||
///
|
||||
/// ```
|
||||
/// # #![allow(dead_code)]
|
||||
/// struct Foo<T>(T);
|
||||
/// struct Bar<T: ?Sized>(T);
|
||||
///
|
||||
/// // struct FooUse(Foo<[i32]>); // error: Sized is not implemented for [i32]
|
||||
/// struct BarUse(Bar<[i32]>); // OK
|
||||
/// ```
|
||||
///
|
||||
/// The one exception is the implicit `Self` type of a trait. A trait does not
|
||||
/// have an implicit `Sized` bound as this is incompatible with [trait object]s
|
||||
/// where, by definition, the trait needs to work with all possible implementors,
|
||||
/// and thus could be any size.
|
||||
///
|
||||
/// Although Rust will let you bind `Sized` to a trait, you won't
|
||||
/// be able to use it to form a trait object later:
|
||||
///
|
||||
/// ```
|
||||
/// # #![allow(unused_variables)]
|
||||
/// trait Foo { }
|
||||
/// trait Bar: Sized { }
|
||||
///
|
||||
/// struct Impl;
|
||||
/// impl Foo for Impl { }
|
||||
/// impl Bar for Impl { }
|
||||
///
|
||||
/// let x: &dyn Foo = &Impl; // OK
|
||||
/// // let y: &dyn Bar = &Impl; // error: the trait `Bar` cannot
|
||||
/// // be made into an object
|
||||
/// ```
|
||||
///
|
||||
/// [trait object]: ../../book/ch17-02-trait-objects.html
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[lang = "sized"]
|
||||
#[rustc_on_unimplemented(
|
||||
message = "the size for values of type `{Self}` cannot be known at compilation time",
|
||||
label = "doesn't have a size known at compile-time"
|
||||
)]
|
||||
#[fundamental] // for Default, for example, which requires that `[T]: !Default` be evaluatable
|
||||
#[rustc_specialization_trait]
|
||||
pub trait Sized {
|
||||
// Empty.
|
||||
}
|
||||
|
||||
/// Types that can be "unsized" to a dynamically-sized type.
|
||||
///
|
||||
/// For example, the sized array type `[i8; 2]` implements `Unsize<[i8]>` and
|
||||
/// `Unsize<dyn fmt::Debug>`.
|
||||
///
|
||||
/// All implementations of `Unsize` are provided automatically by the compiler.
|
||||
///
|
||||
/// `Unsize` is implemented for:
|
||||
///
|
||||
/// - `[T; N]` is `Unsize<[T]>`
|
||||
/// - `T` is `Unsize<dyn Trait>` when `T: Trait`
|
||||
/// - `Foo<..., T, ...>` is `Unsize<Foo<..., U, ...>>` if:
|
||||
/// - `T: Unsize<U>`
|
||||
/// - Foo is a struct
|
||||
/// - Only the last field of `Foo` has a type involving `T`
|
||||
/// - `T` is not part of the type of any other fields
|
||||
/// - `Bar<T>: Unsize<Bar<U>>`, if the last field of `Foo` has type `Bar<T>`
|
||||
///
|
||||
/// `Unsize` is used along with [`ops::CoerceUnsized`] to allow
|
||||
/// "user-defined" containers such as [`Rc`] to contain dynamically-sized
|
||||
/// types. See the [DST coercion RFC][RFC982] and [the nomicon entry on coercion][nomicon-coerce]
|
||||
/// for more details.
|
||||
///
|
||||
/// [`ops::CoerceUnsized`]: crate::ops::CoerceUnsized
|
||||
/// [`Rc`]: ../../std/rc/struct.Rc.html
|
||||
/// [RFC982]: https://github.com/rust-lang/rfcs/blob/master/text/0982-dst-coercion.md
|
||||
/// [nomicon-coerce]: ../../nomicon/coercions.html
|
||||
#[unstable(feature = "unsize", issue = "27732")]
|
||||
#[lang = "unsize"]
|
||||
pub trait Unsize<T: ?Sized> {
|
||||
// Empty.
|
||||
}
|
||||
|
||||
/// Required trait for constants used in pattern matches.
|
||||
///
|
||||
/// Any type that derives `PartialEq` automatically implements this trait,
|
||||
/// *regardless* of whether its type-parameters implement `Eq`.
|
||||
///
|
||||
/// If a `const` item contains some type that does not implement this trait,
|
||||
/// then that type either (1.) does not implement `PartialEq` (which means the
|
||||
/// constant will not provide that comparison method, which code generation
|
||||
/// assumes is available), or (2.) it implements *its own* version of
|
||||
/// `PartialEq` (which we assume does not conform to a structural-equality
|
||||
/// comparison).
|
||||
///
|
||||
/// In either of the two scenarios above, we reject usage of such a constant in
|
||||
/// a pattern match.
|
||||
///
|
||||
/// See also the [structural match RFC][RFC1445], and [issue 63438] which
|
||||
/// motivated migrating from attribute-based design to this trait.
|
||||
///
|
||||
/// [RFC1445]: https://github.com/rust-lang/rfcs/blob/master/text/1445-restrict-constants-in-patterns.md
|
||||
/// [issue 63438]: https://github.com/rust-lang/rust/issues/63438
|
||||
#[unstable(feature = "structural_match", issue = "31434")]
|
||||
#[rustc_on_unimplemented(message = "the type `{Self}` does not `#[derive(PartialEq)]`")]
|
||||
#[lang = "structural_peq"]
|
||||
pub trait StructuralPartialEq {
|
||||
// Empty.
|
||||
}
|
||||
|
||||
/// Required trait for constants used in pattern matches.
|
||||
///
|
||||
/// Any type that derives `Eq` automatically implements this trait, *regardless*
|
||||
/// of whether its type-parameters implement `Eq`.
|
||||
///
|
||||
/// This is a hack to workaround a limitation in our type-system.
|
||||
///
|
||||
/// Background:
|
||||
///
|
||||
/// We want to require that types of consts used in pattern matches
|
||||
/// have the attribute `#[derive(PartialEq, Eq)]`.
|
||||
///
|
||||
/// In a more ideal world, we could check that requirement by just checking that
|
||||
/// the given type implements both (1.) the `StructuralPartialEq` trait *and*
|
||||
/// (2.) the `Eq` trait. However, you can have ADTs that *do* `derive(PartialEq, Eq)`,
|
||||
/// and be a case that we want the compiler to accept, and yet the constant's
|
||||
/// type fails to implement `Eq`.
|
||||
///
|
||||
/// Namely, a case like this:
|
||||
///
|
||||
/// ```rust
|
||||
/// #[derive(PartialEq, Eq)]
|
||||
/// struct Wrap<X>(X);
|
||||
/// fn higher_order(_: &()) { }
|
||||
/// const CFN: Wrap<fn(&())> = Wrap(higher_order);
|
||||
/// fn main() {
|
||||
/// match CFN {
|
||||
/// CFN => {}
|
||||
/// _ => {}
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// (The problem in the above code is that `Wrap<fn(&())>` does not implement
|
||||
/// `PartialEq`, nor `Eq`, because `for<'a> fn(&'a _)` does not implement those
|
||||
/// traits.)
|
||||
///
|
||||
/// Therefore, we cannot rely on naive check for `StructuralPartialEq` and
|
||||
/// mere `Eq`.
|
||||
///
|
||||
/// As a hack to work around this, we use two separate traits injected by each
|
||||
/// of the two derives (`#[derive(PartialEq)]` and `#[derive(Eq)]`) and check
|
||||
/// that both of them are present as part of structural-match checking.
|
||||
#[unstable(feature = "structural_match", issue = "31434")]
|
||||
#[rustc_on_unimplemented(message = "the type `{Self}` does not `#[derive(Eq)]`")]
|
||||
#[lang = "structural_teq"]
|
||||
pub trait StructuralEq {
|
||||
// Empty.
|
||||
}
|
||||
|
||||
/// Types whose values can be duplicated simply by copying bits.
|
||||
///
|
||||
/// By default, variable bindings have 'move semantics.' In other
|
||||
/// words:
|
||||
///
|
||||
/// ```
|
||||
/// #[derive(Debug)]
|
||||
/// struct Foo;
|
||||
///
|
||||
/// let x = Foo;
|
||||
///
|
||||
/// let y = x;
|
||||
///
|
||||
/// // `x` has moved into `y`, and so cannot be used
|
||||
///
|
||||
/// // println!("{:?}", x); // error: use of moved value
|
||||
/// ```
|
||||
///
|
||||
/// However, if a type implements `Copy`, it instead has 'copy semantics':
|
||||
///
|
||||
/// ```
|
||||
/// // We can derive a `Copy` implementation. `Clone` is also required, as it's
|
||||
/// // a supertrait of `Copy`.
|
||||
/// #[derive(Debug, Copy, Clone)]
|
||||
/// struct Foo;
|
||||
///
|
||||
/// let x = Foo;
|
||||
///
|
||||
/// let y = x;
|
||||
///
|
||||
/// // `y` is a copy of `x`
|
||||
///
|
||||
/// println!("{:?}", x); // A-OK!
|
||||
/// ```
|
||||
///
|
||||
/// It's important to note that in these two examples, the only difference is whether you
|
||||
/// are allowed to access `x` after the assignment. Under the hood, both a copy and a move
|
||||
/// can result in bits being copied in memory, although this is sometimes optimized away.
|
||||
///
|
||||
/// ## How can I implement `Copy`?
|
||||
///
|
||||
/// There are two ways to implement `Copy` on your type. The simplest is to use `derive`:
|
||||
///
|
||||
/// ```
|
||||
/// #[derive(Copy, Clone)]
|
||||
/// struct MyStruct;
|
||||
/// ```
|
||||
///
|
||||
/// You can also implement `Copy` and `Clone` manually:
|
||||
///
|
||||
/// ```
|
||||
/// struct MyStruct;
|
||||
///
|
||||
/// impl Copy for MyStruct { }
|
||||
///
|
||||
/// impl Clone for MyStruct {
|
||||
/// fn clone(&self) -> MyStruct {
|
||||
/// *self
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// There is a small difference between the two: the `derive` strategy will also place a `Copy`
|
||||
/// bound on type parameters, which isn't always desired.
|
||||
///
|
||||
/// ## What's the difference between `Copy` and `Clone`?
|
||||
///
|
||||
/// Copies happen implicitly, for example as part of an assignment `y = x`. The behavior of
|
||||
/// `Copy` is not overloadable; it is always a simple bit-wise copy.
|
||||
///
|
||||
/// Cloning is an explicit action, `x.clone()`. The implementation of [`Clone`] can
|
||||
/// provide any type-specific behavior necessary to duplicate values safely. For example,
|
||||
/// the implementation of [`Clone`] for [`String`] needs to copy the pointed-to string
|
||||
/// buffer in the heap. A simple bitwise copy of [`String`] values would merely copy the
|
||||
/// pointer, leading to a double free down the line. For this reason, [`String`] is [`Clone`]
|
||||
/// but not `Copy`.
|
||||
///
|
||||
/// [`Clone`] is a supertrait of `Copy`, so everything which is `Copy` must also implement
|
||||
/// [`Clone`]. If a type is `Copy` then its [`Clone`] implementation only needs to return `*self`
|
||||
/// (see the example above).
|
||||
///
|
||||
/// ## When can my type be `Copy`?
|
||||
///
|
||||
/// A type can implement `Copy` if all of its components implement `Copy`. For example, this
|
||||
/// struct can be `Copy`:
|
||||
///
|
||||
/// ```
|
||||
/// # #[allow(dead_code)]
|
||||
/// #[derive(Copy, Clone)]
|
||||
/// struct Point {
|
||||
/// x: i32,
|
||||
/// y: i32,
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// A struct can be `Copy`, and [`i32`] is `Copy`, therefore `Point` is eligible to be `Copy`.
|
||||
/// By contrast, consider
|
||||
///
|
||||
/// ```
|
||||
/// # #![allow(dead_code)]
|
||||
/// # struct Point;
|
||||
/// struct PointList {
|
||||
/// points: Vec<Point>,
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// The struct `PointList` cannot implement `Copy`, because [`Vec<T>`] is not `Copy`. If we
|
||||
/// attempt to derive a `Copy` implementation, we'll get an error:
|
||||
///
|
||||
/// ```text
|
||||
/// the trait `Copy` may not be implemented for this type; field `points` does not implement `Copy`
|
||||
/// ```
|
||||
///
|
||||
/// Shared references (`&T`) are also `Copy`, so a type can be `Copy`, even when it holds
|
||||
/// shared references of types `T` that are *not* `Copy`. Consider the following struct,
|
||||
/// which can implement `Copy`, because it only holds a *shared reference* to our non-`Copy`
|
||||
/// type `PointList` from above:
|
||||
///
|
||||
/// ```
|
||||
/// # #![allow(dead_code)]
|
||||
/// # struct PointList;
|
||||
/// #[derive(Copy, Clone)]
|
||||
/// struct PointListWrapper<'a> {
|
||||
/// point_list_ref: &'a PointList,
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// ## When *can't* my type be `Copy`?
|
||||
///
|
||||
/// Some types can't be copied safely. For example, copying `&mut T` would create an aliased
|
||||
/// mutable reference. Copying [`String`] would duplicate responsibility for managing the
|
||||
/// [`String`]'s buffer, leading to a double free.
|
||||
///
|
||||
/// Generalizing the latter case, any type implementing [`Drop`] can't be `Copy`, because it's
|
||||
/// managing some resource besides its own [`size_of::<T>`] bytes.
|
||||
///
|
||||
/// If you try to implement `Copy` on a struct or enum containing non-`Copy` data, you will get
|
||||
/// the error [E0204].
|
||||
///
|
||||
/// [E0204]: ../../error-index.html#E0204
|
||||
///
|
||||
/// ## When *should* my type be `Copy`?
|
||||
///
|
||||
/// Generally speaking, if your type _can_ implement `Copy`, it should. Keep in mind, though,
|
||||
/// that implementing `Copy` is part of the public API of your type. If the type might become
|
||||
/// non-`Copy` in the future, it could be prudent to omit the `Copy` implementation now, to
|
||||
/// avoid a breaking API change.
|
||||
///
|
||||
/// ## Additional implementors
|
||||
///
|
||||
/// In addition to the [implementors listed below][impls],
|
||||
/// the following types also implement `Copy`:
|
||||
///
|
||||
/// * Function item types (i.e., the distinct types defined for each function)
|
||||
/// * Function pointer types (e.g., `fn() -> i32`)
|
||||
/// * Array types, for all sizes, if the item type also implements `Copy` (e.g., `[i32; 123456]`)
|
||||
/// * Tuple types, if each component also implements `Copy` (e.g., `()`, `(i32, bool)`)
|
||||
/// * Closure types, if they capture no value from the environment
|
||||
/// or if all such captured values implement `Copy` themselves.
|
||||
/// Note that variables captured by shared reference always implement `Copy`
|
||||
/// (even if the referent doesn't),
|
||||
/// while variables captured by mutable reference never implement `Copy`.
|
||||
///
|
||||
/// [`Vec<T>`]: ../../std/vec/struct.Vec.html
|
||||
/// [`String`]: ../../std/string/struct.String.html
|
||||
/// [`size_of::<T>`]: crate::mem::size_of
|
||||
/// [impls]: #implementors
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[lang = "copy"]
|
||||
// FIXME(matthewjasper) This allows copying a type that doesn't implement
|
||||
// `Copy` because of unsatisfied lifetime bounds (copying `A<'_>` when only
|
||||
// `A<'static>: Copy` and `A<'_>: Clone`).
|
||||
// We have this attribute here for now only because there are quite a few
|
||||
// existing specializations on `Copy` that already exist in the standard
|
||||
// library, and there's no way to safely have this behavior right now.
|
||||
#[rustc_unsafe_specialization_marker]
|
||||
pub trait Copy: Clone {
|
||||
// Empty.
|
||||
}
|
||||
|
||||
/// Derive macro generating an impl of the trait `Copy`.
|
||||
#[rustc_builtin_macro]
|
||||
#[stable(feature = "builtin_macro_prelude", since = "1.38.0")]
|
||||
#[allow_internal_unstable(core_intrinsics, derive_clone_copy)]
|
||||
pub macro Copy($item:item) {
|
||||
/* compiler built-in */
|
||||
}
|
||||
|
||||
/// Types for which it is safe to share references between threads.
|
||||
///
|
||||
/// This trait is automatically implemented when the compiler determines
|
||||
/// it's appropriate.
|
||||
///
|
||||
/// The precise definition is: a type `T` is [`Sync`] if and only if `&T` is
|
||||
/// [`Send`]. In other words, if there is no possibility of
|
||||
/// [undefined behavior][ub] (including data races) when passing
|
||||
/// `&T` references between threads.
|
||||
///
|
||||
/// As one would expect, primitive types like [`u8`] and [`f64`]
|
||||
/// are all [`Sync`], and so are simple aggregate types containing them,
|
||||
/// like tuples, structs and enums. More examples of basic [`Sync`]
|
||||
/// types include "immutable" types like `&T`, and those with simple
|
||||
/// inherited mutability, such as [`Box<T>`][box], [`Vec<T>`][vec] and
|
||||
/// most other collection types. (Generic parameters need to be [`Sync`]
|
||||
/// for their container to be [`Sync`].)
|
||||
///
|
||||
/// A somewhat surprising consequence of the definition is that `&mut T`
|
||||
/// is `Sync` (if `T` is `Sync`) even though it seems like that might
|
||||
/// provide unsynchronized mutation. The trick is that a mutable
|
||||
/// reference behind a shared reference (that is, `& &mut T`)
|
||||
/// becomes read-only, as if it were a `& &T`. Hence there is no risk
|
||||
/// of a data race.
|
||||
///
|
||||
/// Types that are not `Sync` are those that have "interior
|
||||
/// mutability" in a non-thread-safe form, such as [`Cell`][cell]
|
||||
/// and [`RefCell`][refcell]. These types allow for mutation of
|
||||
/// their contents even through an immutable, shared reference. For
|
||||
/// example the `set` method on [`Cell<T>`][cell] takes `&self`, so it requires
|
||||
/// only a shared reference [`&Cell<T>`][cell]. The method performs no
|
||||
/// synchronization, thus [`Cell`][cell] cannot be `Sync`.
|
||||
///
|
||||
/// Another example of a non-`Sync` type is the reference-counting
|
||||
/// pointer [`Rc`][rc]. Given any reference [`&Rc<T>`][rc], you can clone
|
||||
/// a new [`Rc<T>`][rc], modifying the reference counts in a non-atomic way.
|
||||
///
|
||||
/// For cases when one does need thread-safe interior mutability,
|
||||
/// Rust provides [atomic data types], as well as explicit locking via
|
||||
/// [`sync::Mutex`][mutex] and [`sync::RwLock`][rwlock]. These types
|
||||
/// ensure that any mutation cannot cause data races, hence the types
|
||||
/// are `Sync`. Likewise, [`sync::Arc`][arc] provides a thread-safe
|
||||
/// analogue of [`Rc`][rc].
|
||||
///
|
||||
/// Any types with interior mutability must also use the
|
||||
/// [`cell::UnsafeCell`][unsafecell] wrapper around the value(s) which
|
||||
/// can be mutated through a shared reference. Failing to doing this is
|
||||
/// [undefined behavior][ub]. For example, [`transmute`][transmute]-ing
|
||||
/// from `&T` to `&mut T` is invalid.
|
||||
///
|
||||
/// See [the Nomicon][nomicon-send-and-sync] for more details about `Sync`.
|
||||
///
|
||||
/// [box]: ../../std/boxed/struct.Box.html
|
||||
/// [vec]: ../../std/vec/struct.Vec.html
|
||||
/// [cell]: crate::cell::Cell
|
||||
/// [refcell]: crate::cell::RefCell
|
||||
/// [rc]: ../../std/rc/struct.Rc.html
|
||||
/// [arc]: ../../std/sync/struct.Arc.html
|
||||
/// [atomic data types]: crate::sync::atomic
|
||||
/// [mutex]: ../../std/sync/struct.Mutex.html
|
||||
/// [rwlock]: ../../std/sync/struct.RwLock.html
|
||||
/// [unsafecell]: crate::cell::UnsafeCell
|
||||
/// [ub]: ../../reference/behavior-considered-undefined.html
|
||||
/// [transmute]: crate::mem::transmute
|
||||
/// [nomicon-send-and-sync]: ../../nomicon/send-and-sync.html
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[cfg_attr(not(test), rustc_diagnostic_item = "sync_trait")]
|
||||
#[lang = "sync"]
|
||||
#[rustc_on_unimplemented(
|
||||
message = "`{Self}` cannot be shared between threads safely",
|
||||
label = "`{Self}` cannot be shared between threads safely"
|
||||
)]
|
||||
pub unsafe auto trait Sync {
|
||||
// FIXME(estebank): once support to add notes in `rustc_on_unimplemented`
|
||||
// lands in beta, and it has been extended to check whether a closure is
|
||||
// anywhere in the requirement chain, extend it as such (#48534):
|
||||
// ```
|
||||
// on(
|
||||
// closure,
|
||||
// note="`{Self}` cannot be shared safely, consider marking the closure `move`"
|
||||
// ),
|
||||
// ```
|
||||
|
||||
// Empty
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: ?Sized> !Sync for *const T {}
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: ?Sized> !Sync for *mut T {}
|
||||
|
||||
macro_rules! impls {
|
||||
($t: ident) => {
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: ?Sized> Hash for $t<T> {
|
||||
#[inline]
|
||||
fn hash<H: Hasher>(&self, _: &mut H) {}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: ?Sized> cmp::PartialEq for $t<T> {
|
||||
fn eq(&self, _other: &$t<T>) -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: ?Sized> cmp::Eq for $t<T> {}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: ?Sized> cmp::PartialOrd for $t<T> {
|
||||
fn partial_cmp(&self, _other: &$t<T>) -> Option<cmp::Ordering> {
|
||||
Option::Some(cmp::Ordering::Equal)
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: ?Sized> cmp::Ord for $t<T> {
|
||||
fn cmp(&self, _other: &$t<T>) -> cmp::Ordering {
|
||||
cmp::Ordering::Equal
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: ?Sized> Copy for $t<T> {}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: ?Sized> Clone for $t<T> {
|
||||
fn clone(&self) -> Self {
|
||||
Self
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: ?Sized> Default for $t<T> {
|
||||
fn default() -> Self {
|
||||
Self
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "structural_match", issue = "31434")]
|
||||
impl<T: ?Sized> StructuralPartialEq for $t<T> {}
|
||||
|
||||
#[unstable(feature = "structural_match", issue = "31434")]
|
||||
impl<T: ?Sized> StructuralEq for $t<T> {}
|
||||
};
|
||||
}
|
||||
|
||||
/// Zero-sized type used to mark things that "act like" they own a `T`.
|
||||
///
|
||||
/// Adding a `PhantomData<T>` field to your type tells the compiler that your
|
||||
/// type acts as though it stores a value of type `T`, even though it doesn't
|
||||
/// really. This information is used when computing certain safety properties.
|
||||
///
|
||||
/// For a more in-depth explanation of how to use `PhantomData<T>`, please see
|
||||
/// [the Nomicon](../../nomicon/phantom-data.html).
|
||||
///
|
||||
/// # A ghastly note 👻👻👻
|
||||
///
|
||||
/// Though they both have scary names, `PhantomData` and 'phantom types' are
|
||||
/// related, but not identical. A phantom type parameter is simply a type
|
||||
/// parameter which is never used. In Rust, this often causes the compiler to
|
||||
/// complain, and the solution is to add a "dummy" use by way of `PhantomData`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ## Unused lifetime parameters
|
||||
///
|
||||
/// Perhaps the most common use case for `PhantomData` is a struct that has an
|
||||
/// unused lifetime parameter, typically as part of some unsafe code. For
|
||||
/// example, here is a struct `Slice` that has two pointers of type `*const T`,
|
||||
/// presumably pointing into an array somewhere:
|
||||
///
|
||||
/// ```compile_fail,E0392
|
||||
/// struct Slice<'a, T> {
|
||||
/// start: *const T,
|
||||
/// end: *const T,
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// The intention is that the underlying data is only valid for the
|
||||
/// lifetime `'a`, so `Slice` should not outlive `'a`. However, this
|
||||
/// intent is not expressed in the code, since there are no uses of
|
||||
/// the lifetime `'a` and hence it is not clear what data it applies
|
||||
/// to. We can correct this by telling the compiler to act *as if* the
|
||||
/// `Slice` struct contained a reference `&'a T`:
|
||||
///
|
||||
/// ```
|
||||
/// use std::marker::PhantomData;
|
||||
///
|
||||
/// # #[allow(dead_code)]
|
||||
/// struct Slice<'a, T: 'a> {
|
||||
/// start: *const T,
|
||||
/// end: *const T,
|
||||
/// phantom: PhantomData<&'a T>,
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// This also in turn requires the annotation `T: 'a`, indicating
|
||||
/// that any references in `T` are valid over the lifetime `'a`.
|
||||
///
|
||||
/// When initializing a `Slice` you simply provide the value
|
||||
/// `PhantomData` for the field `phantom`:
|
||||
///
|
||||
/// ```
|
||||
/// # #![allow(dead_code)]
|
||||
/// # use std::marker::PhantomData;
|
||||
/// # struct Slice<'a, T: 'a> {
|
||||
/// # start: *const T,
|
||||
/// # end: *const T,
|
||||
/// # phantom: PhantomData<&'a T>,
|
||||
/// # }
|
||||
/// fn borrow_vec<T>(vec: &Vec<T>) -> Slice<'_, T> {
|
||||
/// let ptr = vec.as_ptr();
|
||||
/// Slice {
|
||||
/// start: ptr,
|
||||
/// end: unsafe { ptr.add(vec.len()) },
|
||||
/// phantom: PhantomData,
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// ## Unused type parameters
|
||||
///
|
||||
/// It sometimes happens that you have unused type parameters which
|
||||
/// indicate what type of data a struct is "tied" to, even though that
|
||||
/// data is not actually found in the struct itself. Here is an
|
||||
/// example where this arises with [FFI]. The foreign interface uses
|
||||
/// handles of type `*mut ()` to refer to Rust values of different
|
||||
/// types. We track the Rust type using a phantom type parameter on
|
||||
/// the struct `ExternalResource` which wraps a handle.
|
||||
///
|
||||
/// [FFI]: ../../book/ch19-01-unsafe-rust.html#using-extern-functions-to-call-external-code
|
||||
///
|
||||
/// ```
|
||||
/// # #![allow(dead_code)]
|
||||
/// # trait ResType { }
|
||||
/// # struct ParamType;
|
||||
/// # mod foreign_lib {
|
||||
/// # pub fn new(_: usize) -> *mut () { 42 as *mut () }
|
||||
/// # pub fn do_stuff(_: *mut (), _: usize) {}
|
||||
/// # }
|
||||
/// # fn convert_params(_: ParamType) -> usize { 42 }
|
||||
/// use std::marker::PhantomData;
|
||||
/// use std::mem;
|
||||
///
|
||||
/// struct ExternalResource<R> {
|
||||
/// resource_handle: *mut (),
|
||||
/// resource_type: PhantomData<R>,
|
||||
/// }
|
||||
///
|
||||
/// impl<R: ResType> ExternalResource<R> {
|
||||
/// fn new() -> Self {
|
||||
/// let size_of_res = mem::size_of::<R>();
|
||||
/// Self {
|
||||
/// resource_handle: foreign_lib::new(size_of_res),
|
||||
/// resource_type: PhantomData,
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// fn do_stuff(&self, param: ParamType) {
|
||||
/// let foreign_params = convert_params(param);
|
||||
/// foreign_lib::do_stuff(self.resource_handle, foreign_params);
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// ## Ownership and the drop check
|
||||
///
|
||||
/// Adding a field of type `PhantomData<T>` indicates that your
|
||||
/// type owns data of type `T`. This in turn implies that when your
|
||||
/// type is dropped, it may drop one or more instances of the type
|
||||
/// `T`. This has bearing on the Rust compiler's [drop check]
|
||||
/// analysis.
|
||||
///
|
||||
/// If your struct does not in fact *own* the data of type `T`, it is
|
||||
/// better to use a reference type, like `PhantomData<&'a T>`
|
||||
/// (ideally) or `PhantomData<*const T>` (if no lifetime applies), so
|
||||
/// as not to indicate ownership.
|
||||
///
|
||||
/// [drop check]: ../../nomicon/dropck.html
|
||||
#[lang = "phantom_data"]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub struct PhantomData<T: ?Sized>;
|
||||
|
||||
impls! { PhantomData }
|
||||
|
||||
mod impls {
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
unsafe impl<T: Sync + ?Sized> Send for &T {}
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
unsafe impl<T: Send + ?Sized> Send for &mut T {}
|
||||
}
|
||||
|
||||
/// Compiler-internal trait used to indicate the type of enum discriminants.
|
||||
///
|
||||
/// This trait is automatically implemented for every type and does not add any
|
||||
/// guarantees to [`mem::Discriminant`]. It is **undefined behavior** to transmute
|
||||
/// between `DiscriminantKind::Discriminant` and `mem::Discriminant`.
|
||||
///
|
||||
/// [`mem::Discriminant`]: crate::mem::Discriminant
|
||||
#[unstable(
|
||||
feature = "discriminant_kind",
|
||||
issue = "none",
|
||||
reason = "this trait is unlikely to ever be stabilized, use `mem::discriminant` instead"
|
||||
)]
|
||||
#[lang = "discriminant_kind"]
|
||||
pub trait DiscriminantKind {
|
||||
/// The type of the discriminant, which must satisfy the trait
|
||||
/// bounds required by `mem::Discriminant`.
|
||||
#[lang = "discriminant_type"]
|
||||
type Discriminant: Clone + Copy + Debug + Eq + PartialEq + Hash + Send + Sync + Unpin;
|
||||
}
|
||||
|
||||
/// Compiler-internal trait used to determine whether a type contains
|
||||
/// any `UnsafeCell` internally, but not through an indirection.
|
||||
/// This affects, for example, whether a `static` of that type is
|
||||
/// placed in read-only static memory or writable static memory.
|
||||
#[lang = "freeze"]
|
||||
pub(crate) unsafe auto trait Freeze {}
|
||||
|
||||
impl<T: ?Sized> !Freeze for UnsafeCell<T> {}
|
||||
unsafe impl<T: ?Sized> Freeze for PhantomData<T> {}
|
||||
unsafe impl<T: ?Sized> Freeze for *const T {}
|
||||
unsafe impl<T: ?Sized> Freeze for *mut T {}
|
||||
unsafe impl<T: ?Sized> Freeze for &T {}
|
||||
unsafe impl<T: ?Sized> Freeze for &mut T {}
|
||||
|
||||
/// Types that can be safely moved after being pinned.
|
||||
///
|
||||
/// Rust itself has no notion of immovable types, and considers moves (e.g.,
|
||||
/// through assignment or [`mem::replace`]) to always be safe.
|
||||
///
|
||||
/// The [`Pin`][Pin] type is used instead to prevent moves through the type
|
||||
/// system. Pointers `P<T>` wrapped in the [`Pin<P<T>>`][Pin] wrapper can't be
|
||||
/// moved out of. See the [`pin` module] documentation for more information on
|
||||
/// pinning.
|
||||
///
|
||||
/// Implementing the `Unpin` trait for `T` lifts the restrictions of pinning off
|
||||
/// the type, which then allows moving `T` out of [`Pin<P<T>>`][Pin] with
|
||||
/// functions such as [`mem::replace`].
|
||||
///
|
||||
/// `Unpin` has no consequence at all for non-pinned data. In particular,
|
||||
/// [`mem::replace`] happily moves `!Unpin` data (it works for any `&mut T`, not
|
||||
/// just when `T: Unpin`). However, you cannot use [`mem::replace`] on data
|
||||
/// wrapped inside a [`Pin<P<T>>`][Pin] because you cannot get the `&mut T` you
|
||||
/// need for that, and *that* is what makes this system work.
|
||||
///
|
||||
/// So this, for example, can only be done on types implementing `Unpin`:
|
||||
///
|
||||
/// ```rust
|
||||
/// # #![allow(unused_must_use)]
|
||||
/// use std::mem;
|
||||
/// use std::pin::Pin;
|
||||
///
|
||||
/// let mut string = "this".to_string();
|
||||
/// let mut pinned_string = Pin::new(&mut string);
|
||||
///
|
||||
/// // We need a mutable reference to call `mem::replace`.
|
||||
/// // We can obtain such a reference by (implicitly) invoking `Pin::deref_mut`,
|
||||
/// // but that is only possible because `String` implements `Unpin`.
|
||||
/// mem::replace(&mut *pinned_string, "other".to_string());
|
||||
/// ```
|
||||
///
|
||||
/// This trait is automatically implemented for almost every type.
|
||||
///
|
||||
/// [`mem::replace`]: crate::mem::replace
|
||||
/// [Pin]: crate::pin::Pin
|
||||
/// [`pin` module]: crate::pin
|
||||
#[stable(feature = "pin", since = "1.33.0")]
|
||||
#[rustc_on_unimplemented(
|
||||
on(_Self = "std::future::Future", note = "consider using `Box::pin`",),
|
||||
message = "`{Self}` cannot be unpinned"
|
||||
)]
|
||||
#[lang = "unpin"]
|
||||
pub auto trait Unpin {}
|
||||
|
||||
/// A marker type which does not implement `Unpin`.
|
||||
///
|
||||
/// If a type contains a `PhantomPinned`, it will not implement `Unpin` by default.
|
||||
#[stable(feature = "pin", since = "1.33.0")]
|
||||
#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
|
||||
pub struct PhantomPinned;
|
||||
|
||||
#[stable(feature = "pin", since = "1.33.0")]
|
||||
impl !Unpin for PhantomPinned {}
|
||||
|
||||
#[stable(feature = "pin", since = "1.33.0")]
|
||||
impl<'a, T: ?Sized + 'a> Unpin for &'a T {}
|
||||
|
||||
#[stable(feature = "pin", since = "1.33.0")]
|
||||
impl<'a, T: ?Sized + 'a> Unpin for &'a mut T {}
|
||||
|
||||
#[stable(feature = "pin_raw", since = "1.38.0")]
|
||||
impl<T: ?Sized> Unpin for *const T {}
|
||||
|
||||
#[stable(feature = "pin_raw", since = "1.38.0")]
|
||||
impl<T: ?Sized> Unpin for *mut T {}
|
||||
|
||||
/// Implementations of `Copy` for primitive types.
|
||||
///
|
||||
/// Implementations that cannot be described in Rust
|
||||
/// are implemented in `traits::SelectionContext::copy_clone_conditions()`
|
||||
/// in `rustc_trait_selection`.
|
||||
mod copy_impls {
|
||||
|
||||
use super::Copy;
|
||||
|
||||
macro_rules! impl_copy {
|
||||
($($t:ty)*) => {
|
||||
$(
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl Copy for $t {}
|
||||
)*
|
||||
}
|
||||
}
|
||||
|
||||
impl_copy! {
|
||||
usize u8 u16 u32 u64 u128
|
||||
isize i8 i16 i32 i64 i128
|
||||
f32 f64
|
||||
bool char
|
||||
}
|
||||
|
||||
#[unstable(feature = "never_type", issue = "35121")]
|
||||
impl Copy for ! {}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: ?Sized> Copy for *const T {}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: ?Sized> Copy for *mut T {}
|
||||
|
||||
/// Shared references can be copied, but mutable references *cannot*!
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T: ?Sized> Copy for &T {}
|
||||
}
|
||||
162
libgrust/rustc-lib/core/src/mem/manually_drop.rs
Normal file
162
libgrust/rustc-lib/core/src/mem/manually_drop.rs
Normal file
@@ -0,0 +1,162 @@
|
||||
use crate::ops::{Deref, DerefMut};
|
||||
use crate::ptr;
|
||||
|
||||
/// A wrapper to inhibit compiler from automatically calling `T`’s destructor.
|
||||
/// This wrapper is 0-cost.
|
||||
///
|
||||
/// `ManuallyDrop<T>` is subject to the same layout optimizations as `T`.
|
||||
/// As a consequence, it has *no effect* on the assumptions that the compiler makes
|
||||
/// about its contents. For example, initializing a `ManuallyDrop<&mut T>`
|
||||
/// with [`mem::zeroed`] is undefined behavior.
|
||||
/// If you need to handle uninitialized data, use [`MaybeUninit<T>`] instead.
|
||||
///
|
||||
/// Note that accessing the value inside a `ManuallyDrop<T>` is safe.
|
||||
/// This means that a `ManuallyDrop<T>` whose content has been dropped must not
|
||||
/// be exposed through a public safe API.
|
||||
/// Correspondingly, `ManuallyDrop::drop` is unsafe.
|
||||
///
|
||||
/// # `ManuallyDrop` and drop order.
|
||||
///
|
||||
/// Rust has a well-defined [drop order] of values. To make sure that fields or
|
||||
/// locals are dropped in a specific order, reorder the declarations such that
|
||||
/// the implicit drop order is the correct one.
|
||||
///
|
||||
/// It is possible to use `ManuallyDrop` to control the drop order, but this
|
||||
/// requires unsafe code and is hard to do correctly in the presence of
|
||||
/// unwinding.
|
||||
///
|
||||
/// For example, if you want to make sure that a specific field is dropped after
|
||||
/// the others, make it the last field of a struct:
|
||||
///
|
||||
/// ```
|
||||
/// struct Context;
|
||||
///
|
||||
/// struct Widget {
|
||||
/// children: Vec<Widget>,
|
||||
/// // `context` will be dropped after `children`.
|
||||
/// // Rust guarantees that fields are dropped in the order of declaration.
|
||||
/// context: Context,
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// [drop order]: https://doc.rust-lang.org/reference/destructors.html
|
||||
/// [`mem::zeroed`]: crate::mem::zeroed
|
||||
/// [`MaybeUninit<T>`]: crate::mem::MaybeUninit
|
||||
#[stable(feature = "manually_drop", since = "1.20.0")]
|
||||
#[lang = "manually_drop"]
|
||||
#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
#[repr(transparent)]
|
||||
pub struct ManuallyDrop<T: ?Sized> {
|
||||
value: T,
|
||||
}
|
||||
|
||||
impl<T> ManuallyDrop<T> {
|
||||
/// Wrap a value to be manually dropped.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// use std::mem::ManuallyDrop;
|
||||
/// let mut x = ManuallyDrop::new(String::from("Hello World!"));
|
||||
/// x.truncate(5); // You can still safely operate on the value
|
||||
/// assert_eq!(*x, "Hello");
|
||||
/// // But `Drop` will not be run here
|
||||
/// ```
|
||||
#[must_use = "if you don't need the wrapper, you can use `mem::forget` instead"]
|
||||
#[stable(feature = "manually_drop", since = "1.20.0")]
|
||||
#[rustc_const_stable(feature = "const_manually_drop", since = "1.36.0")]
|
||||
#[inline(always)]
|
||||
pub const fn new(value: T) -> ManuallyDrop<T> {
|
||||
ManuallyDrop { value }
|
||||
}
|
||||
|
||||
/// Extracts the value from the `ManuallyDrop` container.
|
||||
///
|
||||
/// This allows the value to be dropped again.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// use std::mem::ManuallyDrop;
|
||||
/// let x = ManuallyDrop::new(Box::new(()));
|
||||
/// let _: Box<()> = ManuallyDrop::into_inner(x); // This drops the `Box`.
|
||||
/// ```
|
||||
#[stable(feature = "manually_drop", since = "1.20.0")]
|
||||
#[rustc_const_stable(feature = "const_manually_drop", since = "1.36.0")]
|
||||
#[inline(always)]
|
||||
pub const fn into_inner(slot: ManuallyDrop<T>) -> T {
|
||||
slot.value
|
||||
}
|
||||
|
||||
/// Takes the value from the `ManuallyDrop<T>` container out.
|
||||
///
|
||||
/// This method is primarily intended for moving out values in drop.
|
||||
/// Instead of using [`ManuallyDrop::drop`] to manually drop the value,
|
||||
/// you can use this method to take the value and use it however desired.
|
||||
///
|
||||
/// Whenever possible, it is preferable to use [`into_inner`][`ManuallyDrop::into_inner`]
|
||||
/// instead, which prevents duplicating the content of the `ManuallyDrop<T>`.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// This function semantically moves out the contained value without preventing further usage,
|
||||
/// leaving the state of this container unchanged.
|
||||
/// It is your responsibility to ensure that this `ManuallyDrop` is not used again.
|
||||
///
|
||||
#[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]
|
||||
pub unsafe fn take(slot: &mut ManuallyDrop<T>) -> T {
|
||||
// SAFETY: we are reading from a reference, which is guaranteed
|
||||
// to be valid for reads.
|
||||
unsafe { ptr::read(&slot.value) }
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: ?Sized> ManuallyDrop<T> {
|
||||
/// Manually drops the contained value. This is exactly equivalent to calling
|
||||
/// [`ptr::drop_in_place`] with a pointer to the contained value. As such, unless
|
||||
/// the contained value is a packed struct, the destructor will be called in-place
|
||||
/// without moving the value, and thus can be used to safely drop [pinned] data.
|
||||
///
|
||||
/// If you have ownership of the value, you can use [`ManuallyDrop::into_inner`] instead.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// This function runs the destructor of the contained value. Other than changes made by
|
||||
/// the destructor itself, the memory is left unchanged, and so as far as the compiler is
|
||||
/// concerned still holds a bit-pattern which is valid for the type `T`.
|
||||
///
|
||||
/// However, this "zombie" value should not be exposed to safe code, and this function
|
||||
/// should not be called more than once. To use a value after it's been dropped, or drop
|
||||
/// a value multiple times, can cause Undefined Behavior (depending on what `drop` does).
|
||||
/// This is normally prevented by the type system, but users of `ManuallyDrop` must
|
||||
/// uphold those guarantees without assistance from the compiler.
|
||||
///
|
||||
/// [pinned]: crate::pin
|
||||
#[stable(feature = "manually_drop", since = "1.20.0")]
|
||||
#[inline]
|
||||
pub unsafe fn drop(slot: &mut ManuallyDrop<T>) {
|
||||
// SAFETY: we are dropping the value pointed to by a mutable reference
|
||||
// which is guaranteed to be valid for writes.
|
||||
// It is up to the caller to make sure that `slot` isn't dropped again.
|
||||
unsafe { ptr::drop_in_place(&mut slot.value) }
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "manually_drop", since = "1.20.0")]
|
||||
impl<T: ?Sized> Deref for ManuallyDrop<T> {
|
||||
type Target = T;
|
||||
#[inline(always)]
|
||||
fn deref(&self) -> &T {
|
||||
&self.value
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "manually_drop", since = "1.20.0")]
|
||||
impl<T: ?Sized> DerefMut for ManuallyDrop<T> {
|
||||
#[inline(always)]
|
||||
fn deref_mut(&mut self) -> &mut T {
|
||||
&mut self.value
|
||||
}
|
||||
}
|
||||
854
libgrust/rustc-lib/core/src/mem/maybe_uninit.rs
Normal file
854
libgrust/rustc-lib/core/src/mem/maybe_uninit.rs
Normal file
@@ -0,0 +1,854 @@
|
||||
use crate::any::type_name;
|
||||
use crate::fmt;
|
||||
use crate::intrinsics;
|
||||
use crate::mem::ManuallyDrop;
|
||||
use crate::ptr;
|
||||
|
||||
/// A wrapper type to construct uninitialized instances of `T`.
|
||||
///
|
||||
/// # Initialization invariant
|
||||
///
|
||||
/// The compiler, in general, assumes that a variable is properly initialized
|
||||
/// according to the requirements of the variable's type. For example, a variable of
|
||||
/// reference type must be aligned and non-NULL. This is an invariant that must
|
||||
/// *always* be upheld, even in unsafe code. As a consequence, zero-initializing a
|
||||
/// variable of reference type causes instantaneous [undefined behavior][ub],
|
||||
/// no matter whether that reference ever gets used to access memory:
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// # #![allow(invalid_value)]
|
||||
/// use std::mem::{self, MaybeUninit};
|
||||
///
|
||||
/// let x: &i32 = unsafe { mem::zeroed() }; // undefined behavior! ⚠️
|
||||
/// // The equivalent code with `MaybeUninit<&i32>`:
|
||||
/// let x: &i32 = unsafe { MaybeUninit::zeroed().assume_init() }; // undefined behavior! ⚠️
|
||||
/// ```
|
||||
///
|
||||
/// This is exploited by the compiler for various optimizations, such as eliding
|
||||
/// run-time checks and optimizing `enum` layout.
|
||||
///
|
||||
/// Similarly, entirely uninitialized memory may have any content, while a `bool` must
|
||||
/// always be `true` or `false`. Hence, creating an uninitialized `bool` is undefined behavior:
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// # #![allow(invalid_value)]
|
||||
/// use std::mem::{self, MaybeUninit};
|
||||
///
|
||||
/// let b: bool = unsafe { mem::uninitialized() }; // undefined behavior! ⚠️
|
||||
/// // The equivalent code with `MaybeUninit<bool>`:
|
||||
/// let b: bool = unsafe { MaybeUninit::uninit().assume_init() }; // undefined behavior! ⚠️
|
||||
/// ```
|
||||
///
|
||||
/// Moreover, uninitialized memory is special in that the compiler knows that
|
||||
/// it does not have a fixed value. This makes it undefined behavior to have
|
||||
/// uninitialized data in a variable even if that variable has an integer type,
|
||||
/// which otherwise can hold any *fixed* bit pattern:
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// # #![allow(invalid_value)]
|
||||
/// use std::mem::{self, MaybeUninit};
|
||||
///
|
||||
/// let x: i32 = unsafe { mem::uninitialized() }; // undefined behavior! ⚠️
|
||||
/// // The equivalent code with `MaybeUninit<i32>`:
|
||||
/// let x: i32 = unsafe { MaybeUninit::uninit().assume_init() }; // undefined behavior! ⚠️
|
||||
/// ```
|
||||
/// (Notice that the rules around uninitialized integers are not finalized yet, but
|
||||
/// until they are, it is advisable to avoid them.)
|
||||
///
|
||||
/// On top of that, remember that most types have additional invariants beyond merely
|
||||
/// being considered initialized at the type level. For example, a `1`-initialized [`Vec<T>`]
|
||||
/// is considered initialized (under the current implementation; this does not constitute
|
||||
/// a stable guarantee) because the only requirement the compiler knows about it
|
||||
/// is that the data pointer must be non-null. Creating such a `Vec<T>` does not cause
|
||||
/// *immediate* undefined behavior, but will cause undefined behavior with most
|
||||
/// safe operations (including dropping it).
|
||||
///
|
||||
/// [`Vec<T>`]: ../../std/vec/struct.Vec.html
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// `MaybeUninit<T>` serves to enable unsafe code to deal with uninitialized data.
|
||||
/// It is a signal to the compiler indicating that the data here might *not*
|
||||
/// be initialized:
|
||||
///
|
||||
/// ```rust
|
||||
/// use std::mem::MaybeUninit;
|
||||
///
|
||||
/// // Create an explicitly uninitialized reference. The compiler knows that data inside
|
||||
/// // a `MaybeUninit<T>` may be invalid, and hence this is not UB:
|
||||
/// let mut x = MaybeUninit::<&i32>::uninit();
|
||||
/// // Set it to a valid value.
|
||||
/// unsafe { x.as_mut_ptr().write(&0); }
|
||||
/// // Extract the initialized data -- this is only allowed *after* properly
|
||||
/// // initializing `x`!
|
||||
/// let x = unsafe { x.assume_init() };
|
||||
/// ```
|
||||
///
|
||||
/// The compiler then knows to not make any incorrect assumptions or optimizations on this code.
|
||||
///
|
||||
/// You can think of `MaybeUninit<T>` as being a bit like `Option<T>` but without
|
||||
/// any of the run-time tracking and without any of the safety checks.
|
||||
///
|
||||
/// ## out-pointers
|
||||
///
|
||||
/// You can use `MaybeUninit<T>` to implement "out-pointers": instead of returning data
|
||||
/// from a function, pass it a pointer to some (uninitialized) memory to put the
|
||||
/// result into. This can be useful when it is important for the caller to control
|
||||
/// how the memory the result is stored in gets allocated, and you want to avoid
|
||||
/// unnecessary moves.
|
||||
///
|
||||
/// ```
|
||||
/// use std::mem::MaybeUninit;
|
||||
///
|
||||
/// unsafe fn make_vec(out: *mut Vec<i32>) {
|
||||
/// // `write` does not drop the old contents, which is important.
|
||||
/// out.write(vec![1, 2, 3]);
|
||||
/// }
|
||||
///
|
||||
/// let mut v = MaybeUninit::uninit();
|
||||
/// unsafe { make_vec(v.as_mut_ptr()); }
|
||||
/// // Now we know `v` is initialized! This also makes sure the vector gets
|
||||
/// // properly dropped.
|
||||
/// let v = unsafe { v.assume_init() };
|
||||
/// assert_eq!(&v, &[1, 2, 3]);
|
||||
/// ```
|
||||
///
|
||||
/// ## Initializing an array element-by-element
|
||||
///
|
||||
/// `MaybeUninit<T>` can be used to initialize a large array element-by-element:
|
||||
///
|
||||
/// ```
|
||||
/// use std::mem::{self, MaybeUninit};
|
||||
///
|
||||
/// let data = {
|
||||
/// // Create an uninitialized array of `MaybeUninit`. The `assume_init` is
|
||||
/// // safe because the type we are claiming to have initialized here is a
|
||||
/// // bunch of `MaybeUninit`s, which do not require initialization.
|
||||
/// let mut data: [MaybeUninit<Vec<u32>>; 1000] = unsafe {
|
||||
/// MaybeUninit::uninit().assume_init()
|
||||
/// };
|
||||
///
|
||||
/// // Dropping a `MaybeUninit` does nothing. Thus using raw pointer
|
||||
/// // assignment instead of `ptr::write` does not cause the old
|
||||
/// // uninitialized value to be dropped. Also if there is a panic during
|
||||
/// // this loop, we have a memory leak, but there is no memory safety
|
||||
/// // issue.
|
||||
/// for elem in &mut data[..] {
|
||||
/// *elem = MaybeUninit::new(vec![42]);
|
||||
/// }
|
||||
///
|
||||
/// // Everything is initialized. Transmute the array to the
|
||||
/// // initialized type.
|
||||
/// unsafe { mem::transmute::<_, [Vec<u32>; 1000]>(data) }
|
||||
/// };
|
||||
///
|
||||
/// assert_eq!(&data[0], &[42]);
|
||||
/// ```
|
||||
///
|
||||
/// You can also work with partially initialized arrays, which could
|
||||
/// be found in low-level datastructures.
|
||||
///
|
||||
/// ```
|
||||
/// use std::mem::MaybeUninit;
|
||||
/// use std::ptr;
|
||||
///
|
||||
/// // Create an uninitialized array of `MaybeUninit`. The `assume_init` is
|
||||
/// // safe because the type we are claiming to have initialized here is a
|
||||
/// // bunch of `MaybeUninit`s, which do not require initialization.
|
||||
/// let mut data: [MaybeUninit<String>; 1000] = unsafe { MaybeUninit::uninit().assume_init() };
|
||||
/// // Count the number of elements we have assigned.
|
||||
/// let mut data_len: usize = 0;
|
||||
///
|
||||
/// for elem in &mut data[0..500] {
|
||||
/// *elem = MaybeUninit::new(String::from("hello"));
|
||||
/// data_len += 1;
|
||||
/// }
|
||||
///
|
||||
/// // For each item in the array, drop if we allocated it.
|
||||
/// for elem in &mut data[0..data_len] {
|
||||
/// unsafe { ptr::drop_in_place(elem.as_mut_ptr()); }
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// ## Initializing a struct field-by-field
|
||||
///
|
||||
/// There is currently no supported way to create a raw pointer or reference
|
||||
/// to a field of a struct inside `MaybeUninit<Struct>`. That means it is not possible
|
||||
/// to create a struct by calling `MaybeUninit::uninit::<Struct>()` and then writing
|
||||
/// to its fields.
|
||||
///
|
||||
/// [ub]: ../../reference/behavior-considered-undefined.html
|
||||
///
|
||||
/// # Layout
|
||||
///
|
||||
/// `MaybeUninit<T>` is guaranteed to have the same size, alignment, and ABI as `T`:
|
||||
///
|
||||
/// ```rust
|
||||
/// use std::mem::{MaybeUninit, size_of, align_of};
|
||||
/// assert_eq!(size_of::<MaybeUninit<u64>>(), size_of::<u64>());
|
||||
/// assert_eq!(align_of::<MaybeUninit<u64>>(), align_of::<u64>());
|
||||
/// ```
|
||||
///
|
||||
/// However remember that a type *containing* a `MaybeUninit<T>` is not necessarily the same
|
||||
/// layout; Rust does not in general guarantee that the fields of a `Foo<T>` have the same order as
|
||||
/// a `Foo<U>` even if `T` and `U` have the same size and alignment. Furthermore because any bit
|
||||
/// value is valid for a `MaybeUninit<T>` the compiler can't apply non-zero/niche-filling
|
||||
/// optimizations, potentially resulting in a larger size:
|
||||
///
|
||||
/// ```rust
|
||||
/// # use std::mem::{MaybeUninit, size_of};
|
||||
/// assert_eq!(size_of::<Option<bool>>(), 1);
|
||||
/// assert_eq!(size_of::<Option<MaybeUninit<bool>>>(), 2);
|
||||
/// ```
|
||||
///
|
||||
/// If `T` is FFI-safe, then so is `MaybeUninit<T>`.
|
||||
///
|
||||
/// While `MaybeUninit` is `#[repr(transparent)]` (indicating it guarantees the same size,
|
||||
/// alignment, and ABI as `T`), this does *not* change any of the previous caveats. `Option<T>` and
|
||||
/// `Option<MaybeUninit<T>>` may still have different sizes, and types containing a field of type
|
||||
/// `T` may be laid out (and sized) differently than if that field were `MaybeUninit<T>`.
|
||||
/// `MaybeUninit` is a union type, and `#[repr(transparent)]` on unions is unstable (see [the
|
||||
/// tracking issue](https://github.com/rust-lang/rust/issues/60405)). Over time, the exact
|
||||
/// guarantees of `#[repr(transparent)]` on unions may evolve, and `MaybeUninit` may or may not
|
||||
/// remain `#[repr(transparent)]`. That said, `MaybeUninit<T>` will *always* guarantee that it has
|
||||
/// the same size, alignment, and ABI as `T`; it's just that the way `MaybeUninit` implements that
|
||||
/// guarantee may evolve.
|
||||
#[stable(feature = "maybe_uninit", since = "1.36.0")]
|
||||
// Lang item so we can wrap other types in it. This is useful for generators.
|
||||
#[lang = "maybe_uninit"]
|
||||
#[derive(Copy)]
|
||||
#[repr(transparent)]
|
||||
pub union MaybeUninit<T> {
|
||||
uninit: (),
|
||||
value: ManuallyDrop<T>,
|
||||
}
|
||||
|
||||
#[stable(feature = "maybe_uninit", since = "1.36.0")]
|
||||
impl<T: Copy> Clone for MaybeUninit<T> {
|
||||
#[inline(always)]
|
||||
fn clone(&self) -> Self {
|
||||
// Not calling `T::clone()`, we cannot know if we are initialized enough for that.
|
||||
*self
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "maybe_uninit_debug", since = "1.41.0")]
|
||||
impl<T> fmt::Debug for MaybeUninit<T> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.pad(type_name::<Self>())
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> MaybeUninit<T> {
|
||||
/// Creates a new `MaybeUninit<T>` initialized with the given value.
|
||||
/// It is safe to call [`assume_init`] on the return value of this function.
|
||||
///
|
||||
/// 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.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// use std::mem::MaybeUninit;
|
||||
///
|
||||
/// let v: MaybeUninit<Vec<u8>> = MaybeUninit::new(vec![42]);
|
||||
/// ```
|
||||
///
|
||||
/// [`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)]
|
||||
pub const fn new(val: T) -> MaybeUninit<T> {
|
||||
MaybeUninit { value: ManuallyDrop::new(val) }
|
||||
}
|
||||
|
||||
/// Creates a new `MaybeUninit<T>` in an uninitialized state.
|
||||
///
|
||||
/// 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.
|
||||
///
|
||||
/// See the [type-level documentation][MaybeUninit] for some examples.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// use std::mem::MaybeUninit;
|
||||
///
|
||||
/// let v: MaybeUninit<String> = MaybeUninit::uninit();
|
||||
/// ```
|
||||
#[stable(feature = "maybe_uninit", since = "1.36.0")]
|
||||
#[rustc_const_stable(feature = "const_maybe_uninit", since = "1.36.0")]
|
||||
#[inline(always)]
|
||||
#[rustc_diagnostic_item = "maybe_uninit_uninit"]
|
||||
pub const fn uninit() -> MaybeUninit<T> {
|
||||
MaybeUninit { uninit: () }
|
||||
}
|
||||
|
||||
/// Create a new array of `MaybeUninit<T>` items, in an uninitialized state.
|
||||
///
|
||||
/// Note: in a future Rust version this method may become unnecessary
|
||||
/// when array literal syntax allows
|
||||
/// [repeating const expressions](https://github.com/rust-lang/rust/issues/49147).
|
||||
/// The example below could then use `let mut buf = [MaybeUninit::<u8>::uninit(); 32];`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// #![feature(maybe_uninit_uninit_array, maybe_uninit_extra, maybe_uninit_slice)]
|
||||
///
|
||||
/// use std::mem::MaybeUninit;
|
||||
///
|
||||
/// extern "C" {
|
||||
/// fn read_into_buffer(ptr: *mut u8, max_len: usize) -> usize;
|
||||
/// }
|
||||
///
|
||||
/// /// Returns a (possibly smaller) slice of data that was actually read
|
||||
/// fn read(buf: &mut [MaybeUninit<u8>]) -> &[u8] {
|
||||
/// unsafe {
|
||||
/// let len = read_into_buffer(buf.as_mut_ptr() as *mut u8, buf.len());
|
||||
/// MaybeUninit::slice_assume_init_ref(&buf[..len])
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// let mut buf: [MaybeUninit<u8>; 32] = MaybeUninit::uninit_array();
|
||||
/// let data = read(&mut buf);
|
||||
/// ```
|
||||
#[unstable(feature = "maybe_uninit_uninit_array", issue = "none")]
|
||||
#[inline(always)]
|
||||
pub fn uninit_array<const LEN: usize>() -> [Self; LEN] {
|
||||
// SAFETY: An uninitialized `[MaybeUninit<_>; LEN]` is valid.
|
||||
unsafe { MaybeUninit::<[MaybeUninit<T>; LEN]>::uninit().assume_init() }
|
||||
}
|
||||
|
||||
/// Creates a new `MaybeUninit<T>` in an uninitialized state, with the memory being
|
||||
/// filled with `0` bytes. It depends on `T` whether that already makes for
|
||||
/// proper initialization. For example, `MaybeUninit<usize>::zeroed()` is initialized,
|
||||
/// but `MaybeUninit<&'static i32>::zeroed()` is not because references must not
|
||||
/// be null.
|
||||
///
|
||||
/// 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.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// Correct usage of this function: initializing a struct with zero, where all
|
||||
/// fields of the struct can hold the bit-pattern 0 as a valid value.
|
||||
///
|
||||
/// ```rust
|
||||
/// use std::mem::MaybeUninit;
|
||||
///
|
||||
/// let x = MaybeUninit::<(u8, bool)>::zeroed();
|
||||
/// let x = unsafe { x.assume_init() };
|
||||
/// assert_eq!(x, (0, false));
|
||||
/// ```
|
||||
///
|
||||
/// *Incorrect* usage of this function: calling `x.zeroed().assume_init()`
|
||||
/// when `0` is not a valid bit-pattern for the type:
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// use std::mem::MaybeUninit;
|
||||
///
|
||||
/// enum NotZero { One = 1, Two = 2 };
|
||||
///
|
||||
/// let x = MaybeUninit::<(u8, NotZero)>::zeroed();
|
||||
/// let x = unsafe { x.assume_init() };
|
||||
/// // Inside a pair, we create a `NotZero` that does not have a valid discriminant.
|
||||
/// // This is undefined behavior. ⚠️
|
||||
/// ```
|
||||
#[stable(feature = "maybe_uninit", since = "1.36.0")]
|
||||
#[inline]
|
||||
#[rustc_diagnostic_item = "maybe_uninit_zeroed"]
|
||||
pub fn zeroed() -> MaybeUninit<T> {
|
||||
let mut u = MaybeUninit::<T>::uninit();
|
||||
// SAFETY: `u.as_mut_ptr()` points to allocated memory.
|
||||
unsafe {
|
||||
u.as_mut_ptr().write_bytes(0u8, 1);
|
||||
}
|
||||
u
|
||||
}
|
||||
|
||||
/// Sets the value of the `MaybeUninit<T>`. This overwrites any previous value
|
||||
/// without dropping it, so be careful not to use this twice unless you want to
|
||||
/// skip running the destructor. For your convenience, this also returns a mutable
|
||||
/// reference to the (now safely initialized) contents of `self`.
|
||||
#[unstable(feature = "maybe_uninit_extra", issue = "63567")]
|
||||
#[inline(always)]
|
||||
pub fn write(&mut self, val: T) -> &mut T {
|
||||
*self = MaybeUninit::new(val);
|
||||
// SAFETY: We just initialized this value.
|
||||
unsafe { self.assume_init_mut() }
|
||||
}
|
||||
|
||||
/// Gets a pointer to the contained value. Reading from this pointer or turning it
|
||||
/// into a reference is undefined behavior unless the `MaybeUninit<T>` is initialized.
|
||||
/// Writing to memory that this pointer (non-transitively) points to is undefined behavior
|
||||
/// (except inside an `UnsafeCell<T>`).
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Correct usage of this method:
|
||||
///
|
||||
/// ```rust
|
||||
/// use std::mem::MaybeUninit;
|
||||
///
|
||||
/// let mut x = MaybeUninit::<Vec<u32>>::uninit();
|
||||
/// unsafe { x.as_mut_ptr().write(vec![0,1,2]); }
|
||||
/// // Create a reference into the `MaybeUninit<T>`. This is okay because we initialized it.
|
||||
/// let x_vec = unsafe { &*x.as_ptr() };
|
||||
/// assert_eq!(x_vec.len(), 3);
|
||||
/// ```
|
||||
///
|
||||
/// *Incorrect* usage of this method:
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// use std::mem::MaybeUninit;
|
||||
///
|
||||
/// let x = MaybeUninit::<Vec<u32>>::uninit();
|
||||
/// let x_vec = unsafe { &*x.as_ptr() };
|
||||
/// // We have created a reference to an uninitialized vector! This is undefined behavior. ⚠️
|
||||
/// ```
|
||||
///
|
||||
/// (Notice that the rules around references to uninitialized data are not finalized yet, but
|
||||
/// until they are, it is advisable to avoid them.)
|
||||
#[stable(feature = "maybe_uninit", since = "1.36.0")]
|
||||
#[rustc_const_unstable(feature = "const_maybe_uninit_as_ptr", issue = "75251")]
|
||||
#[inline(always)]
|
||||
pub const fn as_ptr(&self) -> *const T {
|
||||
// `MaybeUninit` and `ManuallyDrop` are both `repr(transparent)` so we can cast the pointer.
|
||||
self as *const _ as *const T
|
||||
}
|
||||
|
||||
/// Gets a mutable pointer to the contained value. Reading from this pointer or turning it
|
||||
/// into a reference is undefined behavior unless the `MaybeUninit<T>` is initialized.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Correct usage of this method:
|
||||
///
|
||||
/// ```rust
|
||||
/// use std::mem::MaybeUninit;
|
||||
///
|
||||
/// let mut x = MaybeUninit::<Vec<u32>>::uninit();
|
||||
/// unsafe { x.as_mut_ptr().write(vec![0,1,2]); }
|
||||
/// // Create a reference into the `MaybeUninit<Vec<u32>>`.
|
||||
/// // This is okay because we initialized it.
|
||||
/// let x_vec = unsafe { &mut *x.as_mut_ptr() };
|
||||
/// x_vec.push(3);
|
||||
/// assert_eq!(x_vec.len(), 4);
|
||||
/// ```
|
||||
///
|
||||
/// *Incorrect* usage of this method:
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// use std::mem::MaybeUninit;
|
||||
///
|
||||
/// let mut x = MaybeUninit::<Vec<u32>>::uninit();
|
||||
/// let x_vec = unsafe { &mut *x.as_mut_ptr() };
|
||||
/// // We have created a reference to an uninitialized vector! This is undefined behavior. ⚠️
|
||||
/// ```
|
||||
///
|
||||
/// (Notice that the rules around references to uninitialized data are not finalized yet, but
|
||||
/// until they are, it is advisable to avoid them.)
|
||||
#[stable(feature = "maybe_uninit", since = "1.36.0")]
|
||||
#[rustc_const_unstable(feature = "const_maybe_uninit_as_ptr", issue = "75251")]
|
||||
#[inline(always)]
|
||||
pub const fn as_mut_ptr(&mut self) -> *mut T {
|
||||
// `MaybeUninit` and `ManuallyDrop` are both `repr(transparent)` so we can cast the pointer.
|
||||
self as *mut _ as *mut T
|
||||
}
|
||||
|
||||
/// Extracts the value from the `MaybeUninit<T>` container. This is a great way
|
||||
/// to ensure that the data will get dropped, because the resulting `T` is
|
||||
/// subject to the usual drop handling.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// It is up to the caller to guarantee that the `MaybeUninit<T>` really is in an initialized
|
||||
/// state. Calling this when the content is not yet fully initialized causes immediate undefined
|
||||
/// behavior. The [type-level documentation][inv] contains more information about
|
||||
/// this initialization invariant.
|
||||
///
|
||||
/// [inv]: #initialization-invariant
|
||||
///
|
||||
/// On top of that, remember that most types have additional invariants beyond merely
|
||||
/// being considered initialized at the type level. For example, a `1`-initialized [`Vec<T>`]
|
||||
/// is considered initialized (under the current implementation; this does not constitute
|
||||
/// a stable guarantee) because the only requirement the compiler knows about it
|
||||
/// is that the data pointer must be non-null. Creating such a `Vec<T>` does not cause
|
||||
/// *immediate* undefined behavior, but will cause undefined behavior with most
|
||||
/// safe operations (including dropping it).
|
||||
///
|
||||
/// [`Vec<T>`]: ../../std/vec/struct.Vec.html
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Correct usage of this method:
|
||||
///
|
||||
/// ```rust
|
||||
/// use std::mem::MaybeUninit;
|
||||
///
|
||||
/// let mut x = MaybeUninit::<bool>::uninit();
|
||||
/// unsafe { x.as_mut_ptr().write(true); }
|
||||
/// let x_init = unsafe { x.assume_init() };
|
||||
/// assert_eq!(x_init, true);
|
||||
/// ```
|
||||
///
|
||||
/// *Incorrect* usage of this method:
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// use std::mem::MaybeUninit;
|
||||
///
|
||||
/// let x = MaybeUninit::<Vec<u32>>::uninit();
|
||||
/// let x_init = unsafe { x.assume_init() };
|
||||
/// // `x` had not been initialized yet, so this last line caused undefined behavior. ⚠️
|
||||
/// ```
|
||||
#[stable(feature = "maybe_uninit", since = "1.36.0")]
|
||||
#[inline(always)]
|
||||
#[rustc_diagnostic_item = "assume_init"]
|
||||
pub unsafe fn assume_init(self) -> T {
|
||||
// SAFETY: the caller must guarantee that `self` is initialized.
|
||||
// This also means that `self` must be a `value` variant.
|
||||
unsafe {
|
||||
intrinsics::assert_inhabited::<T>();
|
||||
ManuallyDrop::into_inner(self.value)
|
||||
}
|
||||
}
|
||||
|
||||
/// Reads the value from the `MaybeUninit<T>` container. The resulting `T` is subject
|
||||
/// to the usual drop handling.
|
||||
///
|
||||
/// Whenever possible, it is preferable to use [`assume_init`] instead, which
|
||||
/// prevents duplicating the content of the `MaybeUninit<T>`.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// It is up to the caller to guarantee that the `MaybeUninit<T>` really is in an initialized
|
||||
/// state. Calling this when the content is not yet fully initialized causes undefined
|
||||
/// behavior. The [type-level documentation][inv] contains more information about
|
||||
/// this initialization invariant.
|
||||
///
|
||||
/// Moreover, this leaves a copy of the same data behind in the `MaybeUninit<T>`. When using
|
||||
/// multiple copies of the data (by calling `assume_init_read` multiple times, or first
|
||||
/// calling `assume_init_read` and then [`assume_init`]), it is your responsibility
|
||||
/// to ensure that that data may indeed be duplicated.
|
||||
///
|
||||
/// [inv]: #initialization-invariant
|
||||
/// [`assume_init`]: MaybeUninit::assume_init
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Correct usage of this method:
|
||||
///
|
||||
/// ```rust
|
||||
/// #![feature(maybe_uninit_extra)]
|
||||
/// use std::mem::MaybeUninit;
|
||||
///
|
||||
/// let mut x = MaybeUninit::<u32>::uninit();
|
||||
/// x.write(13);
|
||||
/// let x1 = unsafe { x.assume_init_read() };
|
||||
/// // `u32` is `Copy`, so we may read multiple times.
|
||||
/// let x2 = unsafe { x.assume_init_read() };
|
||||
/// assert_eq!(x1, x2);
|
||||
///
|
||||
/// let mut x = MaybeUninit::<Option<Vec<u32>>>::uninit();
|
||||
/// x.write(None);
|
||||
/// let x1 = unsafe { x.assume_init_read() };
|
||||
/// // Duplicating a `None` value is okay, so we may read multiple times.
|
||||
/// let x2 = unsafe { x.assume_init_read() };
|
||||
/// assert_eq!(x1, x2);
|
||||
/// ```
|
||||
///
|
||||
/// *Incorrect* usage of this method:
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// #![feature(maybe_uninit_extra)]
|
||||
/// use std::mem::MaybeUninit;
|
||||
///
|
||||
/// let mut x = MaybeUninit::<Option<Vec<u32>>>::uninit();
|
||||
/// x.write(Some(vec![0,1,2]));
|
||||
/// let x1 = unsafe { x.assume_init_read() };
|
||||
/// let x2 = unsafe { x.assume_init_read() };
|
||||
/// // We now created two copies of the same vector, leading to a double-free ⚠️ when
|
||||
/// // they both get dropped!
|
||||
/// ```
|
||||
#[unstable(feature = "maybe_uninit_extra", issue = "63567")]
|
||||
#[inline(always)]
|
||||
pub unsafe fn assume_init_read(&self) -> T {
|
||||
// SAFETY: the caller must guarantee that `self` is initialized.
|
||||
// Reading from `self.as_ptr()` is safe since `self` should be initialized.
|
||||
unsafe {
|
||||
intrinsics::assert_inhabited::<T>();
|
||||
self.as_ptr().read()
|
||||
}
|
||||
}
|
||||
|
||||
/// Drops the contained value in place.
|
||||
///
|
||||
/// If you have ownership of the `MaybeUninit`, you can use [`assume_init`] instead.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// It is up to the caller to guarantee that the `MaybeUninit<T>` really is
|
||||
/// in an initialized state. Calling this when the content is not yet fully
|
||||
/// initialized causes undefined behavior.
|
||||
///
|
||||
/// On top of that, all additional invariants of the type `T` must be
|
||||
/// satisfied, as the `Drop` implementation of `T` (or its members) may
|
||||
/// rely on this. For example, a `1`-initialized [`Vec<T>`] is considered
|
||||
/// initialized (under the current implementation; this does not constitute
|
||||
/// a stable guarantee) because the only requirement the compiler knows
|
||||
/// about it is that the data pointer must be non-null. Dropping such a
|
||||
/// `Vec<T>` however will cause undefined behaviour.
|
||||
///
|
||||
/// [`assume_init`]: MaybeUninit::assume_init
|
||||
/// [`Vec<T>`]: ../../std/vec/struct.Vec.html
|
||||
#[unstable(feature = "maybe_uninit_extra", issue = "63567")]
|
||||
pub unsafe fn assume_init_drop(&mut self) {
|
||||
// SAFETY: the caller must guarantee that `self` is initialized and
|
||||
// satisfies all invariants of `T`.
|
||||
// Dropping the value in place is safe if that is the case.
|
||||
unsafe { ptr::drop_in_place(self.as_mut_ptr()) }
|
||||
}
|
||||
|
||||
/// Gets a shared reference to the contained value.
|
||||
///
|
||||
/// This can be useful when we want to access a `MaybeUninit` that has been
|
||||
/// initialized but don't have ownership of the `MaybeUninit` (preventing the use
|
||||
/// of `.assume_init()`).
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// Calling this when the content is not yet fully initialized causes undefined
|
||||
/// behavior: it is up to the caller to guarantee that the `MaybeUninit<T>` really
|
||||
/// is in an initialized state.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ### Correct usage of this method:
|
||||
///
|
||||
/// ```rust
|
||||
/// #![feature(maybe_uninit_ref)]
|
||||
/// use std::mem::MaybeUninit;
|
||||
///
|
||||
/// let mut x = MaybeUninit::<Vec<u32>>::uninit();
|
||||
/// // Initialize `x`:
|
||||
/// unsafe { x.as_mut_ptr().write(vec![1, 2, 3]); }
|
||||
/// // Now that our `MaybeUninit<_>` is known to be initialized, it is okay to
|
||||
/// // create a shared reference to it:
|
||||
/// let x: &Vec<u32> = unsafe {
|
||||
/// // SAFETY: `x` has been initialized.
|
||||
/// x.assume_init_ref()
|
||||
/// };
|
||||
/// assert_eq!(x, &vec![1, 2, 3]);
|
||||
/// ```
|
||||
///
|
||||
/// ### *Incorrect* usages of this method:
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// #![feature(maybe_uninit_ref)]
|
||||
/// use std::mem::MaybeUninit;
|
||||
///
|
||||
/// let x = MaybeUninit::<Vec<u32>>::uninit();
|
||||
/// let x_vec: &Vec<u32> = unsafe { x.assume_init_ref() };
|
||||
/// // We have created a reference to an uninitialized vector! This is undefined behavior. ⚠️
|
||||
/// ```
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// #![feature(maybe_uninit_ref)]
|
||||
/// use std::{cell::Cell, mem::MaybeUninit};
|
||||
///
|
||||
/// let b = MaybeUninit::<Cell<bool>>::uninit();
|
||||
/// // Initialize the `MaybeUninit` using `Cell::set`:
|
||||
/// unsafe {
|
||||
/// b.assume_init_ref().set(true);
|
||||
/// // ^^^^^^^^^^^^^^^
|
||||
/// // Reference to an uninitialized `Cell<bool>`: UB!
|
||||
/// }
|
||||
/// ```
|
||||
#[unstable(feature = "maybe_uninit_ref", issue = "63568")]
|
||||
#[inline(always)]
|
||||
pub unsafe fn assume_init_ref(&self) -> &T {
|
||||
// SAFETY: the caller must guarantee that `self` is initialized.
|
||||
// This also means that `self` must be a `value` variant.
|
||||
unsafe {
|
||||
intrinsics::assert_inhabited::<T>();
|
||||
&*self.value
|
||||
}
|
||||
}
|
||||
|
||||
/// Gets a mutable (unique) reference to the contained value.
|
||||
///
|
||||
/// This can be useful when we want to access a `MaybeUninit` that has been
|
||||
/// initialized but don't have ownership of the `MaybeUninit` (preventing the use
|
||||
/// of `.assume_init()`).
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// Calling this when the content is not yet fully initialized causes undefined
|
||||
/// behavior: it is up to the caller to guarantee that the `MaybeUninit<T>` really
|
||||
/// is in an initialized state. For instance, `.assume_init_mut()` cannot be used to
|
||||
/// initialize a `MaybeUninit`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ### Correct usage of this method:
|
||||
///
|
||||
/// ```rust
|
||||
/// #![feature(maybe_uninit_ref)]
|
||||
/// use std::mem::MaybeUninit;
|
||||
///
|
||||
/// # unsafe extern "C" fn initialize_buffer(buf: *mut [u8; 2048]) { *buf = [0; 2048] }
|
||||
/// # #[cfg(FALSE)]
|
||||
/// extern "C" {
|
||||
/// /// Initializes *all* the bytes of the input buffer.
|
||||
/// fn initialize_buffer(buf: *mut [u8; 2048]);
|
||||
/// }
|
||||
///
|
||||
/// let mut buf = MaybeUninit::<[u8; 2048]>::uninit();
|
||||
///
|
||||
/// // Initialize `buf`:
|
||||
/// unsafe { initialize_buffer(buf.as_mut_ptr()); }
|
||||
/// // Now we know that `buf` has been initialized, so we could `.assume_init()` it.
|
||||
/// // However, using `.assume_init()` may trigger a `memcpy` of the 2048 bytes.
|
||||
/// // To assert our buffer has been initialized without copying it, we upgrade
|
||||
/// // the `&mut MaybeUninit<[u8; 2048]>` to a `&mut [u8; 2048]`:
|
||||
/// let buf: &mut [u8; 2048] = unsafe {
|
||||
/// // SAFETY: `buf` has been initialized.
|
||||
/// buf.assume_init_mut()
|
||||
/// };
|
||||
///
|
||||
/// // Now we can use `buf` as a normal slice:
|
||||
/// buf.sort_unstable();
|
||||
/// assert!(
|
||||
/// buf.windows(2).all(|pair| pair[0] <= pair[1]),
|
||||
/// "buffer is sorted",
|
||||
/// );
|
||||
/// ```
|
||||
///
|
||||
/// ### *Incorrect* usages of this method:
|
||||
///
|
||||
/// You cannot use `.assume_init_mut()` to initialize a value:
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// #![feature(maybe_uninit_ref)]
|
||||
/// use std::mem::MaybeUninit;
|
||||
///
|
||||
/// let mut b = MaybeUninit::<bool>::uninit();
|
||||
/// unsafe {
|
||||
/// *b.assume_init_mut() = true;
|
||||
/// // We have created a (mutable) reference to an uninitialized `bool`!
|
||||
/// // This is undefined behavior. ⚠️
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// For instance, you cannot [`Read`] into an uninitialized buffer:
|
||||
///
|
||||
/// [`Read`]: https://doc.rust-lang.org/std/io/trait.Read.html
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// #![feature(maybe_uninit_ref)]
|
||||
/// use std::{io, mem::MaybeUninit};
|
||||
///
|
||||
/// fn read_chunk (reader: &'_ mut dyn io::Read) -> io::Result<[u8; 64]>
|
||||
/// {
|
||||
/// let mut buffer = MaybeUninit::<[u8; 64]>::uninit();
|
||||
/// reader.read_exact(unsafe { buffer.assume_init_mut() })?;
|
||||
/// // ^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
/// // (mutable) reference to uninitialized memory!
|
||||
/// // This is undefined behavior.
|
||||
/// Ok(unsafe { buffer.assume_init() })
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// Nor can you use direct field access to do field-by-field gradual initialization:
|
||||
///
|
||||
/// ```rust,no_run
|
||||
/// #![feature(maybe_uninit_ref)]
|
||||
/// use std::{mem::MaybeUninit, ptr};
|
||||
///
|
||||
/// struct Foo {
|
||||
/// a: u32,
|
||||
/// b: u8,
|
||||
/// }
|
||||
///
|
||||
/// let foo: Foo = unsafe {
|
||||
/// let mut foo = MaybeUninit::<Foo>::uninit();
|
||||
/// ptr::write(&mut foo.assume_init_mut().a as *mut u32, 1337);
|
||||
/// // ^^^^^^^^^^^^^^^^^^^^^
|
||||
/// // (mutable) reference to uninitialized memory!
|
||||
/// // This is undefined behavior.
|
||||
/// ptr::write(&mut foo.assume_init_mut().b as *mut u8, 42);
|
||||
/// // ^^^^^^^^^^^^^^^^^^^^^
|
||||
/// // (mutable) reference to uninitialized memory!
|
||||
/// // This is undefined behavior.
|
||||
/// foo.assume_init()
|
||||
/// };
|
||||
/// ```
|
||||
// FIXME(#76092): We currently rely on the above being incorrect, i.e., we have references
|
||||
// to uninitialized data (e.g., in `libcore/fmt/float.rs`). We should make
|
||||
// a final decision about the rules before stabilization.
|
||||
#[unstable(feature = "maybe_uninit_ref", issue = "63568")]
|
||||
#[inline(always)]
|
||||
pub unsafe fn assume_init_mut(&mut self) -> &mut T {
|
||||
// SAFETY: the caller must guarantee that `self` is initialized.
|
||||
// This also means that `self` must be a `value` variant.
|
||||
unsafe {
|
||||
intrinsics::assert_inhabited::<T>();
|
||||
&mut *self.value
|
||||
}
|
||||
}
|
||||
|
||||
/// Assuming all the elements are initialized, get a slice to them.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// It is up to the caller to guarantee that the `MaybeUninit<T>` elements
|
||||
/// really are in an initialized state.
|
||||
/// Calling this when the content is not yet fully initialized causes undefined behavior.
|
||||
///
|
||||
/// See [`assume_init_ref`] for more details and examples.
|
||||
///
|
||||
/// [`assume_init_ref`]: MaybeUninit::assume_init_ref
|
||||
#[unstable(feature = "maybe_uninit_slice", issue = "63569")]
|
||||
#[inline(always)]
|
||||
pub unsafe fn slice_assume_init_ref(slice: &[Self]) -> &[T] {
|
||||
// SAFETY: casting slice to a `*const [T]` is safe since the caller guarantees that
|
||||
// `slice` is initialized, and`MaybeUninit` is guaranteed to have the same layout as `T`.
|
||||
// The pointer obtained is valid since it refers to memory owned by `slice` which is a
|
||||
// reference and thus guaranteed to be valid for reads.
|
||||
unsafe { &*(slice as *const [Self] as *const [T]) }
|
||||
}
|
||||
|
||||
/// Assuming all the elements are initialized, get a mutable slice to them.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// It is up to the caller to guarantee that the `MaybeUninit<T>` elements
|
||||
/// really are in an initialized state.
|
||||
/// Calling this when the content is not yet fully initialized causes undefined behavior.
|
||||
///
|
||||
/// See [`assume_init_mut`] for more details and examples.
|
||||
///
|
||||
/// [`assume_init_mut`]: MaybeUninit::assume_init_mut
|
||||
#[unstable(feature = "maybe_uninit_slice", issue = "63569")]
|
||||
#[inline(always)]
|
||||
pub unsafe fn slice_assume_init_mut(slice: &mut [Self]) -> &mut [T] {
|
||||
// SAFETY: similar to safety notes for `slice_get_ref`, but we have a
|
||||
// mutable reference which is also guaranteed to be valid for writes.
|
||||
unsafe { &mut *(slice as *mut [Self] as *mut [T]) }
|
||||
}
|
||||
|
||||
/// Gets a pointer to the first element of the array.
|
||||
#[unstable(feature = "maybe_uninit_slice", issue = "63569")]
|
||||
#[inline(always)]
|
||||
pub fn slice_as_ptr(this: &[MaybeUninit<T>]) -> *const T {
|
||||
this.as_ptr() as *const T
|
||||
}
|
||||
|
||||
/// Gets a mutable pointer to the first element of the array.
|
||||
#[unstable(feature = "maybe_uninit_slice", issue = "63569")]
|
||||
#[inline(always)]
|
||||
pub fn slice_as_mut_ptr(this: &mut [MaybeUninit<T>]) -> *mut T {
|
||||
this.as_mut_ptr() as *mut T
|
||||
}
|
||||
}
|
||||
1040
libgrust/rustc-lib/core/src/mem/mod.rs
Normal file
1040
libgrust/rustc-lib/core/src/mem/mod.rs
Normal file
File diff suppressed because it is too large
Load Diff
473
libgrust/rustc-lib/core/src/num/bignum.rs
Normal file
473
libgrust/rustc-lib/core/src/num/bignum.rs
Normal file
@@ -0,0 +1,473 @@
|
||||
//! Custom arbitrary-precision number (bignum) implementation.
|
||||
//!
|
||||
//! This is designed to avoid the heap allocation at expense of stack memory.
|
||||
//! The most used bignum type, `Big32x40`, is limited by 32 × 40 = 1,280 bits
|
||||
//! and will take at most 160 bytes of stack memory. This is more than enough
|
||||
//! for round-tripping all possible finite `f64` values.
|
||||
//!
|
||||
//! In principle it is possible to have multiple bignum types for different
|
||||
//! inputs, but we don't do so to avoid the code bloat. Each bignum is still
|
||||
//! tracked for the actual usages, so it normally doesn't matter.
|
||||
|
||||
// This module is only for dec2flt and flt2dec, and only public because of coretests.
|
||||
// It is not intended to ever be stabilized.
|
||||
#![doc(hidden)]
|
||||
#![unstable(
|
||||
feature = "core_private_bignum",
|
||||
reason = "internal routines only exposed for testing",
|
||||
issue = "none"
|
||||
)]
|
||||
#![macro_use]
|
||||
|
||||
use crate::intrinsics;
|
||||
|
||||
/// Arithmetic operations required by bignums.
|
||||
pub trait FullOps: Sized {
|
||||
/// Returns `(carry', v')` such that `carry' * 2^W + v' = self + other + carry`,
|
||||
/// where `W` is the number of bits in `Self`.
|
||||
fn full_add(self, other: Self, carry: bool) -> (bool /* carry */, Self);
|
||||
|
||||
/// Returns `(carry', v')` such that `carry' * 2^W + v' = self * other + carry`,
|
||||
/// where `W` is the number of bits in `Self`.
|
||||
fn full_mul(self, other: Self, carry: Self) -> (Self /* carry */, Self);
|
||||
|
||||
/// Returns `(carry', v')` such that `carry' * 2^W + v' = self * other + other2 + carry`,
|
||||
/// where `W` is the number of bits in `Self`.
|
||||
fn full_mul_add(self, other: Self, other2: Self, carry: Self) -> (Self /* carry */, Self);
|
||||
|
||||
/// Returns `(quo, rem)` such that `borrow * 2^W + self = quo * other + rem`
|
||||
/// and `0 <= rem < other`, where `W` is the number of bits in `Self`.
|
||||
fn full_div_rem(self, other: Self, borrow: Self)
|
||||
-> (Self /* quotient */, Self /* remainder */);
|
||||
}
|
||||
|
||||
macro_rules! impl_full_ops {
|
||||
($($ty:ty: add($addfn:path), mul/div($bigty:ident);)*) => (
|
||||
$(
|
||||
impl FullOps for $ty {
|
||||
fn full_add(self, other: $ty, carry: bool) -> (bool, $ty) {
|
||||
// This cannot overflow; the output is between `0` and `2 * 2^nbits - 1`.
|
||||
// FIXME: will LLVM optimize this into ADC or similar?
|
||||
let (v, carry1) = intrinsics::add_with_overflow(self, other);
|
||||
let (v, carry2) = intrinsics::add_with_overflow(v, if carry {1} else {0});
|
||||
(carry1 || carry2, v)
|
||||
}
|
||||
|
||||
fn full_mul(self, other: $ty, carry: $ty) -> ($ty, $ty) {
|
||||
// This cannot overflow;
|
||||
// the output is between `0` and `2^nbits * (2^nbits - 1)`.
|
||||
// FIXME: will LLVM optimize this into ADC or similar?
|
||||
let v = (self as $bigty) * (other as $bigty) + (carry as $bigty);
|
||||
((v >> <$ty>::BITS) as $ty, v as $ty)
|
||||
}
|
||||
|
||||
fn full_mul_add(self, other: $ty, other2: $ty, carry: $ty) -> ($ty, $ty) {
|
||||
// This cannot overflow;
|
||||
// the output is between `0` and `2^nbits * (2^nbits - 1)`.
|
||||
let v = (self as $bigty) * (other as $bigty) + (other2 as $bigty) +
|
||||
(carry as $bigty);
|
||||
((v >> <$ty>::BITS) as $ty, v as $ty)
|
||||
}
|
||||
|
||||
fn full_div_rem(self, other: $ty, borrow: $ty) -> ($ty, $ty) {
|
||||
debug_assert!(borrow < other);
|
||||
// This cannot overflow; the output is between `0` and `other * (2^nbits - 1)`.
|
||||
let lhs = ((borrow as $bigty) << <$ty>::BITS) | (self as $bigty);
|
||||
let rhs = other as $bigty;
|
||||
((lhs / rhs) as $ty, (lhs % rhs) as $ty)
|
||||
}
|
||||
}
|
||||
)*
|
||||
)
|
||||
}
|
||||
|
||||
impl_full_ops! {
|
||||
u8: add(intrinsics::u8_add_with_overflow), mul/div(u16);
|
||||
u16: add(intrinsics::u16_add_with_overflow), mul/div(u32);
|
||||
u32: add(intrinsics::u32_add_with_overflow), mul/div(u64);
|
||||
// See RFC #521 for enabling this.
|
||||
// u64: add(intrinsics::u64_add_with_overflow), mul/div(u128);
|
||||
}
|
||||
|
||||
/// Table of powers of 5 representable in digits. Specifically, the largest {u8, u16, u32} value
|
||||
/// that's a power of five, plus the corresponding exponent. Used in `mul_pow5`.
|
||||
const SMALL_POW5: [(u64, usize); 3] = [(125, 3), (15625, 6), (1_220_703_125, 13)];
|
||||
|
||||
macro_rules! define_bignum {
|
||||
($name:ident: type=$ty:ty, n=$n:expr) => {
|
||||
/// Stack-allocated arbitrary-precision (up to certain limit) integer.
|
||||
///
|
||||
/// This is backed by a fixed-size array of given type ("digit").
|
||||
/// While the array is not very large (normally some hundred bytes),
|
||||
/// copying it recklessly may result in the performance hit.
|
||||
/// Thus this is intentionally not `Copy`.
|
||||
///
|
||||
/// All operations available to bignums panic in the case of overflows.
|
||||
/// The caller is responsible to use large enough bignum types.
|
||||
pub struct $name {
|
||||
/// One plus the offset to the maximum "digit" in use.
|
||||
/// This does not decrease, so be aware of the computation order.
|
||||
/// `base[size..]` should be zero.
|
||||
size: usize,
|
||||
/// Digits. `[a, b, c, ...]` represents `a + b*2^W + c*2^(2W) + ...`
|
||||
/// where `W` is the number of bits in the digit type.
|
||||
base: [$ty; $n],
|
||||
}
|
||||
|
||||
impl $name {
|
||||
/// Makes a bignum from one digit.
|
||||
pub fn from_small(v: $ty) -> $name {
|
||||
let mut base = [0; $n];
|
||||
base[0] = v;
|
||||
$name { size: 1, base: base }
|
||||
}
|
||||
|
||||
/// Makes a bignum from `u64` value.
|
||||
pub fn from_u64(mut v: u64) -> $name {
|
||||
let mut base = [0; $n];
|
||||
let mut sz = 0;
|
||||
while v > 0 {
|
||||
base[sz] = v as $ty;
|
||||
v >>= <$ty>::BITS;
|
||||
sz += 1;
|
||||
}
|
||||
$name { size: sz, base: base }
|
||||
}
|
||||
|
||||
/// Returns the internal digits as a slice `[a, b, c, ...]` such that the numeric
|
||||
/// value is `a + b * 2^W + c * 2^(2W) + ...` where `W` is the number of bits in
|
||||
/// the digit type.
|
||||
pub fn digits(&self) -> &[$ty] {
|
||||
&self.base[..self.size]
|
||||
}
|
||||
|
||||
/// Returns the `i`-th bit where bit 0 is the least significant one.
|
||||
/// In other words, the bit with weight `2^i`.
|
||||
pub fn get_bit(&self, i: usize) -> u8 {
|
||||
let digitbits = <$ty>::BITS as usize;
|
||||
let d = i / digitbits;
|
||||
let b = i % digitbits;
|
||||
((self.base[d] >> b) & 1) as u8
|
||||
}
|
||||
|
||||
/// Returns `true` if the bignum is zero.
|
||||
pub fn is_zero(&self) -> bool {
|
||||
self.digits().iter().all(|&v| v == 0)
|
||||
}
|
||||
|
||||
/// Returns the number of bits necessary to represent this value. Note that zero
|
||||
/// is considered to need 0 bits.
|
||||
pub fn bit_length(&self) -> usize {
|
||||
// Skip over the most significant digits which are zero.
|
||||
let digits = self.digits();
|
||||
let zeros = digits.iter().rev().take_while(|&&x| x == 0).count();
|
||||
let end = digits.len() - zeros;
|
||||
let nonzero = &digits[..end];
|
||||
|
||||
if nonzero.is_empty() {
|
||||
// There are no non-zero digits, i.e., the number is zero.
|
||||
return 0;
|
||||
}
|
||||
// This could be optimized with leading_zeros() and bit shifts, but that's
|
||||
// probably not worth the hassle.
|
||||
let digitbits = <$ty>::BITS as usize;
|
||||
let mut i = nonzero.len() * digitbits - 1;
|
||||
while self.get_bit(i) == 0 {
|
||||
i -= 1;
|
||||
}
|
||||
i + 1
|
||||
}
|
||||
|
||||
/// Adds `other` to itself and returns its own mutable reference.
|
||||
pub fn add<'a>(&'a mut self, other: &$name) -> &'a mut $name {
|
||||
use crate::cmp;
|
||||
use crate::num::bignum::FullOps;
|
||||
|
||||
let mut sz = cmp::max(self.size, other.size);
|
||||
let mut carry = false;
|
||||
for (a, b) in self.base[..sz].iter_mut().zip(&other.base[..sz]) {
|
||||
let (c, v) = (*a).full_add(*b, carry);
|
||||
*a = v;
|
||||
carry = c;
|
||||
}
|
||||
if carry {
|
||||
self.base[sz] = 1;
|
||||
sz += 1;
|
||||
}
|
||||
self.size = sz;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn add_small(&mut self, other: $ty) -> &mut $name {
|
||||
use crate::num::bignum::FullOps;
|
||||
|
||||
let (mut carry, v) = self.base[0].full_add(other, false);
|
||||
self.base[0] = v;
|
||||
let mut i = 1;
|
||||
while carry {
|
||||
let (c, v) = self.base[i].full_add(0, carry);
|
||||
self.base[i] = v;
|
||||
carry = c;
|
||||
i += 1;
|
||||
}
|
||||
if i > self.size {
|
||||
self.size = i;
|
||||
}
|
||||
self
|
||||
}
|
||||
|
||||
/// Subtracts `other` from itself and returns its own mutable reference.
|
||||
pub fn sub<'a>(&'a mut self, other: &$name) -> &'a mut $name {
|
||||
use crate::cmp;
|
||||
use crate::num::bignum::FullOps;
|
||||
|
||||
let sz = cmp::max(self.size, other.size);
|
||||
let mut noborrow = true;
|
||||
for (a, b) in self.base[..sz].iter_mut().zip(&other.base[..sz]) {
|
||||
let (c, v) = (*a).full_add(!*b, noborrow);
|
||||
*a = v;
|
||||
noborrow = c;
|
||||
}
|
||||
assert!(noborrow);
|
||||
self.size = sz;
|
||||
self
|
||||
}
|
||||
|
||||
/// Multiplies itself by a digit-sized `other` and returns its own
|
||||
/// mutable reference.
|
||||
pub fn mul_small(&mut self, other: $ty) -> &mut $name {
|
||||
use crate::num::bignum::FullOps;
|
||||
|
||||
let mut sz = self.size;
|
||||
let mut carry = 0;
|
||||
for a in &mut self.base[..sz] {
|
||||
let (c, v) = (*a).full_mul(other, carry);
|
||||
*a = v;
|
||||
carry = c;
|
||||
}
|
||||
if carry > 0 {
|
||||
self.base[sz] = carry;
|
||||
sz += 1;
|
||||
}
|
||||
self.size = sz;
|
||||
self
|
||||
}
|
||||
|
||||
/// Multiplies itself by `2^bits` and returns its own mutable reference.
|
||||
pub fn mul_pow2(&mut self, bits: usize) -> &mut $name {
|
||||
let digitbits = <$ty>::BITS as usize;
|
||||
let digits = bits / digitbits;
|
||||
let bits = bits % digitbits;
|
||||
|
||||
assert!(digits < $n);
|
||||
debug_assert!(self.base[$n - digits..].iter().all(|&v| v == 0));
|
||||
debug_assert!(bits == 0 || (self.base[$n - digits - 1] >> (digitbits - bits)) == 0);
|
||||
|
||||
// shift by `digits * digitbits` bits
|
||||
for i in (0..self.size).rev() {
|
||||
self.base[i + digits] = self.base[i];
|
||||
}
|
||||
for i in 0..digits {
|
||||
self.base[i] = 0;
|
||||
}
|
||||
|
||||
// shift by `bits` bits
|
||||
let mut sz = self.size + digits;
|
||||
if bits > 0 {
|
||||
let last = sz;
|
||||
let overflow = self.base[last - 1] >> (digitbits - bits);
|
||||
if overflow > 0 {
|
||||
self.base[last] = overflow;
|
||||
sz += 1;
|
||||
}
|
||||
for i in (digits + 1..last).rev() {
|
||||
self.base[i] =
|
||||
(self.base[i] << bits) | (self.base[i - 1] >> (digitbits - bits));
|
||||
}
|
||||
self.base[digits] <<= bits;
|
||||
// self.base[..digits] is zero, no need to shift
|
||||
}
|
||||
|
||||
self.size = sz;
|
||||
self
|
||||
}
|
||||
|
||||
/// Multiplies itself by `5^e` and returns its own mutable reference.
|
||||
pub fn mul_pow5(&mut self, mut e: usize) -> &mut $name {
|
||||
use crate::mem;
|
||||
use crate::num::bignum::SMALL_POW5;
|
||||
|
||||
// There are exactly n trailing zeros on 2^n, and the only relevant digit sizes
|
||||
// are consecutive powers of two, so this is well suited index for the table.
|
||||
let table_index = mem::size_of::<$ty>().trailing_zeros() as usize;
|
||||
let (small_power, small_e) = SMALL_POW5[table_index];
|
||||
let small_power = small_power as $ty;
|
||||
|
||||
// Multiply with the largest single-digit power as long as possible ...
|
||||
while e >= small_e {
|
||||
self.mul_small(small_power);
|
||||
e -= small_e;
|
||||
}
|
||||
|
||||
// ... then finish off the remainder.
|
||||
let mut rest_power = 1;
|
||||
for _ in 0..e {
|
||||
rest_power *= 5;
|
||||
}
|
||||
self.mul_small(rest_power);
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
/// Multiplies itself by a number described by `other[0] + other[1] * 2^W +
|
||||
/// other[2] * 2^(2W) + ...` (where `W` is the number of bits in the digit type)
|
||||
/// and returns its own mutable reference.
|
||||
pub fn mul_digits<'a>(&'a mut self, other: &[$ty]) -> &'a mut $name {
|
||||
// the internal routine. works best when aa.len() <= bb.len().
|
||||
fn mul_inner(ret: &mut [$ty; $n], aa: &[$ty], bb: &[$ty]) -> usize {
|
||||
use crate::num::bignum::FullOps;
|
||||
|
||||
let mut retsz = 0;
|
||||
for (i, &a) in aa.iter().enumerate() {
|
||||
if a == 0 {
|
||||
continue;
|
||||
}
|
||||
let mut sz = bb.len();
|
||||
let mut carry = 0;
|
||||
for (j, &b) in bb.iter().enumerate() {
|
||||
let (c, v) = a.full_mul_add(b, ret[i + j], carry);
|
||||
ret[i + j] = v;
|
||||
carry = c;
|
||||
}
|
||||
if carry > 0 {
|
||||
ret[i + sz] = carry;
|
||||
sz += 1;
|
||||
}
|
||||
if retsz < i + sz {
|
||||
retsz = i + sz;
|
||||
}
|
||||
}
|
||||
retsz
|
||||
}
|
||||
|
||||
let mut ret = [0; $n];
|
||||
let retsz = if self.size < other.len() {
|
||||
mul_inner(&mut ret, &self.digits(), other)
|
||||
} else {
|
||||
mul_inner(&mut ret, other, &self.digits())
|
||||
};
|
||||
self.base = ret;
|
||||
self.size = retsz;
|
||||
self
|
||||
}
|
||||
|
||||
/// Divides itself by a digit-sized `other` and returns its own
|
||||
/// mutable reference *and* the remainder.
|
||||
pub fn div_rem_small(&mut self, other: $ty) -> (&mut $name, $ty) {
|
||||
use crate::num::bignum::FullOps;
|
||||
|
||||
assert!(other > 0);
|
||||
|
||||
let sz = self.size;
|
||||
let mut borrow = 0;
|
||||
for a in self.base[..sz].iter_mut().rev() {
|
||||
let (q, r) = (*a).full_div_rem(other, borrow);
|
||||
*a = q;
|
||||
borrow = r;
|
||||
}
|
||||
(self, borrow)
|
||||
}
|
||||
|
||||
/// Divide self by another bignum, overwriting `q` with the quotient and `r` with the
|
||||
/// remainder.
|
||||
pub fn div_rem(&self, d: &$name, q: &mut $name, r: &mut $name) {
|
||||
// Stupid slow base-2 long division taken from
|
||||
// https://en.wikipedia.org/wiki/Division_algorithm
|
||||
// FIXME use a greater base ($ty) for the long division.
|
||||
assert!(!d.is_zero());
|
||||
let digitbits = <$ty>::BITS as usize;
|
||||
for digit in &mut q.base[..] {
|
||||
*digit = 0;
|
||||
}
|
||||
for digit in &mut r.base[..] {
|
||||
*digit = 0;
|
||||
}
|
||||
r.size = d.size;
|
||||
q.size = 1;
|
||||
let mut q_is_zero = true;
|
||||
let end = self.bit_length();
|
||||
for i in (0..end).rev() {
|
||||
r.mul_pow2(1);
|
||||
r.base[0] |= self.get_bit(i) as $ty;
|
||||
if &*r >= d {
|
||||
r.sub(d);
|
||||
// Set bit `i` of q to 1.
|
||||
let digit_idx = i / digitbits;
|
||||
let bit_idx = i % digitbits;
|
||||
if q_is_zero {
|
||||
q.size = digit_idx + 1;
|
||||
q_is_zero = false;
|
||||
}
|
||||
q.base[digit_idx] |= 1 << bit_idx;
|
||||
}
|
||||
}
|
||||
debug_assert!(q.base[q.size..].iter().all(|&d| d == 0));
|
||||
debug_assert!(r.base[r.size..].iter().all(|&d| d == 0));
|
||||
}
|
||||
}
|
||||
|
||||
impl crate::cmp::PartialEq for $name {
|
||||
fn eq(&self, other: &$name) -> bool {
|
||||
self.base[..] == other.base[..]
|
||||
}
|
||||
}
|
||||
|
||||
impl crate::cmp::Eq for $name {}
|
||||
|
||||
impl crate::cmp::PartialOrd for $name {
|
||||
fn partial_cmp(&self, other: &$name) -> crate::option::Option<crate::cmp::Ordering> {
|
||||
crate::option::Option::Some(self.cmp(other))
|
||||
}
|
||||
}
|
||||
|
||||
impl crate::cmp::Ord for $name {
|
||||
fn cmp(&self, other: &$name) -> crate::cmp::Ordering {
|
||||
use crate::cmp::max;
|
||||
let sz = max(self.size, other.size);
|
||||
let lhs = self.base[..sz].iter().cloned().rev();
|
||||
let rhs = other.base[..sz].iter().cloned().rev();
|
||||
lhs.cmp(rhs)
|
||||
}
|
||||
}
|
||||
|
||||
impl crate::clone::Clone for $name {
|
||||
fn clone(&self) -> Self {
|
||||
Self { size: self.size, base: self.base }
|
||||
}
|
||||
}
|
||||
|
||||
impl crate::fmt::Debug for $name {
|
||||
fn fmt(&self, f: &mut crate::fmt::Formatter<'_>) -> crate::fmt::Result {
|
||||
let sz = if self.size < 1 { 1 } else { self.size };
|
||||
let digitlen = <$ty>::BITS as usize / 4;
|
||||
|
||||
write!(f, "{:#x}", self.base[sz - 1])?;
|
||||
for &v in self.base[..sz - 1].iter().rev() {
|
||||
write!(f, "_{:01$x}", v, digitlen)?;
|
||||
}
|
||||
crate::result::Result::Ok(())
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// The digit type for `Big32x40`.
|
||||
pub type Digit32 = u32;
|
||||
|
||||
define_bignum!(Big32x40: type=Digit32, n=40);
|
||||
|
||||
// this one is used for testing only.
|
||||
#[doc(hidden)]
|
||||
pub mod tests {
|
||||
define_bignum!(Big8x3: type=u8, n=3);
|
||||
}
|
||||
431
libgrust/rustc-lib/core/src/num/dec2flt/algorithm.rs
Normal file
431
libgrust/rustc-lib/core/src/num/dec2flt/algorithm.rs
Normal file
@@ -0,0 +1,431 @@
|
||||
//! The various algorithms from the paper.
|
||||
|
||||
use crate::cmp::min;
|
||||
use crate::cmp::Ordering::{Equal, Greater, Less};
|
||||
use crate::num::dec2flt::num::{self, Big};
|
||||
use crate::num::dec2flt::rawfp::{self, fp_to_float, next_float, prev_float, RawFloat, Unpacked};
|
||||
use crate::num::dec2flt::table;
|
||||
use crate::num::diy_float::Fp;
|
||||
|
||||
/// Number of significand bits in Fp
|
||||
const P: u32 = 64;
|
||||
|
||||
// We simply store the best approximation for *all* exponents, so the variable "h" and the
|
||||
// associated conditions can be omitted. This trades performance for a couple kilobytes of space.
|
||||
|
||||
fn power_of_ten(e: i16) -> Fp {
|
||||
assert!(e >= table::MIN_E);
|
||||
let i = e - table::MIN_E;
|
||||
let sig = table::POWERS.0[i as usize];
|
||||
let exp = table::POWERS.1[i as usize];
|
||||
Fp { f: sig, e: exp }
|
||||
}
|
||||
|
||||
// In most architectures, floating point operations have an explicit bit size, therefore the
|
||||
// precision of the computation is determined on a per-operation basis.
|
||||
#[cfg(any(not(target_arch = "x86"), target_feature = "sse2"))]
|
||||
mod fpu_precision {
|
||||
pub fn set_precision<T>() {}
|
||||
}
|
||||
|
||||
// On x86, the x87 FPU is used for float operations if the SSE/SSE2 extensions are not available.
|
||||
// The x87 FPU operates with 80 bits of precision by default, which means that operations will
|
||||
// round to 80 bits causing double rounding to happen when values are eventually represented as
|
||||
// 32/64 bit float values. To overcome this, the FPU control word can be set so that the
|
||||
// computations are performed in the desired precision.
|
||||
#[cfg(all(target_arch = "x86", not(target_feature = "sse2")))]
|
||||
mod fpu_precision {
|
||||
use crate::mem::size_of;
|
||||
|
||||
/// A structure used to preserve the original value of the FPU control word, so that it can be
|
||||
/// restored when the structure is dropped.
|
||||
///
|
||||
/// The x87 FPU is a 16-bits register whose fields are as follows:
|
||||
///
|
||||
/// | 12-15 | 10-11 | 8-9 | 6-7 | 5 | 4 | 3 | 2 | 1 | 0 |
|
||||
/// |------:|------:|----:|----:|---:|---:|---:|---:|---:|---:|
|
||||
/// | | RC | PC | | PM | UM | OM | ZM | DM | IM |
|
||||
///
|
||||
/// The documentation for all of the fields is available in the IA-32 Architectures Software
|
||||
/// Developer's Manual (Volume 1).
|
||||
///
|
||||
/// The only field which is relevant for the following code is PC, Precision Control. This
|
||||
/// field determines the precision of the operations performed by the FPU. It can be set to:
|
||||
/// - 0b00, single precision i.e., 32-bits
|
||||
/// - 0b10, double precision i.e., 64-bits
|
||||
/// - 0b11, double extended precision i.e., 80-bits (default state)
|
||||
/// The 0b01 value is reserved and should not be used.
|
||||
pub struct FPUControlWord(u16);
|
||||
|
||||
fn set_cw(cw: u16) {
|
||||
// SAFETY: the `fldcw` instruction has been audited to be able to work correctly with
|
||||
// any `u16`
|
||||
unsafe {
|
||||
asm!(
|
||||
"fldcw ({})",
|
||||
in(reg) &cw,
|
||||
// FIXME: We are using ATT syntax to support LLVM 8 and LLVM 9.
|
||||
options(att_syntax, nostack),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets the precision field of the FPU to `T` and returns a `FPUControlWord`.
|
||||
pub fn set_precision<T>() -> FPUControlWord {
|
||||
let mut cw = 0_u16;
|
||||
|
||||
// Compute the value for the Precision Control field that is appropriate for `T`.
|
||||
let cw_precision = match size_of::<T>() {
|
||||
4 => 0x0000, // 32 bits
|
||||
8 => 0x0200, // 64 bits
|
||||
_ => 0x0300, // default, 80 bits
|
||||
};
|
||||
|
||||
// Get the original value of the control word to restore it later, when the
|
||||
// `FPUControlWord` structure is dropped
|
||||
// SAFETY: the `fnstcw` instruction has been audited to be able to work correctly with
|
||||
// any `u16`
|
||||
unsafe {
|
||||
asm!(
|
||||
"fnstcw ({})",
|
||||
in(reg) &mut cw,
|
||||
// FIXME: We are using ATT syntax to support LLVM 8 and LLVM 9.
|
||||
options(att_syntax, nostack),
|
||||
)
|
||||
}
|
||||
|
||||
// Set the control word to the desired precision. This is achieved by masking away the old
|
||||
// precision (bits 8 and 9, 0x300) and replacing it with the precision flag computed above.
|
||||
set_cw((cw & 0xFCFF) | cw_precision);
|
||||
|
||||
FPUControlWord(cw)
|
||||
}
|
||||
|
||||
impl Drop for FPUControlWord {
|
||||
fn drop(&mut self) {
|
||||
set_cw(self.0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The fast path of Bellerophon using machine-sized integers and floats.
|
||||
///
|
||||
/// This is extracted into a separate function so that it can be attempted before constructing
|
||||
/// a bignum.
|
||||
pub fn fast_path<T: RawFloat>(integral: &[u8], fractional: &[u8], e: i64) -> Option<T> {
|
||||
let num_digits = integral.len() + fractional.len();
|
||||
// log_10(f64::MAX_SIG) ~ 15.95. We compare the exact value to MAX_SIG near the end,
|
||||
// this is just a quick, cheap rejection (and also frees the rest of the code from
|
||||
// worrying about underflow).
|
||||
if num_digits > 16 {
|
||||
return None;
|
||||
}
|
||||
if e.abs() >= T::CEIL_LOG5_OF_MAX_SIG as i64 {
|
||||
return None;
|
||||
}
|
||||
let f = num::from_str_unchecked(integral.iter().chain(fractional.iter()));
|
||||
if f > T::MAX_SIG {
|
||||
return None;
|
||||
}
|
||||
|
||||
// The fast path crucially depends on arithmetic being rounded to the correct number of bits
|
||||
// without any intermediate rounding. On x86 (without SSE or SSE2) this requires the precision
|
||||
// of the x87 FPU stack to be changed so that it directly rounds to 64/32 bit.
|
||||
// The `set_precision` function takes care of setting the precision on architectures which
|
||||
// require setting it by changing the global state (like the control word of the x87 FPU).
|
||||
let _cw = fpu_precision::set_precision::<T>();
|
||||
|
||||
// The case e < 0 cannot be folded into the other branch. Negative powers result in
|
||||
// a repeating fractional part in binary, which are rounded, which causes real
|
||||
// (and occasionally quite significant!) errors in the final result.
|
||||
if e >= 0 {
|
||||
Some(T::from_int(f) * T::short_fast_pow10(e as usize))
|
||||
} else {
|
||||
Some(T::from_int(f) / T::short_fast_pow10(e.abs() as usize))
|
||||
}
|
||||
}
|
||||
|
||||
/// Algorithm Bellerophon is trivial code justified by non-trivial numeric analysis.
|
||||
///
|
||||
/// It rounds ``f`` to a float with 64 bit significand and multiplies it by the best approximation
|
||||
/// of `10^e` (in the same floating point format). This is often enough to get the correct result.
|
||||
/// However, when the result is close to halfway between two adjacent (ordinary) floats, the
|
||||
/// compound rounding error from multiplying two approximation means the result may be off by a
|
||||
/// few bits. When this happens, the iterative Algorithm R fixes things up.
|
||||
///
|
||||
/// The hand-wavy "close to halfway" is made precise by the numeric analysis in the paper.
|
||||
/// In the words of Clinger:
|
||||
///
|
||||
/// > Slop, expressed in units of the least significant bit, is an inclusive bound for the error
|
||||
/// > accumulated during the floating point calculation of the approximation to f * 10^e. (Slop is
|
||||
/// > not a bound for the true error, but bounds the difference between the approximation z and
|
||||
/// > the best possible approximation that uses p bits of significand.)
|
||||
pub fn bellerophon<T: RawFloat>(f: &Big, e: i16) -> T {
|
||||
let slop = if f <= &Big::from_u64(T::MAX_SIG) {
|
||||
// The cases abs(e) < log5(2^N) are in fast_path()
|
||||
if e >= 0 { 0 } else { 3 }
|
||||
} else {
|
||||
if e >= 0 { 1 } else { 4 }
|
||||
};
|
||||
let z = rawfp::big_to_fp(f).mul(&power_of_ten(e)).normalize();
|
||||
let exp_p_n = 1 << (P - T::SIG_BITS as u32);
|
||||
let lowbits: i64 = (z.f % exp_p_n) as i64;
|
||||
// Is the slop large enough to make a difference when
|
||||
// rounding to n bits?
|
||||
if (lowbits - exp_p_n as i64 / 2).abs() <= slop {
|
||||
algorithm_r(f, e, fp_to_float(z))
|
||||
} else {
|
||||
fp_to_float(z)
|
||||
}
|
||||
}
|
||||
|
||||
/// An iterative algorithm that improves a floating point approximation of `f * 10^e`.
|
||||
///
|
||||
/// Each iteration gets one unit in the last place closer, which of course takes terribly long to
|
||||
/// converge if `z0` is even mildly off. Luckily, when used as fallback for Bellerophon, the
|
||||
/// starting approximation is off by at most one ULP.
|
||||
fn algorithm_r<T: RawFloat>(f: &Big, e: i16, z0: T) -> T {
|
||||
let mut z = z0;
|
||||
loop {
|
||||
let raw = z.unpack();
|
||||
let (m, k) = (raw.sig, raw.k);
|
||||
let mut x = f.clone();
|
||||
let mut y = Big::from_u64(m);
|
||||
|
||||
// Find positive integers `x`, `y` such that `x / y` is exactly `(f * 10^e) / (m * 2^k)`.
|
||||
// This not only avoids dealing with the signs of `e` and `k`, we also eliminate the
|
||||
// power of two common to `10^e` and `2^k` to make the numbers smaller.
|
||||
make_ratio(&mut x, &mut y, e, k);
|
||||
|
||||
let m_digits = [(m & 0xFF_FF_FF_FF) as u32, (m >> 32) as u32];
|
||||
// This is written a bit awkwardly because our bignums don't support
|
||||
// negative numbers, so we use the absolute value + sign information.
|
||||
// The multiplication with m_digits can't overflow. If `x` or `y` are large enough that
|
||||
// we need to worry about overflow, then they are also large enough that `make_ratio` has
|
||||
// reduced the fraction by a factor of 2^64 or more.
|
||||
let (d2, d_negative) = if x >= y {
|
||||
// Don't need x any more, save a clone().
|
||||
x.sub(&y).mul_pow2(1).mul_digits(&m_digits);
|
||||
(x, false)
|
||||
} else {
|
||||
// Still need y - make a copy.
|
||||
let mut y = y.clone();
|
||||
y.sub(&x).mul_pow2(1).mul_digits(&m_digits);
|
||||
(y, true)
|
||||
};
|
||||
|
||||
if d2 < y {
|
||||
let mut d2_double = d2;
|
||||
d2_double.mul_pow2(1);
|
||||
if m == T::MIN_SIG && d_negative && d2_double > y {
|
||||
z = prev_float(z);
|
||||
} else {
|
||||
return z;
|
||||
}
|
||||
} else if d2 == y {
|
||||
if m % 2 == 0 {
|
||||
if m == T::MIN_SIG && d_negative {
|
||||
z = prev_float(z);
|
||||
} else {
|
||||
return z;
|
||||
}
|
||||
} else if d_negative {
|
||||
z = prev_float(z);
|
||||
} else {
|
||||
z = next_float(z);
|
||||
}
|
||||
} else if d_negative {
|
||||
z = prev_float(z);
|
||||
} else {
|
||||
z = next_float(z);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Given `x = f` and `y = m` where `f` represent input decimal digits as usual and `m` is the
|
||||
/// significand of a floating point approximation, make the ratio `x / y` equal to
|
||||
/// `(f * 10^e) / (m * 2^k)`, possibly reduced by a power of two both have in common.
|
||||
fn make_ratio(x: &mut Big, y: &mut Big, e: i16, k: i16) {
|
||||
let (e_abs, k_abs) = (e.abs() as usize, k.abs() as usize);
|
||||
if e >= 0 {
|
||||
if k >= 0 {
|
||||
// x = f * 10^e, y = m * 2^k, except that we reduce the fraction by some power of two.
|
||||
let common = min(e_abs, k_abs);
|
||||
x.mul_pow5(e_abs).mul_pow2(e_abs - common);
|
||||
y.mul_pow2(k_abs - common);
|
||||
} else {
|
||||
// x = f * 10^e * 2^abs(k), y = m
|
||||
// This can't overflow because it requires positive `e` and negative `k`, which can
|
||||
// only happen for values extremely close to 1, which means that `e` and `k` will be
|
||||
// comparatively tiny.
|
||||
x.mul_pow5(e_abs).mul_pow2(e_abs + k_abs);
|
||||
}
|
||||
} else {
|
||||
if k >= 0 {
|
||||
// x = f, y = m * 10^abs(e) * 2^k
|
||||
// This can't overflow either, see above.
|
||||
y.mul_pow5(e_abs).mul_pow2(k_abs + e_abs);
|
||||
} else {
|
||||
// x = f * 2^abs(k), y = m * 10^abs(e), again reducing by a common power of two.
|
||||
let common = min(e_abs, k_abs);
|
||||
x.mul_pow2(k_abs - common);
|
||||
y.mul_pow5(e_abs).mul_pow2(e_abs - common);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Conceptually, Algorithm M is the simplest way to convert a decimal to a float.
|
||||
///
|
||||
/// We form a ratio that is equal to `f * 10^e`, then throwing in powers of two until it gives
|
||||
/// a valid float significand. The binary exponent `k` is the number of times we multiplied
|
||||
/// numerator or denominator by two, i.e., at all times `f * 10^e` equals `(u / v) * 2^k`.
|
||||
/// When we have found out significand, we only need to round by inspecting the remainder of the
|
||||
/// division, which is done in helper functions further below.
|
||||
///
|
||||
/// This algorithm is super slow, even with the optimization described in `quick_start()`.
|
||||
/// However, it's the simplest of the algorithms to adapt for overflow, underflow, and subnormal
|
||||
/// results. This implementation takes over when Bellerophon and Algorithm R are overwhelmed.
|
||||
/// Detecting underflow and overflow is easy: The ratio still isn't an in-range significand,
|
||||
/// yet the minimum/maximum exponent has been reached. In the case of overflow, we simply return
|
||||
/// infinity.
|
||||
///
|
||||
/// Handling underflow and subnormals is trickier. One big problem is that, with the minimum
|
||||
/// exponent, the ratio might still be too large for a significand. See underflow() for details.
|
||||
pub fn algorithm_m<T: RawFloat>(f: &Big, e: i16) -> T {
|
||||
let mut u;
|
||||
let mut v;
|
||||
let e_abs = e.abs() as usize;
|
||||
let mut k = 0;
|
||||
if e < 0 {
|
||||
u = f.clone();
|
||||
v = Big::from_small(1);
|
||||
v.mul_pow5(e_abs).mul_pow2(e_abs);
|
||||
} else {
|
||||
// FIXME possible optimization: generalize big_to_fp so that we can do the equivalent of
|
||||
// fp_to_float(big_to_fp(u)) here, only without the double rounding.
|
||||
u = f.clone();
|
||||
u.mul_pow5(e_abs).mul_pow2(e_abs);
|
||||
v = Big::from_small(1);
|
||||
}
|
||||
quick_start::<T>(&mut u, &mut v, &mut k);
|
||||
let mut rem = Big::from_small(0);
|
||||
let mut x = Big::from_small(0);
|
||||
let min_sig = Big::from_u64(T::MIN_SIG);
|
||||
let max_sig = Big::from_u64(T::MAX_SIG);
|
||||
loop {
|
||||
u.div_rem(&v, &mut x, &mut rem);
|
||||
if k == T::MIN_EXP_INT {
|
||||
// We have to stop at the minimum exponent, if we wait until `k < T::MIN_EXP_INT`,
|
||||
// then we'd be off by a factor of two. Unfortunately this means we have to special-
|
||||
// case normal numbers with the minimum exponent.
|
||||
// FIXME find a more elegant formulation, but run the `tiny-pow10` test to make sure
|
||||
// that it's actually correct!
|
||||
if x >= min_sig && x <= max_sig {
|
||||
break;
|
||||
}
|
||||
return underflow(x, v, rem);
|
||||
}
|
||||
if k > T::MAX_EXP_INT {
|
||||
return T::INFINITY;
|
||||
}
|
||||
if x < min_sig {
|
||||
u.mul_pow2(1);
|
||||
k -= 1;
|
||||
} else if x > max_sig {
|
||||
v.mul_pow2(1);
|
||||
k += 1;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
let q = num::to_u64(&x);
|
||||
let z = rawfp::encode_normal(Unpacked::new(q, k));
|
||||
round_by_remainder(v, rem, q, z)
|
||||
}
|
||||
|
||||
/// Skips over most Algorithm M iterations by checking the bit length.
|
||||
fn quick_start<T: RawFloat>(u: &mut Big, v: &mut Big, k: &mut i16) {
|
||||
// The bit length is an estimate of the base two logarithm, and log(u / v) = log(u) - log(v).
|
||||
// The estimate is off by at most 1, but always an under-estimate, so the error on log(u)
|
||||
// and log(v) are of the same sign and cancel out (if both are large). Therefore the error
|
||||
// for log(u / v) is at most one as well.
|
||||
// The target ratio is one where u/v is in an in-range significand. Thus our termination
|
||||
// condition is log2(u / v) being the significand bits, plus/minus one.
|
||||
// FIXME Looking at the second bit could improve the estimate and avoid some more divisions.
|
||||
let target_ratio = T::SIG_BITS as i16;
|
||||
let log2_u = u.bit_length() as i16;
|
||||
let log2_v = v.bit_length() as i16;
|
||||
let mut u_shift: i16 = 0;
|
||||
let mut v_shift: i16 = 0;
|
||||
assert!(*k == 0);
|
||||
loop {
|
||||
if *k == T::MIN_EXP_INT {
|
||||
// Underflow or subnormal. Leave it to the main function.
|
||||
break;
|
||||
}
|
||||
if *k == T::MAX_EXP_INT {
|
||||
// Overflow. Leave it to the main function.
|
||||
break;
|
||||
}
|
||||
let log2_ratio = (log2_u + u_shift) - (log2_v + v_shift);
|
||||
if log2_ratio < target_ratio - 1 {
|
||||
u_shift += 1;
|
||||
*k -= 1;
|
||||
} else if log2_ratio > target_ratio + 1 {
|
||||
v_shift += 1;
|
||||
*k += 1;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
u.mul_pow2(u_shift as usize);
|
||||
v.mul_pow2(v_shift as usize);
|
||||
}
|
||||
|
||||
fn underflow<T: RawFloat>(x: Big, v: Big, rem: Big) -> T {
|
||||
if x < Big::from_u64(T::MIN_SIG) {
|
||||
let q = num::to_u64(&x);
|
||||
let z = rawfp::encode_subnormal(q);
|
||||
return round_by_remainder(v, rem, q, z);
|
||||
}
|
||||
// Ratio isn't an in-range significand with the minimum exponent, so we need to round off
|
||||
// excess bits and adjust the exponent accordingly. The real value now looks like this:
|
||||
//
|
||||
// x lsb
|
||||
// /--------------\/
|
||||
// 1010101010101010.10101010101010 * 2^k
|
||||
// \-----/\-------/ \------------/
|
||||
// q trunc. (represented by rem)
|
||||
//
|
||||
// Therefore, when the rounded-off bits are != 0.5 ULP, they decide the rounding
|
||||
// on their own. When they are equal and the remainder is non-zero, the value still
|
||||
// needs to be rounded up. Only when the rounded off bits are 1/2 and the remainder
|
||||
// is zero, we have a half-to-even situation.
|
||||
let bits = x.bit_length();
|
||||
let lsb = bits - T::SIG_BITS as usize;
|
||||
let q = num::get_bits(&x, lsb, bits);
|
||||
let k = T::MIN_EXP_INT + lsb as i16;
|
||||
let z = rawfp::encode_normal(Unpacked::new(q, k));
|
||||
let q_even = q % 2 == 0;
|
||||
match num::compare_with_half_ulp(&x, lsb) {
|
||||
Greater => next_float(z),
|
||||
Less => z,
|
||||
Equal if rem.is_zero() && q_even => z,
|
||||
Equal => next_float(z),
|
||||
}
|
||||
}
|
||||
|
||||
/// Ordinary round-to-even, obfuscated by having to round based on the remainder of a division.
|
||||
fn round_by_remainder<T: RawFloat>(v: Big, r: Big, q: u64, z: T) -> T {
|
||||
let mut v_minus_r = v;
|
||||
v_minus_r.sub(&r);
|
||||
if r < v_minus_r {
|
||||
z
|
||||
} else if r > v_minus_r {
|
||||
next_float(z)
|
||||
} else if q % 2 == 0 {
|
||||
z
|
||||
} else {
|
||||
next_float(z)
|
||||
}
|
||||
}
|
||||
356
libgrust/rustc-lib/core/src/num/dec2flt/mod.rs
Normal file
356
libgrust/rustc-lib/core/src/num/dec2flt/mod.rs
Normal file
@@ -0,0 +1,356 @@
|
||||
//! Converting decimal strings into IEEE 754 binary floating point numbers.
|
||||
//!
|
||||
//! # Problem statement
|
||||
//!
|
||||
//! We are given a decimal string such as `12.34e56`. This string consists of integral (`12`),
|
||||
//! fractional (`45`), and exponent (`56`) parts. All parts are optional and interpreted as zero
|
||||
//! when missing.
|
||||
//!
|
||||
//! We seek the IEEE 754 floating point number that is closest to the exact value of the decimal
|
||||
//! string. It is well-known that many decimal strings do not have terminating representations in
|
||||
//! base two, so we round to 0.5 units in the last place (in other words, as well as possible).
|
||||
//! Ties, decimal values exactly half-way between two consecutive floats, are resolved with the
|
||||
//! half-to-even strategy, also known as banker's rounding.
|
||||
//!
|
||||
//! Needless to say, this is quite hard, both in terms of implementation complexity and in terms
|
||||
//! of CPU cycles taken.
|
||||
//!
|
||||
//! # Implementation
|
||||
//!
|
||||
//! First, we ignore signs. Or rather, we remove it at the very beginning of the conversion
|
||||
//! process and re-apply it at the very end. This is correct in all edge cases since IEEE
|
||||
//! floats are symmetric around zero, negating one simply flips the first bit.
|
||||
//!
|
||||
//! Then we remove the decimal point by adjusting the exponent: Conceptually, `12.34e56` turns
|
||||
//! into `1234e54`, which we describe with a positive integer `f = 1234` and an integer `e = 54`.
|
||||
//! The `(f, e)` representation is used by almost all code past the parsing stage.
|
||||
//!
|
||||
//! We then try a long chain of progressively more general and expensive special cases using
|
||||
//! machine-sized integers and small, fixed-sized floating point numbers (first `f32`/`f64`, then
|
||||
//! a type with 64 bit significand, `Fp`). When all these fail, we bite the bullet and resort to a
|
||||
//! simple but very slow algorithm that involved computing `f * 10^e` fully and doing an iterative
|
||||
//! search for the best approximation.
|
||||
//!
|
||||
//! Primarily, this module and its children implement the algorithms described in:
|
||||
//! "How to Read Floating Point Numbers Accurately" by William D. Clinger,
|
||||
//! available online: <http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.45.4152>
|
||||
//!
|
||||
//! In addition, there are numerous helper functions that are used in the paper but not available
|
||||
//! in Rust (or at least in core). Our version is additionally complicated by the need to handle
|
||||
//! overflow and underflow and the desire to handle subnormal numbers. Bellerophon and
|
||||
//! Algorithm R have trouble with overflow, subnormals, and underflow. We conservatively switch to
|
||||
//! Algorithm M (with the modifications described in section 8 of the paper) well before the
|
||||
//! inputs get into the critical region.
|
||||
//!
|
||||
//! Another aspect that needs attention is the ``RawFloat`` trait by which almost all functions
|
||||
//! are parametrized. One might think that it's enough to parse to `f64` and cast the result to
|
||||
//! `f32`. Unfortunately this is not the world we live in, and this has nothing to do with using
|
||||
//! base two or half-to-even rounding.
|
||||
//!
|
||||
//! Consider for example two types `d2` and `d4` representing a decimal type with two decimal
|
||||
//! digits and four decimal digits each and take "0.01499" as input. Let's use half-up rounding.
|
||||
//! Going directly to two decimal digits gives `0.01`, but if we round to four digits first,
|
||||
//! we get `0.0150`, which is then rounded up to `0.02`. The same principle applies to other
|
||||
//! operations as well, if you want 0.5 ULP accuracy you need to do *everything* in full precision
|
||||
//! and round *exactly once, at the end*, by considering all truncated bits at once.
|
||||
//!
|
||||
//! FIXME: Although some code duplication is necessary, perhaps parts of the code could be shuffled
|
||||
//! around such that less code is duplicated. Large parts of the algorithms are independent of the
|
||||
//! float type to output, or only needs access to a few constants, which could be passed in as
|
||||
//! parameters.
|
||||
//!
|
||||
//! # Other
|
||||
//!
|
||||
//! The conversion should *never* panic. There are assertions and explicit panics in the code,
|
||||
//! but they should never be triggered and only serve as internal sanity checks. Any panics should
|
||||
//! be considered a bug.
|
||||
//!
|
||||
//! There are unit tests but they are woefully inadequate at ensuring correctness, they only cover
|
||||
//! a small percentage of possible errors. Far more extensive tests are located in the directory
|
||||
//! `src/etc/test-float-parse` as a Python script.
|
||||
//!
|
||||
//! A note on integer overflow: Many parts of this file perform arithmetic with the decimal
|
||||
//! exponent `e`. Primarily, we shift the decimal point around: Before the first decimal digit,
|
||||
//! after the last decimal digit, and so on. This could overflow if done carelessly. We rely on
|
||||
//! the parsing submodule to only hand out sufficiently small exponents, where "sufficient" means
|
||||
//! "such that the exponent +/- the number of decimal digits fits into a 64 bit integer".
|
||||
//! Larger exponents are accepted, but we don't do arithmetic with them, they are immediately
|
||||
//! turned into {positive,negative} {zero,infinity}.
|
||||
|
||||
#![doc(hidden)]
|
||||
#![unstable(
|
||||
feature = "dec2flt",
|
||||
reason = "internal routines only exposed for testing",
|
||||
issue = "none"
|
||||
)]
|
||||
|
||||
use crate::fmt;
|
||||
use crate::str::FromStr;
|
||||
|
||||
use self::num::digits_to_big;
|
||||
use self::parse::{parse_decimal, Decimal, ParseResult, Sign};
|
||||
use self::rawfp::RawFloat;
|
||||
|
||||
mod algorithm;
|
||||
mod num;
|
||||
mod table;
|
||||
// These two have their own tests.
|
||||
pub mod parse;
|
||||
pub mod rawfp;
|
||||
|
||||
macro_rules! from_str_float_impl {
|
||||
($t:ty) => {
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl FromStr for $t {
|
||||
type Err = ParseFloatError;
|
||||
|
||||
/// Converts a string in base 10 to a float.
|
||||
/// Accepts an optional decimal exponent.
|
||||
///
|
||||
/// This function accepts strings such as
|
||||
///
|
||||
/// * '3.14'
|
||||
/// * '-3.14'
|
||||
/// * '2.5E10', or equivalently, '2.5e10'
|
||||
/// * '2.5E-10'
|
||||
/// * '5.'
|
||||
/// * '.5', or, equivalently, '0.5'
|
||||
/// * 'inf', '-inf', 'NaN'
|
||||
///
|
||||
/// Leading and trailing whitespace represent an error.
|
||||
///
|
||||
/// # Grammar
|
||||
///
|
||||
/// All strings that adhere to the following [EBNF] grammar
|
||||
/// will result in an [`Ok`] being returned:
|
||||
///
|
||||
/// ```txt
|
||||
/// Float ::= Sign? ( 'inf' | 'NaN' | Number )
|
||||
/// Number ::= ( Digit+ |
|
||||
/// Digit+ '.' Digit* |
|
||||
/// Digit* '.' Digit+ ) Exp?
|
||||
/// Exp ::= [eE] Sign? Digit+
|
||||
/// Sign ::= [+-]
|
||||
/// Digit ::= [0-9]
|
||||
/// ```
|
||||
///
|
||||
/// [EBNF]: https://www.w3.org/TR/REC-xml/#sec-notation
|
||||
///
|
||||
/// # Known bugs
|
||||
///
|
||||
/// In some situations, some strings that should create a valid float
|
||||
/// instead return an error. See [issue #31407] for details.
|
||||
///
|
||||
/// [issue #31407]: https://github.com/rust-lang/rust/issues/31407
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * src - A string
|
||||
///
|
||||
/// # Return value
|
||||
///
|
||||
/// `Err(ParseFloatError)` if the string did not represent a valid
|
||||
/// number. Otherwise, `Ok(n)` where `n` is the floating-point
|
||||
/// number represented by `src`.
|
||||
#[inline]
|
||||
fn from_str(src: &str) -> Result<Self, ParseFloatError> {
|
||||
dec2flt(src)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
from_str_float_impl!(f32);
|
||||
from_str_float_impl!(f64);
|
||||
|
||||
/// An error which can be returned when parsing a float.
|
||||
///
|
||||
/// This error is used as the error type for the [`FromStr`] implementation
|
||||
/// for [`f32`] and [`f64`].
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// use std::str::FromStr;
|
||||
///
|
||||
/// if let Err(e) = f64::from_str("a.12") {
|
||||
/// println!("Failed conversion to f64: {}", e);
|
||||
/// }
|
||||
/// ```
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub struct ParseFloatError {
|
||||
kind: FloatErrorKind,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
enum FloatErrorKind {
|
||||
Empty,
|
||||
Invalid,
|
||||
}
|
||||
|
||||
impl ParseFloatError {
|
||||
#[unstable(
|
||||
feature = "int_error_internals",
|
||||
reason = "available through Error trait and this method should \
|
||||
not be exposed publicly",
|
||||
issue = "none"
|
||||
)]
|
||||
#[doc(hidden)]
|
||||
pub fn __description(&self) -> &str {
|
||||
match self.kind {
|
||||
FloatErrorKind::Empty => "cannot parse float from empty string",
|
||||
FloatErrorKind::Invalid => "invalid float literal",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl fmt::Display for ParseFloatError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
self.__description().fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
fn pfe_empty() -> ParseFloatError {
|
||||
ParseFloatError { kind: FloatErrorKind::Empty }
|
||||
}
|
||||
|
||||
fn pfe_invalid() -> ParseFloatError {
|
||||
ParseFloatError { kind: FloatErrorKind::Invalid }
|
||||
}
|
||||
|
||||
/// Splits a decimal string into sign and the rest, without inspecting or validating the rest.
|
||||
fn extract_sign(s: &str) -> (Sign, &str) {
|
||||
match s.as_bytes()[0] {
|
||||
b'+' => (Sign::Positive, &s[1..]),
|
||||
b'-' => (Sign::Negative, &s[1..]),
|
||||
// If the string is invalid, we never use the sign, so we don't need to validate here.
|
||||
_ => (Sign::Positive, s),
|
||||
}
|
||||
}
|
||||
|
||||
/// Converts a decimal string into a floating point number.
|
||||
fn dec2flt<T: RawFloat>(s: &str) -> Result<T, ParseFloatError> {
|
||||
if s.is_empty() {
|
||||
return Err(pfe_empty());
|
||||
}
|
||||
let (sign, s) = extract_sign(s);
|
||||
let flt = match parse_decimal(s) {
|
||||
ParseResult::Valid(decimal) => convert(decimal)?,
|
||||
ParseResult::ShortcutToInf => T::INFINITY,
|
||||
ParseResult::ShortcutToZero => T::ZERO,
|
||||
ParseResult::Invalid => match s {
|
||||
"inf" => T::INFINITY,
|
||||
"NaN" => T::NAN,
|
||||
_ => {
|
||||
return Err(pfe_invalid());
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
match sign {
|
||||
Sign::Positive => Ok(flt),
|
||||
Sign::Negative => Ok(-flt),
|
||||
}
|
||||
}
|
||||
|
||||
/// The main workhorse for the decimal-to-float conversion: Orchestrate all the preprocessing
|
||||
/// and figure out which algorithm should do the actual conversion.
|
||||
fn convert<T: RawFloat>(mut decimal: Decimal<'_>) -> Result<T, ParseFloatError> {
|
||||
simplify(&mut decimal);
|
||||
if let Some(x) = trivial_cases(&decimal) {
|
||||
return Ok(x);
|
||||
}
|
||||
// Remove/shift out the decimal point.
|
||||
let e = decimal.exp - decimal.fractional.len() as i64;
|
||||
if let Some(x) = algorithm::fast_path(decimal.integral, decimal.fractional, e) {
|
||||
return Ok(x);
|
||||
}
|
||||
// Big32x40 is limited to 1280 bits, which translates to about 385 decimal digits.
|
||||
// If we exceed this, we'll crash, so we error out before getting too close (within 10^10).
|
||||
let upper_bound = bound_intermediate_digits(&decimal, e);
|
||||
if upper_bound > 375 {
|
||||
return Err(pfe_invalid());
|
||||
}
|
||||
let f = digits_to_big(decimal.integral, decimal.fractional);
|
||||
|
||||
// Now the exponent certainly fits in 16 bit, which is used throughout the main algorithms.
|
||||
let e = e as i16;
|
||||
// FIXME These bounds are rather conservative. A more careful analysis of the failure modes
|
||||
// of Bellerophon could allow using it in more cases for a massive speed up.
|
||||
let exponent_in_range = table::MIN_E <= e && e <= table::MAX_E;
|
||||
let value_in_range = upper_bound <= T::MAX_NORMAL_DIGITS as u64;
|
||||
if exponent_in_range && value_in_range {
|
||||
Ok(algorithm::bellerophon(&f, e))
|
||||
} else {
|
||||
Ok(algorithm::algorithm_m(&f, e))
|
||||
}
|
||||
}
|
||||
|
||||
// As written, this optimizes badly (see #27130, though it refers to an old version of the code).
|
||||
// `inline(always)` is a workaround for that. There are only two call sites overall and it doesn't
|
||||
// make code size worse.
|
||||
|
||||
/// Strip zeros where possible, even when this requires changing the exponent
|
||||
#[inline(always)]
|
||||
fn simplify(decimal: &mut Decimal<'_>) {
|
||||
let is_zero = &|&&d: &&u8| -> bool { d == b'0' };
|
||||
// Trimming these zeros does not change anything but may enable the fast path (< 15 digits).
|
||||
let leading_zeros = decimal.integral.iter().take_while(is_zero).count();
|
||||
decimal.integral = &decimal.integral[leading_zeros..];
|
||||
let trailing_zeros = decimal.fractional.iter().rev().take_while(is_zero).count();
|
||||
let end = decimal.fractional.len() - trailing_zeros;
|
||||
decimal.fractional = &decimal.fractional[..end];
|
||||
// Simplify numbers of the form 0.0...x and x...0.0, adjusting the exponent accordingly.
|
||||
// This may not always be a win (possibly pushes some numbers out of the fast path), but it
|
||||
// simplifies other parts significantly (notably, approximating the magnitude of the value).
|
||||
if decimal.integral.is_empty() {
|
||||
let leading_zeros = decimal.fractional.iter().take_while(is_zero).count();
|
||||
decimal.fractional = &decimal.fractional[leading_zeros..];
|
||||
decimal.exp -= leading_zeros as i64;
|
||||
} else if decimal.fractional.is_empty() {
|
||||
let trailing_zeros = decimal.integral.iter().rev().take_while(is_zero).count();
|
||||
let end = decimal.integral.len() - trailing_zeros;
|
||||
decimal.integral = &decimal.integral[..end];
|
||||
decimal.exp += trailing_zeros as i64;
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a quick-an-dirty upper bound on the size (log10) of the largest value that Algorithm R
|
||||
/// and Algorithm M will compute while working on the given decimal.
|
||||
fn bound_intermediate_digits(decimal: &Decimal<'_>, e: i64) -> u64 {
|
||||
// We don't need to worry too much about overflow here thanks to trivial_cases() and the
|
||||
// parser, which filter out the most extreme inputs for us.
|
||||
let f_len: u64 = decimal.integral.len() as u64 + decimal.fractional.len() as u64;
|
||||
if e >= 0 {
|
||||
// In the case e >= 0, both algorithms compute about `f * 10^e`. Algorithm R proceeds to
|
||||
// do some complicated calculations with this but we can ignore that for the upper bound
|
||||
// because it also reduces the fraction beforehand, so we have plenty of buffer there.
|
||||
f_len + (e as u64)
|
||||
} else {
|
||||
// If e < 0, Algorithm R does roughly the same thing, but Algorithm M differs:
|
||||
// It tries to find a positive number k such that `f << k / 10^e` is an in-range
|
||||
// significand. This will result in about `2^53 * f * 10^e` < `10^17 * f * 10^e`.
|
||||
// One input that triggers this is 0.33...33 (375 x 3).
|
||||
f_len + (e.abs() as u64) + 17
|
||||
}
|
||||
}
|
||||
|
||||
/// Detects obvious overflows and underflows without even looking at the decimal digits.
|
||||
fn trivial_cases<T: RawFloat>(decimal: &Decimal<'_>) -> Option<T> {
|
||||
// There were zeros but they were stripped by simplify()
|
||||
if decimal.integral.is_empty() && decimal.fractional.is_empty() {
|
||||
return Some(T::ZERO);
|
||||
}
|
||||
// This is a crude approximation of ceil(log10(the real value)). We don't need to worry too
|
||||
// much about overflow here because the input length is tiny (at least compared to 2^64) and
|
||||
// the parser already handles exponents whose absolute value is greater than 10^18
|
||||
// (which is still 10^19 short of 2^64).
|
||||
let max_place = decimal.exp + decimal.integral.len() as i64;
|
||||
if max_place > T::INF_CUTOFF {
|
||||
return Some(T::INFINITY);
|
||||
} else if max_place < T::ZERO_CUTOFF {
|
||||
return Some(T::ZERO);
|
||||
}
|
||||
None
|
||||
}
|
||||
81
libgrust/rustc-lib/core/src/num/dec2flt/num.rs
Normal file
81
libgrust/rustc-lib/core/src/num/dec2flt/num.rs
Normal file
@@ -0,0 +1,81 @@
|
||||
//! Utility functions for bignums that don't make too much sense to turn into methods.
|
||||
|
||||
// FIXME This module's name is a bit unfortunate, since other modules also import `core::num`.
|
||||
|
||||
use crate::cmp::Ordering::{self, Equal, Greater, Less};
|
||||
|
||||
pub use crate::num::bignum::Big32x40 as Big;
|
||||
|
||||
/// Test whether truncating all bits less significant than `ones_place` introduces
|
||||
/// a relative error less, equal, or greater than 0.5 ULP.
|
||||
pub fn compare_with_half_ulp(f: &Big, ones_place: usize) -> Ordering {
|
||||
if ones_place == 0 {
|
||||
return Less;
|
||||
}
|
||||
let half_bit = ones_place - 1;
|
||||
if f.get_bit(half_bit) == 0 {
|
||||
// < 0.5 ULP
|
||||
return Less;
|
||||
}
|
||||
// If all remaining bits are zero, it's = 0.5 ULP, otherwise > 0.5
|
||||
// If there are no more bits (half_bit == 0), the below also correctly returns Equal.
|
||||
for i in 0..half_bit {
|
||||
if f.get_bit(i) == 1 {
|
||||
return Greater;
|
||||
}
|
||||
}
|
||||
Equal
|
||||
}
|
||||
|
||||
/// Converts an ASCII string containing only decimal digits to a `u64`.
|
||||
///
|
||||
/// Does not perform checks for overflow or invalid characters, so if the caller is not careful,
|
||||
/// the result is bogus and can panic (though it won't be `unsafe`). Additionally, empty strings
|
||||
/// are treated as zero. This function exists because
|
||||
///
|
||||
/// 1. using `FromStr` on `&[u8]` requires `from_utf8_unchecked`, which is bad, and
|
||||
/// 2. piecing together the results of `integral.parse()` and `fractional.parse()` is
|
||||
/// more complicated than this entire function.
|
||||
pub fn from_str_unchecked<'a, T>(bytes: T) -> u64
|
||||
where
|
||||
T: IntoIterator<Item = &'a u8>,
|
||||
{
|
||||
let mut result = 0;
|
||||
for &c in bytes {
|
||||
result = result * 10 + (c - b'0') as u64;
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
/// Converts a string of ASCII digits into a bignum.
|
||||
///
|
||||
/// Like `from_str_unchecked`, this function relies on the parser to weed out non-digits.
|
||||
pub fn digits_to_big(integral: &[u8], fractional: &[u8]) -> Big {
|
||||
let mut f = Big::from_small(0);
|
||||
for &c in integral.iter().chain(fractional) {
|
||||
let n = (c - b'0') as u32;
|
||||
f.mul_small(10);
|
||||
f.add_small(n);
|
||||
}
|
||||
f
|
||||
}
|
||||
|
||||
/// Unwraps a bignum into a 64 bit integer. Panics if the number is too large.
|
||||
pub fn to_u64(x: &Big) -> u64 {
|
||||
assert!(x.bit_length() < 64);
|
||||
let d = x.digits();
|
||||
if d.len() < 2 { d[0] as u64 } else { (d[1] as u64) << 32 | d[0] as u64 }
|
||||
}
|
||||
|
||||
/// Extracts a range of bits.
|
||||
|
||||
/// Index 0 is the least significant bit and the range is half-open as usual.
|
||||
/// Panics if asked to extract more bits than fit into the return type.
|
||||
pub fn get_bits(x: &Big, start: usize, end: usize) -> u64 {
|
||||
assert!(end - start <= 64);
|
||||
let mut result: u64 = 0;
|
||||
for i in (start..end).rev() {
|
||||
result = result << 1 | x.get_bit(i) as u64;
|
||||
}
|
||||
result
|
||||
}
|
||||
124
libgrust/rustc-lib/core/src/num/dec2flt/parse.rs
Normal file
124
libgrust/rustc-lib/core/src/num/dec2flt/parse.rs
Normal file
@@ -0,0 +1,124 @@
|
||||
//! Validating and decomposing a decimal string of the form:
|
||||
//!
|
||||
//! `(digits | digits? '.'? digits?) (('e' | 'E') ('+' | '-')? digits)?`
|
||||
//!
|
||||
//! In other words, standard floating-point syntax, with two exceptions: No sign, and no
|
||||
//! handling of "inf" and "NaN". These are handled by the driver function (super::dec2flt).
|
||||
//!
|
||||
//! Although recognizing valid inputs is relatively easy, this module also has to reject the
|
||||
//! countless invalid variations, never panic, and perform numerous checks that the other
|
||||
//! modules rely on to not panic (or overflow) in turn.
|
||||
//! To make matters worse, all that happens in a single pass over the input.
|
||||
//! So, be careful when modifying anything, and double-check with the other modules.
|
||||
use self::ParseResult::{Invalid, ShortcutToInf, ShortcutToZero, Valid};
|
||||
use super::num;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Sign {
|
||||
Positive,
|
||||
Negative,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
/// The interesting parts of a decimal string.
|
||||
pub struct Decimal<'a> {
|
||||
pub integral: &'a [u8],
|
||||
pub fractional: &'a [u8],
|
||||
/// The decimal exponent, guaranteed to have fewer than 18 decimal digits.
|
||||
pub exp: i64,
|
||||
}
|
||||
|
||||
impl<'a> Decimal<'a> {
|
||||
pub fn new(integral: &'a [u8], fractional: &'a [u8], exp: i64) -> Decimal<'a> {
|
||||
Decimal { integral, fractional, exp }
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
pub enum ParseResult<'a> {
|
||||
Valid(Decimal<'a>),
|
||||
ShortcutToInf,
|
||||
ShortcutToZero,
|
||||
Invalid,
|
||||
}
|
||||
|
||||
/// Checks if the input string is a valid floating point number and if so, locate the integral
|
||||
/// part, the fractional part, and the exponent in it. Does not handle signs.
|
||||
pub fn parse_decimal(s: &str) -> ParseResult<'_> {
|
||||
if s.is_empty() {
|
||||
return Invalid;
|
||||
}
|
||||
|
||||
let s = s.as_bytes();
|
||||
let (integral, s) = eat_digits(s);
|
||||
|
||||
match s.first() {
|
||||
None => Valid(Decimal::new(integral, b"", 0)),
|
||||
Some(&b'e' | &b'E') => {
|
||||
if integral.is_empty() {
|
||||
return Invalid; // No digits before 'e'
|
||||
}
|
||||
|
||||
parse_exp(integral, b"", &s[1..])
|
||||
}
|
||||
Some(&b'.') => {
|
||||
let (fractional, s) = eat_digits(&s[1..]);
|
||||
if integral.is_empty() && fractional.is_empty() {
|
||||
// We require at least a single digit before or after the point.
|
||||
return Invalid;
|
||||
}
|
||||
|
||||
match s.first() {
|
||||
None => Valid(Decimal::new(integral, fractional, 0)),
|
||||
Some(&b'e' | &b'E') => parse_exp(integral, fractional, &s[1..]),
|
||||
_ => Invalid, // Trailing junk after fractional part
|
||||
}
|
||||
}
|
||||
_ => Invalid, // Trailing junk after first digit string
|
||||
}
|
||||
}
|
||||
|
||||
/// Carves off decimal digits up to the first non-digit character.
|
||||
fn eat_digits(s: &[u8]) -> (&[u8], &[u8]) {
|
||||
let mut i = 0;
|
||||
while i < s.len() && b'0' <= s[i] && s[i] <= b'9' {
|
||||
i += 1;
|
||||
}
|
||||
(&s[..i], &s[i..])
|
||||
}
|
||||
|
||||
/// Exponent extraction and error checking.
|
||||
fn parse_exp<'a>(integral: &'a [u8], fractional: &'a [u8], rest: &'a [u8]) -> ParseResult<'a> {
|
||||
let (sign, rest) = match rest.first() {
|
||||
Some(&b'-') => (Sign::Negative, &rest[1..]),
|
||||
Some(&b'+') => (Sign::Positive, &rest[1..]),
|
||||
_ => (Sign::Positive, rest),
|
||||
};
|
||||
let (mut number, trailing) = eat_digits(rest);
|
||||
if !trailing.is_empty() {
|
||||
return Invalid; // Trailing junk after exponent
|
||||
}
|
||||
if number.is_empty() {
|
||||
return Invalid; // Empty exponent
|
||||
}
|
||||
// At this point, we certainly have a valid string of digits. It may be too long to put into
|
||||
// an `i64`, but if it's that huge, the input is certainly zero or infinity. Since each zero
|
||||
// in the decimal digits only adjusts the exponent by +/- 1, at exp = 10^18 the input would
|
||||
// have to be 17 exabyte (!) of zeros to get even remotely close to being finite.
|
||||
// This is not exactly a use case we need to cater to.
|
||||
while number.first() == Some(&b'0') {
|
||||
number = &number[1..];
|
||||
}
|
||||
if number.len() >= 18 {
|
||||
return match sign {
|
||||
Sign::Positive => ShortcutToInf,
|
||||
Sign::Negative => ShortcutToZero,
|
||||
};
|
||||
}
|
||||
let abs_exp = num::from_str_unchecked(number);
|
||||
let e = match sign {
|
||||
Sign::Positive => abs_exp as i64,
|
||||
Sign::Negative => -(abs_exp as i64),
|
||||
};
|
||||
Valid(Decimal::new(integral, fractional, e))
|
||||
}
|
||||
363
libgrust/rustc-lib/core/src/num/dec2flt/rawfp.rs
Normal file
363
libgrust/rustc-lib/core/src/num/dec2flt/rawfp.rs
Normal file
@@ -0,0 +1,363 @@
|
||||
//! Bit fiddling on positive IEEE 754 floats. Negative numbers aren't and needn't be handled.
|
||||
//! Normal floating point numbers have a canonical representation as (frac, exp) such that the
|
||||
//! value is 2<sup>exp</sup> * (1 + sum(frac[N-i] / 2<sup>i</sup>)) where N is the number of bits.
|
||||
//! Subnormals are slightly different and weird, but the same principle applies.
|
||||
//!
|
||||
//! Here, however, we represent them as (sig, k) with f positive, such that the value is f *
|
||||
//! 2<sup>e</sup>. Besides making the "hidden bit" explicit, this changes the exponent by the
|
||||
//! so-called mantissa shift.
|
||||
//!
|
||||
//! Put another way, normally floats are written as (1) but here they are written as (2):
|
||||
//!
|
||||
//! 1. `1.101100...11 * 2^m`
|
||||
//! 2. `1101100...11 * 2^n`
|
||||
//!
|
||||
//! We call (1) the **fractional representation** and (2) the **integral representation**.
|
||||
//!
|
||||
//! Many functions in this module only handle normal numbers. The dec2flt routines conservatively
|
||||
//! take the universally-correct slow path (Algorithm M) for very small and very large numbers.
|
||||
//! That algorithm needs only next_float() which does handle subnormals and zeros.
|
||||
use crate::cmp::Ordering::{Equal, Greater, Less};
|
||||
use crate::convert::{TryFrom, TryInto};
|
||||
use crate::fmt::{Debug, LowerExp};
|
||||
use crate::num::dec2flt::num::{self, Big};
|
||||
use crate::num::dec2flt::table;
|
||||
use crate::num::diy_float::Fp;
|
||||
use crate::num::FpCategory;
|
||||
use crate::num::FpCategory::{Infinite, Nan, Normal, Subnormal, Zero};
|
||||
use crate::ops::{Add, Div, Mul, Neg};
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub struct Unpacked {
|
||||
pub sig: u64,
|
||||
pub k: i16,
|
||||
}
|
||||
|
||||
impl Unpacked {
|
||||
pub fn new(sig: u64, k: i16) -> Self {
|
||||
Unpacked { sig, k }
|
||||
}
|
||||
}
|
||||
|
||||
/// A helper trait to avoid duplicating basically all the conversion code for `f32` and `f64`.
|
||||
///
|
||||
/// See the parent module's doc comment for why this is necessary.
|
||||
///
|
||||
/// Should **never ever** be implemented for other types or be used outside the dec2flt module.
|
||||
pub trait RawFloat:
|
||||
Copy + Debug + LowerExp + Mul<Output = Self> + Div<Output = Self> + Neg<Output = Self>
|
||||
{
|
||||
const INFINITY: Self;
|
||||
const NAN: Self;
|
||||
const ZERO: Self;
|
||||
|
||||
/// Type used by `to_bits` and `from_bits`.
|
||||
type Bits: Add<Output = Self::Bits> + From<u8> + TryFrom<u64>;
|
||||
|
||||
/// Performs a raw transmutation to an integer.
|
||||
fn to_bits(self) -> Self::Bits;
|
||||
|
||||
/// Performs a raw transmutation from an integer.
|
||||
fn from_bits(v: Self::Bits) -> Self;
|
||||
|
||||
/// Returns the category that this number falls into.
|
||||
fn classify(self) -> FpCategory;
|
||||
|
||||
/// Returns the mantissa, exponent and sign as integers.
|
||||
fn integer_decode(self) -> (u64, i16, i8);
|
||||
|
||||
/// Decodes the float.
|
||||
fn unpack(self) -> Unpacked;
|
||||
|
||||
/// Casts from a small integer that can be represented exactly. Panic if the integer can't be
|
||||
/// represented, the other code in this module makes sure to never let that happen.
|
||||
fn from_int(x: u64) -> Self;
|
||||
|
||||
/// Gets the value 10<sup>e</sup> from a pre-computed table.
|
||||
/// Panics for `e >= CEIL_LOG5_OF_MAX_SIG`.
|
||||
fn short_fast_pow10(e: usize) -> Self;
|
||||
|
||||
/// What the name says. It's easier to hard code than juggling intrinsics and
|
||||
/// hoping LLVM constant folds it.
|
||||
const CEIL_LOG5_OF_MAX_SIG: i16;
|
||||
|
||||
// A conservative bound on the decimal digits of inputs that can't produce overflow or zero or
|
||||
/// subnormals. Probably the decimal exponent of the maximum normal value, hence the name.
|
||||
const MAX_NORMAL_DIGITS: usize;
|
||||
|
||||
/// When the most significant decimal digit has a place value greater than this, the number
|
||||
/// is certainly rounded to infinity.
|
||||
const INF_CUTOFF: i64;
|
||||
|
||||
/// When the most significant decimal digit has a place value less than this, the number
|
||||
/// is certainly rounded to zero.
|
||||
const ZERO_CUTOFF: i64;
|
||||
|
||||
/// The number of bits in the exponent.
|
||||
const EXP_BITS: u8;
|
||||
|
||||
/// The number of bits in the significand, *including* the hidden bit.
|
||||
const SIG_BITS: u8;
|
||||
|
||||
/// The number of bits in the significand, *excluding* the hidden bit.
|
||||
const EXPLICIT_SIG_BITS: u8;
|
||||
|
||||
/// The maximum legal exponent in fractional representation.
|
||||
const MAX_EXP: i16;
|
||||
|
||||
/// The minimum legal exponent in fractional representation, excluding subnormals.
|
||||
const MIN_EXP: i16;
|
||||
|
||||
/// `MAX_EXP` for integral representation, i.e., with the shift applied.
|
||||
const MAX_EXP_INT: i16;
|
||||
|
||||
/// `MAX_EXP` encoded (i.e., with offset bias)
|
||||
const MAX_ENCODED_EXP: i16;
|
||||
|
||||
/// `MIN_EXP` for integral representation, i.e., with the shift applied.
|
||||
const MIN_EXP_INT: i16;
|
||||
|
||||
/// The maximum normalized significand in integral representation.
|
||||
const MAX_SIG: u64;
|
||||
|
||||
/// The minimal normalized significand in integral representation.
|
||||
const MIN_SIG: u64;
|
||||
}
|
||||
|
||||
// Mostly a workaround for #34344.
|
||||
macro_rules! other_constants {
|
||||
($type: ident) => {
|
||||
const EXPLICIT_SIG_BITS: u8 = Self::SIG_BITS - 1;
|
||||
const MAX_EXP: i16 = (1 << (Self::EXP_BITS - 1)) - 1;
|
||||
const MIN_EXP: i16 = -<Self as RawFloat>::MAX_EXP + 1;
|
||||
const MAX_EXP_INT: i16 = <Self as RawFloat>::MAX_EXP - (Self::SIG_BITS as i16 - 1);
|
||||
const MAX_ENCODED_EXP: i16 = (1 << Self::EXP_BITS) - 1;
|
||||
const MIN_EXP_INT: i16 = <Self as RawFloat>::MIN_EXP - (Self::SIG_BITS as i16 - 1);
|
||||
const MAX_SIG: u64 = (1 << Self::SIG_BITS) - 1;
|
||||
const MIN_SIG: u64 = 1 << (Self::SIG_BITS - 1);
|
||||
|
||||
const INFINITY: Self = $type::INFINITY;
|
||||
const NAN: Self = $type::NAN;
|
||||
const ZERO: Self = 0.0;
|
||||
};
|
||||
}
|
||||
|
||||
impl RawFloat for f32 {
|
||||
type Bits = u32;
|
||||
|
||||
const SIG_BITS: u8 = 24;
|
||||
const EXP_BITS: u8 = 8;
|
||||
const CEIL_LOG5_OF_MAX_SIG: i16 = 11;
|
||||
const MAX_NORMAL_DIGITS: usize = 35;
|
||||
const INF_CUTOFF: i64 = 40;
|
||||
const ZERO_CUTOFF: i64 = -48;
|
||||
other_constants!(f32);
|
||||
|
||||
/// Returns the mantissa, exponent and sign as integers.
|
||||
fn integer_decode(self) -> (u64, i16, i8) {
|
||||
let bits = self.to_bits();
|
||||
let sign: i8 = if bits >> 31 == 0 { 1 } else { -1 };
|
||||
let mut exponent: i16 = ((bits >> 23) & 0xff) as i16;
|
||||
let mantissa =
|
||||
if exponent == 0 { (bits & 0x7fffff) << 1 } else { (bits & 0x7fffff) | 0x800000 };
|
||||
// Exponent bias + mantissa shift
|
||||
exponent -= 127 + 23;
|
||||
(mantissa as u64, exponent, sign)
|
||||
}
|
||||
|
||||
fn unpack(self) -> Unpacked {
|
||||
let (sig, exp, _sig) = self.integer_decode();
|
||||
Unpacked::new(sig, exp)
|
||||
}
|
||||
|
||||
fn from_int(x: u64) -> f32 {
|
||||
// rkruppe is uncertain whether `as` rounds correctly on all platforms.
|
||||
debug_assert!(x as f32 == fp_to_float(Fp { f: x, e: 0 }));
|
||||
x as f32
|
||||
}
|
||||
|
||||
fn short_fast_pow10(e: usize) -> Self {
|
||||
table::F32_SHORT_POWERS[e]
|
||||
}
|
||||
|
||||
fn classify(self) -> FpCategory {
|
||||
self.classify()
|
||||
}
|
||||
fn to_bits(self) -> Self::Bits {
|
||||
self.to_bits()
|
||||
}
|
||||
fn from_bits(v: Self::Bits) -> Self {
|
||||
Self::from_bits(v)
|
||||
}
|
||||
}
|
||||
|
||||
impl RawFloat for f64 {
|
||||
type Bits = u64;
|
||||
|
||||
const SIG_BITS: u8 = 53;
|
||||
const EXP_BITS: u8 = 11;
|
||||
const CEIL_LOG5_OF_MAX_SIG: i16 = 23;
|
||||
const MAX_NORMAL_DIGITS: usize = 305;
|
||||
const INF_CUTOFF: i64 = 310;
|
||||
const ZERO_CUTOFF: i64 = -326;
|
||||
other_constants!(f64);
|
||||
|
||||
/// Returns the mantissa, exponent and sign as integers.
|
||||
fn integer_decode(self) -> (u64, i16, i8) {
|
||||
let bits = self.to_bits();
|
||||
let sign: i8 = if bits >> 63 == 0 { 1 } else { -1 };
|
||||
let mut exponent: i16 = ((bits >> 52) & 0x7ff) as i16;
|
||||
let mantissa = if exponent == 0 {
|
||||
(bits & 0xfffffffffffff) << 1
|
||||
} else {
|
||||
(bits & 0xfffffffffffff) | 0x10000000000000
|
||||
};
|
||||
// Exponent bias + mantissa shift
|
||||
exponent -= 1023 + 52;
|
||||
(mantissa, exponent, sign)
|
||||
}
|
||||
|
||||
fn unpack(self) -> Unpacked {
|
||||
let (sig, exp, _sig) = self.integer_decode();
|
||||
Unpacked::new(sig, exp)
|
||||
}
|
||||
|
||||
fn from_int(x: u64) -> f64 {
|
||||
// rkruppe is uncertain whether `as` rounds correctly on all platforms.
|
||||
debug_assert!(x as f64 == fp_to_float(Fp { f: x, e: 0 }));
|
||||
x as f64
|
||||
}
|
||||
|
||||
fn short_fast_pow10(e: usize) -> Self {
|
||||
table::F64_SHORT_POWERS[e]
|
||||
}
|
||||
|
||||
fn classify(self) -> FpCategory {
|
||||
self.classify()
|
||||
}
|
||||
fn to_bits(self) -> Self::Bits {
|
||||
self.to_bits()
|
||||
}
|
||||
fn from_bits(v: Self::Bits) -> Self {
|
||||
Self::from_bits(v)
|
||||
}
|
||||
}
|
||||
|
||||
/// Converts an `Fp` to the closest machine float type.
|
||||
/// Does not handle subnormal results.
|
||||
pub fn fp_to_float<T: RawFloat>(x: Fp) -> T {
|
||||
let x = x.normalize();
|
||||
// x.f is 64 bit, so x.e has a mantissa shift of 63
|
||||
let e = x.e + 63;
|
||||
if e > T::MAX_EXP {
|
||||
panic!("fp_to_float: exponent {} too large", e)
|
||||
} else if e > T::MIN_EXP {
|
||||
encode_normal(round_normal::<T>(x))
|
||||
} else {
|
||||
panic!("fp_to_float: exponent {} too small", e)
|
||||
}
|
||||
}
|
||||
|
||||
/// Round the 64-bit significand to T::SIG_BITS bits with half-to-even.
|
||||
/// Does not handle exponent overflow.
|
||||
pub fn round_normal<T: RawFloat>(x: Fp) -> Unpacked {
|
||||
let excess = 64 - T::SIG_BITS as i16;
|
||||
let half: u64 = 1 << (excess - 1);
|
||||
let (q, rem) = (x.f >> excess, x.f & ((1 << excess) - 1));
|
||||
assert_eq!(q << excess | rem, x.f);
|
||||
// Adjust mantissa shift
|
||||
let k = x.e + excess;
|
||||
if rem < half {
|
||||
Unpacked::new(q, k)
|
||||
} else if rem == half && (q % 2) == 0 {
|
||||
Unpacked::new(q, k)
|
||||
} else if q == T::MAX_SIG {
|
||||
Unpacked::new(T::MIN_SIG, k + 1)
|
||||
} else {
|
||||
Unpacked::new(q + 1, k)
|
||||
}
|
||||
}
|
||||
|
||||
/// Inverse of `RawFloat::unpack()` for normalized numbers.
|
||||
/// Panics if the significand or exponent are not valid for normalized numbers.
|
||||
pub fn encode_normal<T: RawFloat>(x: Unpacked) -> T {
|
||||
debug_assert!(
|
||||
T::MIN_SIG <= x.sig && x.sig <= T::MAX_SIG,
|
||||
"encode_normal: significand not normalized"
|
||||
);
|
||||
// Remove the hidden bit
|
||||
let sig_enc = x.sig & !(1 << T::EXPLICIT_SIG_BITS);
|
||||
// Adjust the exponent for exponent bias and mantissa shift
|
||||
let k_enc = x.k + T::MAX_EXP + T::EXPLICIT_SIG_BITS as i16;
|
||||
debug_assert!(k_enc != 0 && k_enc < T::MAX_ENCODED_EXP, "encode_normal: exponent out of range");
|
||||
// Leave sign bit at 0 ("+"), our numbers are all positive
|
||||
let bits = (k_enc as u64) << T::EXPLICIT_SIG_BITS | sig_enc;
|
||||
T::from_bits(bits.try_into().unwrap_or_else(|_| unreachable!()))
|
||||
}
|
||||
|
||||
/// Construct a subnormal. A mantissa of 0 is allowed and constructs zero.
|
||||
pub fn encode_subnormal<T: RawFloat>(significand: u64) -> T {
|
||||
assert!(significand < T::MIN_SIG, "encode_subnormal: not actually subnormal");
|
||||
// Encoded exponent is 0, the sign bit is 0, so we just have to reinterpret the bits.
|
||||
T::from_bits(significand.try_into().unwrap_or_else(|_| unreachable!()))
|
||||
}
|
||||
|
||||
/// Approximate a bignum with an Fp. Rounds within 0.5 ULP with half-to-even.
|
||||
pub fn big_to_fp(f: &Big) -> Fp {
|
||||
let end = f.bit_length();
|
||||
assert!(end != 0, "big_to_fp: unexpectedly, input is zero");
|
||||
let start = end.saturating_sub(64);
|
||||
let leading = num::get_bits(f, start, end);
|
||||
// We cut off all bits prior to the index `start`, i.e., we effectively right-shift by
|
||||
// an amount of `start`, so this is also the exponent we need.
|
||||
let e = start as i16;
|
||||
let rounded_down = Fp { f: leading, e }.normalize();
|
||||
// Round (half-to-even) depending on the truncated bits.
|
||||
match num::compare_with_half_ulp(f, start) {
|
||||
Less => rounded_down,
|
||||
Equal if leading % 2 == 0 => rounded_down,
|
||||
Equal | Greater => match leading.checked_add(1) {
|
||||
Some(f) => Fp { f, e }.normalize(),
|
||||
None => Fp { f: 1 << 63, e: e + 1 },
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
/// Finds the largest floating point number strictly smaller than the argument.
|
||||
/// Does not handle subnormals, zero, or exponent underflow.
|
||||
pub fn prev_float<T: RawFloat>(x: T) -> T {
|
||||
match x.classify() {
|
||||
Infinite => panic!("prev_float: argument is infinite"),
|
||||
Nan => panic!("prev_float: argument is NaN"),
|
||||
Subnormal => panic!("prev_float: argument is subnormal"),
|
||||
Zero => panic!("prev_float: argument is zero"),
|
||||
Normal => {
|
||||
let Unpacked { sig, k } = x.unpack();
|
||||
if sig == T::MIN_SIG {
|
||||
encode_normal(Unpacked::new(T::MAX_SIG, k - 1))
|
||||
} else {
|
||||
encode_normal(Unpacked::new(sig - 1, k))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Find the smallest floating point number strictly larger than the argument.
|
||||
// This operation is saturating, i.e., next_float(inf) == inf.
|
||||
// Unlike most code in this module, this function does handle zero, subnormals, and infinities.
|
||||
// However, like all other code here, it does not deal with NaN and negative numbers.
|
||||
pub fn next_float<T: RawFloat>(x: T) -> T {
|
||||
match x.classify() {
|
||||
Nan => panic!("next_float: argument is NaN"),
|
||||
Infinite => T::INFINITY,
|
||||
// This seems too good to be true, but it works.
|
||||
// 0.0 is encoded as the all-zero word. Subnormals are 0x000m...m where m is the mantissa.
|
||||
// In particular, the smallest subnormal is 0x0...01 and the largest is 0x000F...F.
|
||||
// The smallest normal number is 0x0010...0, so this corner case works as well.
|
||||
// If the increment overflows the mantissa, the carry bit increments the exponent as we
|
||||
// want, and the mantissa bits become zero. Because of the hidden bit convention, this
|
||||
// too is exactly what we want!
|
||||
// Finally, f64::MAX + 1 = 7eff...f + 1 = 7ff0...0 = f64::INFINITY.
|
||||
Zero | Subnormal | Normal => T::from_bits(x.to_bits() + T::Bits::from(1u8)),
|
||||
}
|
||||
}
|
||||
1277
libgrust/rustc-lib/core/src/num/dec2flt/table.rs
Normal file
1277
libgrust/rustc-lib/core/src/num/dec2flt/table.rs
Normal file
File diff suppressed because it is too large
Load Diff
81
libgrust/rustc-lib/core/src/num/diy_float.rs
Normal file
81
libgrust/rustc-lib/core/src/num/diy_float.rs
Normal file
@@ -0,0 +1,81 @@
|
||||
//! Extended precision "soft float", for internal use only.
|
||||
|
||||
// This module is only for dec2flt and flt2dec, and only public because of coretests.
|
||||
// It is not intended to ever be stabilized.
|
||||
#![doc(hidden)]
|
||||
#![unstable(
|
||||
feature = "core_private_diy_float",
|
||||
reason = "internal routines only exposed for testing",
|
||||
issue = "none"
|
||||
)]
|
||||
|
||||
/// A custom 64-bit floating point type, representing `f * 2^e`.
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
#[doc(hidden)]
|
||||
pub struct Fp {
|
||||
/// The integer mantissa.
|
||||
pub f: u64,
|
||||
/// The exponent in base 2.
|
||||
pub e: i16,
|
||||
}
|
||||
|
||||
impl Fp {
|
||||
/// Returns a correctly rounded product of itself and `other`.
|
||||
pub fn mul(&self, other: &Fp) -> Fp {
|
||||
const MASK: u64 = 0xffffffff;
|
||||
let a = self.f >> 32;
|
||||
let b = self.f & MASK;
|
||||
let c = other.f >> 32;
|
||||
let d = other.f & MASK;
|
||||
let ac = a * c;
|
||||
let bc = b * c;
|
||||
let ad = a * d;
|
||||
let bd = b * d;
|
||||
let tmp = (bd >> 32) + (ad & MASK) + (bc & MASK) + (1 << 31) /* round */;
|
||||
let f = ac + (ad >> 32) + (bc >> 32) + (tmp >> 32);
|
||||
let e = self.e + other.e + 64;
|
||||
Fp { f, e }
|
||||
}
|
||||
|
||||
/// Normalizes itself so that the resulting mantissa is at least `2^63`.
|
||||
pub fn normalize(&self) -> Fp {
|
||||
let mut f = self.f;
|
||||
let mut e = self.e;
|
||||
if f >> (64 - 32) == 0 {
|
||||
f <<= 32;
|
||||
e -= 32;
|
||||
}
|
||||
if f >> (64 - 16) == 0 {
|
||||
f <<= 16;
|
||||
e -= 16;
|
||||
}
|
||||
if f >> (64 - 8) == 0 {
|
||||
f <<= 8;
|
||||
e -= 8;
|
||||
}
|
||||
if f >> (64 - 4) == 0 {
|
||||
f <<= 4;
|
||||
e -= 4;
|
||||
}
|
||||
if f >> (64 - 2) == 0 {
|
||||
f <<= 2;
|
||||
e -= 2;
|
||||
}
|
||||
if f >> (64 - 1) == 0 {
|
||||
f <<= 1;
|
||||
e -= 1;
|
||||
}
|
||||
debug_assert!(f >= (1 >> 63));
|
||||
Fp { f, e }
|
||||
}
|
||||
|
||||
/// Normalizes itself to have the shared exponent.
|
||||
/// It can only decrease the exponent (and thus increase the mantissa).
|
||||
pub fn normalize_to(&self, e: i16) -> Fp {
|
||||
let edelta = self.e - e;
|
||||
assert!(edelta >= 0);
|
||||
let edelta = edelta as usize;
|
||||
assert_eq!(self.f << edelta >> edelta, self.f);
|
||||
Fp { f: self.f << edelta, e }
|
||||
}
|
||||
}
|
||||
154
libgrust/rustc-lib/core/src/num/error.rs
Normal file
154
libgrust/rustc-lib/core/src/num/error.rs
Normal file
@@ -0,0 +1,154 @@
|
||||
//! Error types for conversion to integral types.
|
||||
|
||||
use crate::convert::Infallible;
|
||||
use crate::fmt;
|
||||
|
||||
/// The error type returned when a checked integral type conversion fails.
|
||||
#[stable(feature = "try_from", since = "1.34.0")]
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
pub struct TryFromIntError(pub(crate) ());
|
||||
|
||||
impl TryFromIntError {
|
||||
#[unstable(
|
||||
feature = "int_error_internals",
|
||||
reason = "available through Error trait and this method should \
|
||||
not be exposed publicly",
|
||||
issue = "none"
|
||||
)]
|
||||
#[doc(hidden)]
|
||||
pub fn __description(&self) -> &str {
|
||||
"out of range integral type conversion attempted"
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "try_from", since = "1.34.0")]
|
||||
impl fmt::Display for TryFromIntError {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
self.__description().fmt(fmt)
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "try_from", since = "1.34.0")]
|
||||
impl From<Infallible> for TryFromIntError {
|
||||
fn from(x: Infallible) -> TryFromIntError {
|
||||
match x {}
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable(feature = "never_type", issue = "35121")]
|
||||
impl From<!> for TryFromIntError {
|
||||
fn from(never: !) -> TryFromIntError {
|
||||
// Match rather than coerce to make sure that code like
|
||||
// `From<Infallible> for TryFromIntError` above will keep working
|
||||
// when `Infallible` becomes an alias to `!`.
|
||||
match never {}
|
||||
}
|
||||
}
|
||||
|
||||
/// An error which can be returned when parsing an integer.
|
||||
///
|
||||
/// This error is used as the error type for the `from_str_radix()` functions
|
||||
/// on the primitive integer types, such as [`i8::from_str_radix`].
|
||||
///
|
||||
/// # Potential causes
|
||||
///
|
||||
/// Among other causes, `ParseIntError` can be thrown because of leading or trailing whitespace
|
||||
/// in the string e.g., when it is obtained from the standard input.
|
||||
/// Using the [`str.trim()`] method ensures that no whitespace remains before parsing.
|
||||
///
|
||||
/// [`str.trim()`]: ../../std/primitive.str.html#method.trim
|
||||
/// [`i8::from_str_radix`]: ../../std/primitive.i8.html#method.from_str_radix
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// if let Err(e) = i32::from_str_radix("a12", 10) {
|
||||
/// println!("Failed conversion to i32: {}", e);
|
||||
/// }
|
||||
/// ```
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub struct ParseIntError {
|
||||
pub(super) kind: IntErrorKind,
|
||||
}
|
||||
|
||||
/// Enum to store the various types of errors that can cause parsing an integer to fail.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(int_error_matching)]
|
||||
///
|
||||
/// # fn main() {
|
||||
/// if let Err(e) = i32::from_str_radix("a12", 10) {
|
||||
/// println!("Failed conversion to i32: {:?}", e.kind());
|
||||
/// }
|
||||
/// # }
|
||||
/// ```
|
||||
#[unstable(
|
||||
feature = "int_error_matching",
|
||||
reason = "it can be useful to match errors when making error messages \
|
||||
for integer parsing",
|
||||
issue = "22639"
|
||||
)]
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
#[non_exhaustive]
|
||||
pub enum IntErrorKind {
|
||||
/// Value being parsed is empty.
|
||||
///
|
||||
/// Among other causes, this variant will be constructed when parsing an empty string.
|
||||
Empty,
|
||||
/// Contains an invalid digit in its context.
|
||||
///
|
||||
/// Among other causes, this variant will be constructed when parsing a string that
|
||||
/// contains a non-ASCII char.
|
||||
///
|
||||
/// This variant is also constructed when a `+` or `-` is misplaced within a string
|
||||
/// either on its own or in the middle of a number.
|
||||
InvalidDigit,
|
||||
/// Integer is too large to store in target integer type.
|
||||
PosOverflow,
|
||||
/// Integer is too small to store in target integer type.
|
||||
NegOverflow,
|
||||
/// Value was Zero
|
||||
///
|
||||
/// This variant will be emitted when the parsing string has a value of zero, which
|
||||
/// would be illegal for non-zero types.
|
||||
Zero,
|
||||
}
|
||||
|
||||
impl ParseIntError {
|
||||
/// Outputs the detailed cause of parsing an integer failing.
|
||||
#[unstable(
|
||||
feature = "int_error_matching",
|
||||
reason = "it can be useful to match errors when making error messages \
|
||||
for integer parsing",
|
||||
issue = "22639"
|
||||
)]
|
||||
pub fn kind(&self) -> &IntErrorKind {
|
||||
&self.kind
|
||||
}
|
||||
#[unstable(
|
||||
feature = "int_error_internals",
|
||||
reason = "available through Error trait and this method should \
|
||||
not be exposed publicly",
|
||||
issue = "none"
|
||||
)]
|
||||
#[doc(hidden)]
|
||||
pub fn __description(&self) -> &str {
|
||||
match self.kind {
|
||||
IntErrorKind::Empty => "cannot parse integer from empty string",
|
||||
IntErrorKind::InvalidDigit => "invalid digit found in string",
|
||||
IntErrorKind::PosOverflow => "number too large to fit in target type",
|
||||
IntErrorKind::NegOverflow => "number too small to fit in target type",
|
||||
IntErrorKind::Zero => "number would be zero for non-zero type",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl fmt::Display for ParseIntError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
self.__description().fmt(f)
|
||||
}
|
||||
}
|
||||
938
libgrust/rustc-lib/core/src/num/f32.rs
Normal file
938
libgrust/rustc-lib/core/src/num/f32.rs
Normal file
@@ -0,0 +1,938 @@
|
||||
//! This module provides constants which are specific to the implementation
|
||||
//! of the `f32` floating point data type.
|
||||
//!
|
||||
//! *[See also the `f32` primitive type](../../std/primitive.f32.html).*
|
||||
//!
|
||||
//! Mathematically significant numbers are provided in the `consts` sub-module.
|
||||
//!
|
||||
//! Although using these constants won’t cause compilation warnings,
|
||||
//! new code should use the associated constants directly on the primitive type.
|
||||
|
||||
#![stable(feature = "rust1", since = "1.0.0")]
|
||||
|
||||
use crate::convert::FloatToInt;
|
||||
#[cfg(not(test))]
|
||||
use crate::intrinsics;
|
||||
use crate::mem;
|
||||
use crate::num::FpCategory;
|
||||
|
||||
/// The radix or base of the internal representation of `f32`.
|
||||
/// Use [`f32::RADIX`](../../std/primitive.f32.html#associatedconstant.RADIX) instead.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// // deprecated way
|
||||
/// let r = std::f32::RADIX;
|
||||
///
|
||||
/// // intended way
|
||||
/// let r = f32::RADIX;
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub const RADIX: u32 = f32::RADIX;
|
||||
|
||||
/// Number of significant digits in base 2.
|
||||
/// Use [`f32::MANTISSA_DIGITS`](../../std/primitive.f32.html#associatedconstant.MANTISSA_DIGITS) instead.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// // deprecated way
|
||||
/// let d = std::f32::MANTISSA_DIGITS;
|
||||
///
|
||||
/// // intended way
|
||||
/// let d = f32::MANTISSA_DIGITS;
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub const MANTISSA_DIGITS: u32 = f32::MANTISSA_DIGITS;
|
||||
|
||||
/// Approximate number of significant digits in base 10.
|
||||
/// Use [`f32::DIGITS`](../../std/primitive.f32.html#associatedconstant.DIGITS) instead.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// // deprecated way
|
||||
/// let d = std::f32::DIGITS;
|
||||
///
|
||||
/// // intended way
|
||||
/// let d = f32::DIGITS;
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub const DIGITS: u32 = f32::DIGITS;
|
||||
|
||||
/// [Machine epsilon] value for `f32`.
|
||||
/// Use [`f32::EPSILON`](../../std/primitive.f32.html#associatedconstant.EPSILON) instead.
|
||||
///
|
||||
/// This is the difference between `1.0` and the next larger representable number.
|
||||
///
|
||||
/// [Machine epsilon]: https://en.wikipedia.org/wiki/Machine_epsilon
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// // deprecated way
|
||||
/// let e = std::f32::EPSILON;
|
||||
///
|
||||
/// // intended way
|
||||
/// let e = f32::EPSILON;
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub const EPSILON: f32 = f32::EPSILON;
|
||||
|
||||
/// Smallest finite `f32` value.
|
||||
/// Use [`f32::MIN`](../../std/primitive.f32.html#associatedconstant.MIN) instead.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// // deprecated way
|
||||
/// let min = std::f32::MIN;
|
||||
///
|
||||
/// // intended way
|
||||
/// let min = f32::MIN;
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub const MIN: f32 = f32::MIN;
|
||||
|
||||
/// Smallest positive normal `f32` value.
|
||||
/// Use [`f32::MIN_POSITIVE`](../../std/primitive.f32.html#associatedconstant.MIN_POSITIVE) instead.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// // deprecated way
|
||||
/// let min = std::f32::MIN_POSITIVE;
|
||||
///
|
||||
/// // intended way
|
||||
/// let min = f32::MIN_POSITIVE;
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub const MIN_POSITIVE: f32 = f32::MIN_POSITIVE;
|
||||
|
||||
/// Largest finite `f32` value.
|
||||
/// Use [`f32::MAX`](../../std/primitive.f32.html#associatedconstant.MAX) instead.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// // deprecated way
|
||||
/// let max = std::f32::MAX;
|
||||
///
|
||||
/// // intended way
|
||||
/// let max = f32::MAX;
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub const MAX: f32 = f32::MAX;
|
||||
|
||||
/// One greater than the minimum possible normal power of 2 exponent.
|
||||
/// Use [`f32::MIN_EXP`](../../std/primitive.f32.html#associatedconstant.MIN_EXP) instead.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// // deprecated way
|
||||
/// let min = std::f32::MIN_EXP;
|
||||
///
|
||||
/// // intended way
|
||||
/// let min = f32::MIN_EXP;
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub const MIN_EXP: i32 = f32::MIN_EXP;
|
||||
|
||||
/// Maximum possible power of 2 exponent.
|
||||
/// Use [`f32::MAX_EXP`](../../std/primitive.f32.html#associatedconstant.MAX_EXP) instead.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// // deprecated way
|
||||
/// let max = std::f32::MAX_EXP;
|
||||
///
|
||||
/// // intended way
|
||||
/// let max = f32::MAX_EXP;
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub const MAX_EXP: i32 = f32::MAX_EXP;
|
||||
|
||||
/// Minimum possible normal power of 10 exponent.
|
||||
/// Use [`f32::MIN_10_EXP`](../../std/primitive.f32.html#associatedconstant.MIN_10_EXP) instead.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// // deprecated way
|
||||
/// let min = std::f32::MIN_10_EXP;
|
||||
///
|
||||
/// // intended way
|
||||
/// let min = f32::MIN_10_EXP;
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub const MIN_10_EXP: i32 = f32::MIN_10_EXP;
|
||||
|
||||
/// Maximum possible power of 10 exponent.
|
||||
/// Use [`f32::MAX_10_EXP`](../../std/primitive.f32.html#associatedconstant.MAX_10_EXP) instead.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// // deprecated way
|
||||
/// let max = std::f32::MAX_10_EXP;
|
||||
///
|
||||
/// // intended way
|
||||
/// let max = f32::MAX_10_EXP;
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub const MAX_10_EXP: i32 = f32::MAX_10_EXP;
|
||||
|
||||
/// Not a Number (NaN).
|
||||
/// Use [`f32::NAN`](../../std/primitive.f32.html#associatedconstant.NAN) instead.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// // deprecated way
|
||||
/// let nan = std::f32::NAN;
|
||||
///
|
||||
/// // intended way
|
||||
/// let nan = f32::NAN;
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub const NAN: f32 = f32::NAN;
|
||||
|
||||
/// Infinity (∞).
|
||||
/// Use [`f32::INFINITY`](../../std/primitive.f32.html#associatedconstant.INFINITY) instead.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// // deprecated way
|
||||
/// let inf = std::f32::INFINITY;
|
||||
///
|
||||
/// // intended way
|
||||
/// let inf = f32::INFINITY;
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub const INFINITY: f32 = f32::INFINITY;
|
||||
|
||||
/// Negative infinity (−∞).
|
||||
/// Use [`f32::NEG_INFINITY`](../../std/primitive.f32.html#associatedconstant.NEG_INFINITY) instead.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// // deprecated way
|
||||
/// let ninf = std::f32::NEG_INFINITY;
|
||||
///
|
||||
/// // intended way
|
||||
/// let ninf = f32::NEG_INFINITY;
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub const NEG_INFINITY: f32 = f32::NEG_INFINITY;
|
||||
|
||||
/// Basic mathematical constants.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub mod consts {
|
||||
// FIXME: replace with mathematical constants from cmath.
|
||||
|
||||
/// Archimedes' constant (π)
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub const PI: f32 = 3.14159265358979323846264338327950288_f32;
|
||||
|
||||
/// The full circle constant (τ)
|
||||
///
|
||||
/// Equal to 2π.
|
||||
#[stable(feature = "tau_constant", since = "1.47.0")]
|
||||
pub const TAU: f32 = 6.28318530717958647692528676655900577_f32;
|
||||
|
||||
/// π/2
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub const FRAC_PI_2: f32 = 1.57079632679489661923132169163975144_f32;
|
||||
|
||||
/// π/3
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub const FRAC_PI_3: f32 = 1.04719755119659774615421446109316763_f32;
|
||||
|
||||
/// π/4
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub const FRAC_PI_4: f32 = 0.785398163397448309615660845819875721_f32;
|
||||
|
||||
/// π/6
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub const FRAC_PI_6: f32 = 0.52359877559829887307710723054658381_f32;
|
||||
|
||||
/// π/8
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub const FRAC_PI_8: f32 = 0.39269908169872415480783042290993786_f32;
|
||||
|
||||
/// 1/π
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub const FRAC_1_PI: f32 = 0.318309886183790671537767526745028724_f32;
|
||||
|
||||
/// 2/π
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub const FRAC_2_PI: f32 = 0.636619772367581343075535053490057448_f32;
|
||||
|
||||
/// 2/sqrt(π)
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub const FRAC_2_SQRT_PI: f32 = 1.12837916709551257389615890312154517_f32;
|
||||
|
||||
/// sqrt(2)
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub const SQRT_2: f32 = 1.41421356237309504880168872420969808_f32;
|
||||
|
||||
/// 1/sqrt(2)
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub const FRAC_1_SQRT_2: f32 = 0.707106781186547524400844362104849039_f32;
|
||||
|
||||
/// Euler's number (e)
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub const E: f32 = 2.71828182845904523536028747135266250_f32;
|
||||
|
||||
/// log<sub>2</sub>(e)
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub const LOG2_E: f32 = 1.44269504088896340735992468100189214_f32;
|
||||
|
||||
/// log<sub>2</sub>(10)
|
||||
#[stable(feature = "extra_log_consts", since = "1.43.0")]
|
||||
pub const LOG2_10: f32 = 3.32192809488736234787031942948939018_f32;
|
||||
|
||||
/// log<sub>10</sub>(e)
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub const LOG10_E: f32 = 0.434294481903251827651128918916605082_f32;
|
||||
|
||||
/// log<sub>10</sub>(2)
|
||||
#[stable(feature = "extra_log_consts", since = "1.43.0")]
|
||||
pub const LOG10_2: f32 = 0.301029995663981195213738894724493027_f32;
|
||||
|
||||
/// ln(2)
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub const LN_2: f32 = 0.693147180559945309417232121458176568_f32;
|
||||
|
||||
/// ln(10)
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub const LN_10: f32 = 2.30258509299404568401799145468436421_f32;
|
||||
}
|
||||
|
||||
#[lang = "f32"]
|
||||
#[cfg(not(test))]
|
||||
impl f32 {
|
||||
/// The radix or base of the internal representation of `f32`.
|
||||
#[stable(feature = "assoc_int_consts", since = "1.43.0")]
|
||||
pub const RADIX: u32 = 2;
|
||||
|
||||
/// Number of significant digits in base 2.
|
||||
#[stable(feature = "assoc_int_consts", since = "1.43.0")]
|
||||
pub const MANTISSA_DIGITS: u32 = 24;
|
||||
|
||||
/// Approximate number of significant digits in base 10.
|
||||
#[stable(feature = "assoc_int_consts", since = "1.43.0")]
|
||||
pub const DIGITS: u32 = 6;
|
||||
|
||||
/// [Machine epsilon] value for `f32`.
|
||||
///
|
||||
/// This is the difference between `1.0` and the next larger representable number.
|
||||
///
|
||||
/// [Machine epsilon]: https://en.wikipedia.org/wiki/Machine_epsilon
|
||||
#[stable(feature = "assoc_int_consts", since = "1.43.0")]
|
||||
pub const EPSILON: f32 = 1.19209290e-07_f32;
|
||||
|
||||
/// Smallest finite `f32` value.
|
||||
#[stable(feature = "assoc_int_consts", since = "1.43.0")]
|
||||
pub const MIN: f32 = -3.40282347e+38_f32;
|
||||
/// Smallest positive normal `f32` value.
|
||||
#[stable(feature = "assoc_int_consts", since = "1.43.0")]
|
||||
pub const MIN_POSITIVE: f32 = 1.17549435e-38_f32;
|
||||
/// Largest finite `f32` value.
|
||||
#[stable(feature = "assoc_int_consts", since = "1.43.0")]
|
||||
pub const MAX: f32 = 3.40282347e+38_f32;
|
||||
|
||||
/// One greater than the minimum possible normal power of 2 exponent.
|
||||
#[stable(feature = "assoc_int_consts", since = "1.43.0")]
|
||||
pub const MIN_EXP: i32 = -125;
|
||||
/// Maximum possible power of 2 exponent.
|
||||
#[stable(feature = "assoc_int_consts", since = "1.43.0")]
|
||||
pub const MAX_EXP: i32 = 128;
|
||||
|
||||
/// Minimum possible normal power of 10 exponent.
|
||||
#[stable(feature = "assoc_int_consts", since = "1.43.0")]
|
||||
pub const MIN_10_EXP: i32 = -37;
|
||||
/// Maximum possible power of 10 exponent.
|
||||
#[stable(feature = "assoc_int_consts", since = "1.43.0")]
|
||||
pub const MAX_10_EXP: i32 = 38;
|
||||
|
||||
/// Not a Number (NaN).
|
||||
#[stable(feature = "assoc_int_consts", since = "1.43.0")]
|
||||
pub const NAN: f32 = 0.0_f32 / 0.0_f32;
|
||||
/// Infinity (∞).
|
||||
#[stable(feature = "assoc_int_consts", since = "1.43.0")]
|
||||
pub const INFINITY: f32 = 1.0_f32 / 0.0_f32;
|
||||
/// Negative infinity (−∞).
|
||||
#[stable(feature = "assoc_int_consts", since = "1.43.0")]
|
||||
pub const NEG_INFINITY: f32 = -1.0_f32 / 0.0_f32;
|
||||
|
||||
/// Returns `true` if this value is `NaN`.
|
||||
///
|
||||
/// ```
|
||||
/// let nan = f32::NAN;
|
||||
/// let f = 7.0_f32;
|
||||
///
|
||||
/// assert!(nan.is_nan());
|
||||
/// assert!(!f.is_nan());
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
|
||||
#[inline]
|
||||
pub const fn is_nan(self) -> bool {
|
||||
self != self
|
||||
}
|
||||
|
||||
// FIXME(#50145): `abs` is publicly unavailable in libcore due to
|
||||
// concerns about portability, so this implementation is for
|
||||
// private use internally.
|
||||
#[inline]
|
||||
#[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
|
||||
const fn abs_private(self) -> f32 {
|
||||
f32::from_bits(self.to_bits() & 0x7fff_ffff)
|
||||
}
|
||||
|
||||
/// Returns `true` if this value is positive infinity or negative infinity, and
|
||||
/// `false` otherwise.
|
||||
///
|
||||
/// ```
|
||||
/// let f = 7.0f32;
|
||||
/// let inf = f32::INFINITY;
|
||||
/// let neg_inf = f32::NEG_INFINITY;
|
||||
/// let nan = f32::NAN;
|
||||
///
|
||||
/// assert!(!f.is_infinite());
|
||||
/// assert!(!nan.is_infinite());
|
||||
///
|
||||
/// assert!(inf.is_infinite());
|
||||
/// assert!(neg_inf.is_infinite());
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
|
||||
#[inline]
|
||||
pub const fn is_infinite(self) -> bool {
|
||||
self.abs_private() == Self::INFINITY
|
||||
}
|
||||
|
||||
/// Returns `true` if this number is neither infinite nor `NaN`.
|
||||
///
|
||||
/// ```
|
||||
/// let f = 7.0f32;
|
||||
/// let inf = f32::INFINITY;
|
||||
/// let neg_inf = f32::NEG_INFINITY;
|
||||
/// let nan = f32::NAN;
|
||||
///
|
||||
/// assert!(f.is_finite());
|
||||
///
|
||||
/// assert!(!nan.is_finite());
|
||||
/// assert!(!inf.is_finite());
|
||||
/// assert!(!neg_inf.is_finite());
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
|
||||
#[inline]
|
||||
pub const fn is_finite(self) -> bool {
|
||||
// There's no need to handle NaN separately: if self is NaN,
|
||||
// the comparison is not true, exactly as desired.
|
||||
self.abs_private() < Self::INFINITY
|
||||
}
|
||||
|
||||
/// Returns `true` if the number is neither zero, infinite,
|
||||
/// [subnormal], or `NaN`.
|
||||
///
|
||||
/// ```
|
||||
/// let min = f32::MIN_POSITIVE; // 1.17549435e-38f32
|
||||
/// let max = f32::MAX;
|
||||
/// let lower_than_min = 1.0e-40_f32;
|
||||
/// let zero = 0.0_f32;
|
||||
///
|
||||
/// assert!(min.is_normal());
|
||||
/// assert!(max.is_normal());
|
||||
///
|
||||
/// assert!(!zero.is_normal());
|
||||
/// assert!(!f32::NAN.is_normal());
|
||||
/// assert!(!f32::INFINITY.is_normal());
|
||||
/// // Values between `0` and `min` are Subnormal.
|
||||
/// assert!(!lower_than_min.is_normal());
|
||||
/// ```
|
||||
/// [subnormal]: https://en.wikipedia.org/wiki/Denormal_number
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
|
||||
#[inline]
|
||||
pub const fn is_normal(self) -> bool {
|
||||
matches!(self.classify(), FpCategory::Normal)
|
||||
}
|
||||
|
||||
/// Returns the floating point category of the number. If only one property
|
||||
/// is going to be tested, it is generally faster to use the specific
|
||||
/// predicate instead.
|
||||
///
|
||||
/// ```
|
||||
/// use std::num::FpCategory;
|
||||
///
|
||||
/// let num = 12.4_f32;
|
||||
/// let inf = f32::INFINITY;
|
||||
///
|
||||
/// assert_eq!(num.classify(), FpCategory::Normal);
|
||||
/// assert_eq!(inf.classify(), FpCategory::Infinite);
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
|
||||
pub const fn classify(self) -> FpCategory {
|
||||
const EXP_MASK: u32 = 0x7f800000;
|
||||
const MAN_MASK: u32 = 0x007fffff;
|
||||
|
||||
let bits = self.to_bits();
|
||||
match (bits & MAN_MASK, bits & EXP_MASK) {
|
||||
(0, 0) => FpCategory::Zero,
|
||||
(_, 0) => FpCategory::Subnormal,
|
||||
(0, EXP_MASK) => FpCategory::Infinite,
|
||||
(_, EXP_MASK) => FpCategory::Nan,
|
||||
_ => FpCategory::Normal,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns `true` if `self` has a positive sign, including `+0.0`, `NaN`s with
|
||||
/// positive sign bit and positive infinity.
|
||||
///
|
||||
/// ```
|
||||
/// let f = 7.0_f32;
|
||||
/// let g = -7.0_f32;
|
||||
///
|
||||
/// assert!(f.is_sign_positive());
|
||||
/// assert!(!g.is_sign_positive());
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
|
||||
#[inline]
|
||||
pub const fn is_sign_positive(self) -> bool {
|
||||
!self.is_sign_negative()
|
||||
}
|
||||
|
||||
/// Returns `true` if `self` has a negative sign, including `-0.0`, `NaN`s with
|
||||
/// negative sign bit and negative infinity.
|
||||
///
|
||||
/// ```
|
||||
/// let f = 7.0f32;
|
||||
/// let g = -7.0f32;
|
||||
///
|
||||
/// assert!(!f.is_sign_negative());
|
||||
/// assert!(g.is_sign_negative());
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
|
||||
#[inline]
|
||||
pub const fn is_sign_negative(self) -> bool {
|
||||
// IEEE754 says: isSignMinus(x) is true if and only if x has negative sign. isSignMinus
|
||||
// applies to zeros and NaNs as well.
|
||||
self.to_bits() & 0x8000_0000 != 0
|
||||
}
|
||||
|
||||
/// Takes the reciprocal (inverse) of a number, `1/x`.
|
||||
///
|
||||
/// ```
|
||||
/// let x = 2.0_f32;
|
||||
/// let abs_difference = (x.recip() - (1.0 / x)).abs();
|
||||
///
|
||||
/// assert!(abs_difference <= f32::EPSILON);
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[inline]
|
||||
pub fn recip(self) -> f32 {
|
||||
1.0 / self
|
||||
}
|
||||
|
||||
/// Converts radians to degrees.
|
||||
///
|
||||
/// ```
|
||||
/// let angle = std::f32::consts::PI;
|
||||
///
|
||||
/// let abs_difference = (angle.to_degrees() - 180.0).abs();
|
||||
///
|
||||
/// assert!(abs_difference <= f32::EPSILON);
|
||||
/// ```
|
||||
#[stable(feature = "f32_deg_rad_conversions", since = "1.7.0")]
|
||||
#[inline]
|
||||
pub fn to_degrees(self) -> f32 {
|
||||
// Use a constant for better precision.
|
||||
const PIS_IN_180: f32 = 57.2957795130823208767981548141051703_f32;
|
||||
self * PIS_IN_180
|
||||
}
|
||||
|
||||
/// Converts degrees to radians.
|
||||
///
|
||||
/// ```
|
||||
/// let angle = 180.0f32;
|
||||
///
|
||||
/// let abs_difference = (angle.to_radians() - std::f32::consts::PI).abs();
|
||||
///
|
||||
/// assert!(abs_difference <= f32::EPSILON);
|
||||
/// ```
|
||||
#[stable(feature = "f32_deg_rad_conversions", since = "1.7.0")]
|
||||
#[inline]
|
||||
pub fn to_radians(self) -> f32 {
|
||||
let value: f32 = consts::PI;
|
||||
self * (value / 180.0f32)
|
||||
}
|
||||
|
||||
/// Returns the maximum of the two numbers.
|
||||
///
|
||||
/// ```
|
||||
/// let x = 1.0f32;
|
||||
/// let y = 2.0f32;
|
||||
///
|
||||
/// assert_eq!(x.max(y), y);
|
||||
/// ```
|
||||
///
|
||||
/// If one of the arguments is NaN, then the other argument is returned.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[inline]
|
||||
pub fn max(self, other: f32) -> f32 {
|
||||
intrinsics::maxnumf32(self, other)
|
||||
}
|
||||
|
||||
/// Returns the minimum of the two numbers.
|
||||
///
|
||||
/// ```
|
||||
/// let x = 1.0f32;
|
||||
/// let y = 2.0f32;
|
||||
///
|
||||
/// assert_eq!(x.min(y), x);
|
||||
/// ```
|
||||
///
|
||||
/// If one of the arguments is NaN, then the other argument is returned.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[inline]
|
||||
pub fn min(self, other: f32) -> f32 {
|
||||
intrinsics::minnumf32(self, other)
|
||||
}
|
||||
|
||||
/// Rounds toward zero and converts to any primitive integer type,
|
||||
/// assuming that the value is finite and fits in that type.
|
||||
///
|
||||
/// ```
|
||||
/// let value = 4.6_f32;
|
||||
/// let rounded = unsafe { value.to_int_unchecked::<u16>() };
|
||||
/// assert_eq!(rounded, 4);
|
||||
///
|
||||
/// let value = -128.9_f32;
|
||||
/// let rounded = unsafe { value.to_int_unchecked::<i8>() };
|
||||
/// assert_eq!(rounded, i8::MIN);
|
||||
/// ```
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The value must:
|
||||
///
|
||||
/// * Not be `NaN`
|
||||
/// * Not be infinite
|
||||
/// * Be representable in the return type `Int`, after truncating off its fractional part
|
||||
#[stable(feature = "float_approx_unchecked_to", since = "1.44.0")]
|
||||
#[inline]
|
||||
pub unsafe fn to_int_unchecked<Int>(self) -> Int
|
||||
where
|
||||
Self: FloatToInt<Int>,
|
||||
{
|
||||
// SAFETY: the caller must uphold the safety contract for
|
||||
// `FloatToInt::to_int_unchecked`.
|
||||
unsafe { FloatToInt::<Int>::to_int_unchecked(self) }
|
||||
}
|
||||
|
||||
/// Raw transmutation to `u32`.
|
||||
///
|
||||
/// This is currently identical to `transmute::<f32, u32>(self)` on all platforms.
|
||||
///
|
||||
/// See `from_bits` for some discussion of the portability of this operation
|
||||
/// (there are almost no issues).
|
||||
///
|
||||
/// Note that this function is distinct from `as` casting, which attempts to
|
||||
/// preserve the *numeric* value, and not the bitwise value.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// assert_ne!((1f32).to_bits(), 1f32 as u32); // to_bits() is not casting!
|
||||
/// assert_eq!((12.5f32).to_bits(), 0x41480000);
|
||||
///
|
||||
/// ```
|
||||
#[stable(feature = "float_bits_conv", since = "1.20.0")]
|
||||
#[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")]
|
||||
#[inline]
|
||||
pub const fn to_bits(self) -> u32 {
|
||||
// SAFETY: `u32` is a plain old datatype so we can always transmute to it
|
||||
unsafe { mem::transmute(self) }
|
||||
}
|
||||
|
||||
/// Raw transmutation from `u32`.
|
||||
///
|
||||
/// This is currently identical to `transmute::<u32, f32>(v)` on all platforms.
|
||||
/// It turns out this is incredibly portable, for two reasons:
|
||||
///
|
||||
/// * Floats and Ints have the same endianness on all supported platforms.
|
||||
/// * IEEE-754 very precisely specifies the bit layout of floats.
|
||||
///
|
||||
/// However there is one caveat: prior to the 2008 version of IEEE-754, how
|
||||
/// to interpret the NaN signaling bit wasn't actually specified. Most platforms
|
||||
/// (notably x86 and ARM) picked the interpretation that was ultimately
|
||||
/// standardized in 2008, but some didn't (notably MIPS). As a result, all
|
||||
/// signaling NaNs on MIPS are quiet NaNs on x86, and vice-versa.
|
||||
///
|
||||
/// Rather than trying to preserve signaling-ness cross-platform, this
|
||||
/// implementation favors preserving the exact bits. This means that
|
||||
/// any payloads encoded in NaNs will be preserved even if the result of
|
||||
/// this method is sent over the network from an x86 machine to a MIPS one.
|
||||
///
|
||||
/// If the results of this method are only manipulated by the same
|
||||
/// architecture that produced them, then there is no portability concern.
|
||||
///
|
||||
/// If the input isn't NaN, then there is no portability concern.
|
||||
///
|
||||
/// If you don't care about signalingness (very likely), then there is no
|
||||
/// portability concern.
|
||||
///
|
||||
/// Note that this function is distinct from `as` casting, which attempts to
|
||||
/// preserve the *numeric* value, and not the bitwise value.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// let v = f32::from_bits(0x41480000);
|
||||
/// assert_eq!(v, 12.5);
|
||||
/// ```
|
||||
#[stable(feature = "float_bits_conv", since = "1.20.0")]
|
||||
#[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")]
|
||||
#[inline]
|
||||
pub const fn from_bits(v: u32) -> Self {
|
||||
// SAFETY: `u32` is a plain old datatype so we can always transmute from it
|
||||
// It turns out the safety issues with sNaN were overblown! Hooray!
|
||||
unsafe { mem::transmute(v) }
|
||||
}
|
||||
|
||||
/// Return the memory representation of this floating point number as a byte array in
|
||||
/// big-endian (network) byte order.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// let bytes = 12.5f32.to_be_bytes();
|
||||
/// assert_eq!(bytes, [0x41, 0x48, 0x00, 0x00]);
|
||||
/// ```
|
||||
#[stable(feature = "float_to_from_bytes", since = "1.40.0")]
|
||||
#[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")]
|
||||
#[inline]
|
||||
pub const fn to_be_bytes(self) -> [u8; 4] {
|
||||
self.to_bits().to_be_bytes()
|
||||
}
|
||||
|
||||
/// Return the memory representation of this floating point number as a byte array in
|
||||
/// little-endian byte order.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// let bytes = 12.5f32.to_le_bytes();
|
||||
/// assert_eq!(bytes, [0x00, 0x00, 0x48, 0x41]);
|
||||
/// ```
|
||||
#[stable(feature = "float_to_from_bytes", since = "1.40.0")]
|
||||
#[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")]
|
||||
#[inline]
|
||||
pub const fn to_le_bytes(self) -> [u8; 4] {
|
||||
self.to_bits().to_le_bytes()
|
||||
}
|
||||
|
||||
/// Return the memory representation of this floating point number as a byte array in
|
||||
/// native byte order.
|
||||
///
|
||||
/// As the target platform's native endianness is used, portable code
|
||||
/// should use [`to_be_bytes`] or [`to_le_bytes`], as appropriate, instead.
|
||||
///
|
||||
/// [`to_be_bytes`]: #method.to_be_bytes
|
||||
/// [`to_le_bytes`]: #method.to_le_bytes
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// let bytes = 12.5f32.to_ne_bytes();
|
||||
/// assert_eq!(
|
||||
/// bytes,
|
||||
/// if cfg!(target_endian = "big") {
|
||||
/// [0x41, 0x48, 0x00, 0x00]
|
||||
/// } else {
|
||||
/// [0x00, 0x00, 0x48, 0x41]
|
||||
/// }
|
||||
/// );
|
||||
/// ```
|
||||
#[stable(feature = "float_to_from_bytes", since = "1.40.0")]
|
||||
#[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")]
|
||||
#[inline]
|
||||
pub const fn to_ne_bytes(self) -> [u8; 4] {
|
||||
self.to_bits().to_ne_bytes()
|
||||
}
|
||||
|
||||
/// Return the memory representation of this floating point number as a byte array in
|
||||
/// native byte order.
|
||||
///
|
||||
/// [`to_ne_bytes`] should be preferred over this whenever possible.
|
||||
///
|
||||
/// [`to_ne_bytes`]: #method.to_ne_bytes
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(num_as_ne_bytes)]
|
||||
/// let num = 12.5f32;
|
||||
/// let bytes = num.as_ne_bytes();
|
||||
/// assert_eq!(
|
||||
/// bytes,
|
||||
/// if cfg!(target_endian = "big") {
|
||||
/// &[0x41, 0x48, 0x00, 0x00]
|
||||
/// } else {
|
||||
/// &[0x00, 0x00, 0x48, 0x41]
|
||||
/// }
|
||||
/// );
|
||||
/// ```
|
||||
#[unstable(feature = "num_as_ne_bytes", issue = "76976")]
|
||||
#[inline]
|
||||
pub fn as_ne_bytes(&self) -> &[u8; 4] {
|
||||
// SAFETY: `f32` is a plain old datatype so we can always transmute to it
|
||||
unsafe { &*(self as *const Self as *const _) }
|
||||
}
|
||||
|
||||
/// Create a floating point value from its representation as a byte array in big endian.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// let value = f32::from_be_bytes([0x41, 0x48, 0x00, 0x00]);
|
||||
/// assert_eq!(value, 12.5);
|
||||
/// ```
|
||||
#[stable(feature = "float_to_from_bytes", since = "1.40.0")]
|
||||
#[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")]
|
||||
#[inline]
|
||||
pub const fn from_be_bytes(bytes: [u8; 4]) -> Self {
|
||||
Self::from_bits(u32::from_be_bytes(bytes))
|
||||
}
|
||||
|
||||
/// Create a floating point value from its representation as a byte array in little endian.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// let value = f32::from_le_bytes([0x00, 0x00, 0x48, 0x41]);
|
||||
/// assert_eq!(value, 12.5);
|
||||
/// ```
|
||||
#[stable(feature = "float_to_from_bytes", since = "1.40.0")]
|
||||
#[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")]
|
||||
#[inline]
|
||||
pub const fn from_le_bytes(bytes: [u8; 4]) -> Self {
|
||||
Self::from_bits(u32::from_le_bytes(bytes))
|
||||
}
|
||||
|
||||
/// Create a floating point value from its representation as a byte array in native endian.
|
||||
///
|
||||
/// As the target platform's native endianness is used, portable code
|
||||
/// likely wants to use [`from_be_bytes`] or [`from_le_bytes`], as
|
||||
/// appropriate instead.
|
||||
///
|
||||
/// [`from_be_bytes`]: #method.from_be_bytes
|
||||
/// [`from_le_bytes`]: #method.from_le_bytes
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// let value = f32::from_ne_bytes(if cfg!(target_endian = "big") {
|
||||
/// [0x41, 0x48, 0x00, 0x00]
|
||||
/// } else {
|
||||
/// [0x00, 0x00, 0x48, 0x41]
|
||||
/// });
|
||||
/// assert_eq!(value, 12.5);
|
||||
/// ```
|
||||
#[stable(feature = "float_to_from_bytes", since = "1.40.0")]
|
||||
#[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")]
|
||||
#[inline]
|
||||
pub const fn from_ne_bytes(bytes: [u8; 4]) -> Self {
|
||||
Self::from_bits(u32::from_ne_bytes(bytes))
|
||||
}
|
||||
|
||||
/// Returns an ordering between self and other values.
|
||||
/// Unlike the standard partial comparison between floating point numbers,
|
||||
/// this comparison always produces an ordering in accordance to
|
||||
/// the totalOrder predicate as defined in IEEE 754 (2008 revision)
|
||||
/// floating point standard. The values are ordered in following order:
|
||||
/// - Negative quiet NaN
|
||||
/// - Negative signaling NaN
|
||||
/// - Negative infinity
|
||||
/// - Negative numbers
|
||||
/// - Negative subnormal numbers
|
||||
/// - Negative zero
|
||||
/// - Positive zero
|
||||
/// - Positive subnormal numbers
|
||||
/// - Positive numbers
|
||||
/// - Positive infinity
|
||||
/// - Positive signaling NaN
|
||||
/// - Positive quiet NaN
|
||||
///
|
||||
/// Note that this function does not always agree with the [`PartialOrd`]
|
||||
/// and [`PartialEq`] implementations of `f32`. In particular, they regard
|
||||
/// negative and positive zero as equal, while `total_cmp` doesn't.
|
||||
///
|
||||
/// # Example
|
||||
/// ```
|
||||
/// #![feature(total_cmp)]
|
||||
/// struct GoodBoy {
|
||||
/// name: String,
|
||||
/// weight: f32,
|
||||
/// }
|
||||
///
|
||||
/// let mut bois = vec![
|
||||
/// GoodBoy { name: "Pucci".to_owned(), weight: 0.1 },
|
||||
/// GoodBoy { name: "Woofer".to_owned(), weight: 99.0 },
|
||||
/// GoodBoy { name: "Yapper".to_owned(), weight: 10.0 },
|
||||
/// GoodBoy { name: "Chonk".to_owned(), weight: f32::INFINITY },
|
||||
/// GoodBoy { name: "Abs. Unit".to_owned(), weight: f32::NAN },
|
||||
/// GoodBoy { name: "Floaty".to_owned(), weight: -5.0 },
|
||||
/// ];
|
||||
///
|
||||
/// bois.sort_by(|a, b| a.weight.total_cmp(&b.weight));
|
||||
/// # assert!(bois.into_iter().map(|b| b.weight)
|
||||
/// # .zip([-5.0, 0.1, 10.0, 99.0, f32::INFINITY, f32::NAN].iter())
|
||||
/// # .all(|(a, b)| a.to_bits() == b.to_bits()))
|
||||
/// ```
|
||||
#[unstable(feature = "total_cmp", issue = "72599")]
|
||||
#[inline]
|
||||
pub fn total_cmp(&self, other: &Self) -> crate::cmp::Ordering {
|
||||
let mut left = self.to_bits() as i32;
|
||||
let mut right = other.to_bits() as i32;
|
||||
|
||||
// In case of negatives, flip all the bits except the sign
|
||||
// to achieve a similar layout as two's complement integers
|
||||
//
|
||||
// Why does this work? IEEE 754 floats consist of three fields:
|
||||
// Sign bit, exponent and mantissa. The set of exponent and mantissa
|
||||
// fields as a whole have the property that their bitwise order is
|
||||
// equal to the numeric magnitude where the magnitude is defined.
|
||||
// The magnitude is not normally defined on NaN values, but
|
||||
// IEEE 754 totalOrder defines the NaN values also to follow the
|
||||
// bitwise order. This leads to order explained in the doc comment.
|
||||
// However, the representation of magnitude is the same for negative
|
||||
// and positive numbers – only the sign bit is different.
|
||||
// To easily compare the floats as signed integers, we need to
|
||||
// flip the exponent and mantissa bits in case of negative numbers.
|
||||
// We effectively convert the numbers to "two's complement" form.
|
||||
//
|
||||
// To do the flipping, we construct a mask and XOR against it.
|
||||
// We branchlessly calculate an "all-ones except for the sign bit"
|
||||
// mask from negative-signed values: right shifting sign-extends
|
||||
// the integer, so we "fill" the mask with sign bits, and then
|
||||
// convert to unsigned to push one more zero bit.
|
||||
// On positive values, the mask is all zeros, so it's a no-op.
|
||||
left ^= (((left >> 31) as u32) >> 1) as i32;
|
||||
right ^= (((right >> 31) as u32) >> 1) as i32;
|
||||
|
||||
left.cmp(&right)
|
||||
}
|
||||
}
|
||||
952
libgrust/rustc-lib/core/src/num/f64.rs
Normal file
952
libgrust/rustc-lib/core/src/num/f64.rs
Normal file
@@ -0,0 +1,952 @@
|
||||
//! This module provides constants which are specific to the implementation
|
||||
//! of the `f64` floating point data type.
|
||||
//!
|
||||
//! *[See also the `f64` primitive type](../../std/primitive.f64.html).*
|
||||
//!
|
||||
//! Mathematically significant numbers are provided in the `consts` sub-module.
|
||||
//!
|
||||
//! Although using these constants won’t cause compilation warnings,
|
||||
//! new code should use the associated constants directly on the primitive type.
|
||||
|
||||
#![stable(feature = "rust1", since = "1.0.0")]
|
||||
|
||||
use crate::convert::FloatToInt;
|
||||
#[cfg(not(test))]
|
||||
use crate::intrinsics;
|
||||
use crate::mem;
|
||||
use crate::num::FpCategory;
|
||||
|
||||
/// The radix or base of the internal representation of `f64`.
|
||||
/// Use [`f64::RADIX`](../../std/primitive.f64.html#associatedconstant.RADIX) instead.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// // deprecated way
|
||||
/// let r = std::f64::RADIX;
|
||||
///
|
||||
/// // intended way
|
||||
/// let r = f64::RADIX;
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub const RADIX: u32 = f64::RADIX;
|
||||
|
||||
/// Number of significant digits in base 2.
|
||||
/// Use [`f64::MANTISSA_DIGITS`](../../std/primitive.f64.html#associatedconstant.MANTISSA_DIGITS) instead.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// // deprecated way
|
||||
/// let d = std::f64::MANTISSA_DIGITS;
|
||||
///
|
||||
/// // intended way
|
||||
/// let d = f64::MANTISSA_DIGITS;
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub const MANTISSA_DIGITS: u32 = f64::MANTISSA_DIGITS;
|
||||
|
||||
/// Approximate number of significant digits in base 10.
|
||||
/// Use [`f64::DIGITS`](../../std/primitive.f64.html#associatedconstant.DIGITS) instead.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// // deprecated way
|
||||
/// let d = std::f64::DIGITS;
|
||||
///
|
||||
/// // intended way
|
||||
/// let d = f64::DIGITS;
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub const DIGITS: u32 = f64::DIGITS;
|
||||
|
||||
/// [Machine epsilon] value for `f64`.
|
||||
/// Use [`f64::EPSILON`](../../std/primitive.f64.html#associatedconstant.EPSILON) instead.
|
||||
///
|
||||
/// This is the difference between `1.0` and the next larger representable number.
|
||||
///
|
||||
/// [Machine epsilon]: https://en.wikipedia.org/wiki/Machine_epsilon
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// // deprecated way
|
||||
/// let e = std::f64::EPSILON;
|
||||
///
|
||||
/// // intended way
|
||||
/// let e = f64::EPSILON;
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub const EPSILON: f64 = f64::EPSILON;
|
||||
|
||||
/// Smallest finite `f64` value.
|
||||
/// Use [`f64::MIN`](../../std/primitive.f64.html#associatedconstant.MIN) instead.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// // deprecated way
|
||||
/// let min = std::f64::MIN;
|
||||
///
|
||||
/// // intended way
|
||||
/// let min = f64::MIN;
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub const MIN: f64 = f64::MIN;
|
||||
|
||||
/// Smallest positive normal `f64` value.
|
||||
/// Use [`f64::MIN_POSITIVE`](../../std/primitive.f64.html#associatedconstant.MIN_POSITIVE) instead.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// // deprecated way
|
||||
/// let min = std::f64::MIN_POSITIVE;
|
||||
///
|
||||
/// // intended way
|
||||
/// let min = f64::MIN_POSITIVE;
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub const MIN_POSITIVE: f64 = f64::MIN_POSITIVE;
|
||||
|
||||
/// Largest finite `f64` value.
|
||||
/// Use [`f64::MAX`](../../std/primitive.f64.html#associatedconstant.MAX) instead.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// // deprecated way
|
||||
/// let max = std::f64::MAX;
|
||||
///
|
||||
/// // intended way
|
||||
/// let max = f64::MAX;
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub const MAX: f64 = f64::MAX;
|
||||
|
||||
/// One greater than the minimum possible normal power of 2 exponent.
|
||||
/// Use [`f64::MIN_EXP`](../../std/primitive.f64.html#associatedconstant.MIN_EXP) instead.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// // deprecated way
|
||||
/// let min = std::f64::MIN_EXP;
|
||||
///
|
||||
/// // intended way
|
||||
/// let min = f64::MIN_EXP;
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub const MIN_EXP: i32 = f64::MIN_EXP;
|
||||
|
||||
/// Maximum possible power of 2 exponent.
|
||||
/// Use [`f64::MAX_EXP`](../../std/primitive.f64.html#associatedconstant.MAX_EXP) instead.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// // deprecated way
|
||||
/// let max = std::f64::MAX_EXP;
|
||||
///
|
||||
/// // intended way
|
||||
/// let max = f64::MAX_EXP;
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub const MAX_EXP: i32 = f64::MAX_EXP;
|
||||
|
||||
/// Minimum possible normal power of 10 exponent.
|
||||
/// Use [`f64::MIN_10_EXP`](../../std/primitive.f64.html#associatedconstant.MIN_10_EXP) instead.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// // deprecated way
|
||||
/// let min = std::f64::MIN_10_EXP;
|
||||
///
|
||||
/// // intended way
|
||||
/// let min = f64::MIN_10_EXP;
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub const MIN_10_EXP: i32 = f64::MIN_10_EXP;
|
||||
|
||||
/// Maximum possible power of 10 exponent.
|
||||
/// Use [`f64::MAX_10_EXP`](../../std/primitive.f64.html#associatedconstant.MAX_10_EXP) instead.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// // deprecated way
|
||||
/// let max = std::f64::MAX_10_EXP;
|
||||
///
|
||||
/// // intended way
|
||||
/// let max = f64::MAX_10_EXP;
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub const MAX_10_EXP: i32 = f64::MAX_10_EXP;
|
||||
|
||||
/// Not a Number (NaN).
|
||||
/// Use [`f64::NAN`](../../std/primitive.f64.html#associatedconstant.NAN) instead.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// // deprecated way
|
||||
/// let nan = std::f64::NAN;
|
||||
///
|
||||
/// // intended way
|
||||
/// let nan = f64::NAN;
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub const NAN: f64 = f64::NAN;
|
||||
|
||||
/// Infinity (∞).
|
||||
/// Use [`f64::INFINITY`](../../std/primitive.f64.html#associatedconstant.INFINITY) instead.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// // deprecated way
|
||||
/// let inf = std::f64::INFINITY;
|
||||
///
|
||||
/// // intended way
|
||||
/// let inf = f64::INFINITY;
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub const INFINITY: f64 = f64::INFINITY;
|
||||
|
||||
/// Negative infinity (−∞).
|
||||
/// Use [`f64::NEG_INFINITY`](../../std/primitive.f64.html#associatedconstant.NEG_INFINITY) instead.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// // deprecated way
|
||||
/// let ninf = std::f64::NEG_INFINITY;
|
||||
///
|
||||
/// // intended way
|
||||
/// let ninf = f64::NEG_INFINITY;
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub const NEG_INFINITY: f64 = f64::NEG_INFINITY;
|
||||
|
||||
/// Basic mathematical constants.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub mod consts {
|
||||
// FIXME: replace with mathematical constants from cmath.
|
||||
|
||||
/// Archimedes' constant (π)
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub const PI: f64 = 3.14159265358979323846264338327950288_f64;
|
||||
|
||||
/// The full circle constant (τ)
|
||||
///
|
||||
/// Equal to 2π.
|
||||
#[stable(feature = "tau_constant", since = "1.47.0")]
|
||||
pub const TAU: f64 = 6.28318530717958647692528676655900577_f64;
|
||||
|
||||
/// π/2
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub const FRAC_PI_2: f64 = 1.57079632679489661923132169163975144_f64;
|
||||
|
||||
/// π/3
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub const FRAC_PI_3: f64 = 1.04719755119659774615421446109316763_f64;
|
||||
|
||||
/// π/4
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub const FRAC_PI_4: f64 = 0.785398163397448309615660845819875721_f64;
|
||||
|
||||
/// π/6
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub const FRAC_PI_6: f64 = 0.52359877559829887307710723054658381_f64;
|
||||
|
||||
/// π/8
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub const FRAC_PI_8: f64 = 0.39269908169872415480783042290993786_f64;
|
||||
|
||||
/// 1/π
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub const FRAC_1_PI: f64 = 0.318309886183790671537767526745028724_f64;
|
||||
|
||||
/// 2/π
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub const FRAC_2_PI: f64 = 0.636619772367581343075535053490057448_f64;
|
||||
|
||||
/// 2/sqrt(π)
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub const FRAC_2_SQRT_PI: f64 = 1.12837916709551257389615890312154517_f64;
|
||||
|
||||
/// sqrt(2)
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub const SQRT_2: f64 = 1.41421356237309504880168872420969808_f64;
|
||||
|
||||
/// 1/sqrt(2)
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub const FRAC_1_SQRT_2: f64 = 0.707106781186547524400844362104849039_f64;
|
||||
|
||||
/// Euler's number (e)
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub const E: f64 = 2.71828182845904523536028747135266250_f64;
|
||||
|
||||
/// log<sub>2</sub>(10)
|
||||
#[stable(feature = "extra_log_consts", since = "1.43.0")]
|
||||
pub const LOG2_10: f64 = 3.32192809488736234787031942948939018_f64;
|
||||
|
||||
/// log<sub>2</sub>(e)
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub const LOG2_E: f64 = 1.44269504088896340735992468100189214_f64;
|
||||
|
||||
/// log<sub>10</sub>(2)
|
||||
#[stable(feature = "extra_log_consts", since = "1.43.0")]
|
||||
pub const LOG10_2: f64 = 0.301029995663981195213738894724493027_f64;
|
||||
|
||||
/// log<sub>10</sub>(e)
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub const LOG10_E: f64 = 0.434294481903251827651128918916605082_f64;
|
||||
|
||||
/// ln(2)
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub const LN_2: f64 = 0.693147180559945309417232121458176568_f64;
|
||||
|
||||
/// ln(10)
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub const LN_10: f64 = 2.30258509299404568401799145468436421_f64;
|
||||
}
|
||||
|
||||
#[lang = "f64"]
|
||||
#[cfg(not(test))]
|
||||
impl f64 {
|
||||
/// The radix or base of the internal representation of `f64`.
|
||||
#[stable(feature = "assoc_int_consts", since = "1.43.0")]
|
||||
pub const RADIX: u32 = 2;
|
||||
|
||||
/// Number of significant digits in base 2.
|
||||
#[stable(feature = "assoc_int_consts", since = "1.43.0")]
|
||||
pub const MANTISSA_DIGITS: u32 = 53;
|
||||
/// Approximate number of significant digits in base 10.
|
||||
#[stable(feature = "assoc_int_consts", since = "1.43.0")]
|
||||
pub const DIGITS: u32 = 15;
|
||||
|
||||
/// [Machine epsilon] value for `f64`.
|
||||
///
|
||||
/// This is the difference between `1.0` and the next larger representable number.
|
||||
///
|
||||
/// [Machine epsilon]: https://en.wikipedia.org/wiki/Machine_epsilon
|
||||
#[stable(feature = "assoc_int_consts", since = "1.43.0")]
|
||||
pub const EPSILON: f64 = 2.2204460492503131e-16_f64;
|
||||
|
||||
/// Smallest finite `f64` value.
|
||||
#[stable(feature = "assoc_int_consts", since = "1.43.0")]
|
||||
pub const MIN: f64 = -1.7976931348623157e+308_f64;
|
||||
/// Smallest positive normal `f64` value.
|
||||
#[stable(feature = "assoc_int_consts", since = "1.43.0")]
|
||||
pub const MIN_POSITIVE: f64 = 2.2250738585072014e-308_f64;
|
||||
/// Largest finite `f64` value.
|
||||
#[stable(feature = "assoc_int_consts", since = "1.43.0")]
|
||||
pub const MAX: f64 = 1.7976931348623157e+308_f64;
|
||||
|
||||
/// One greater than the minimum possible normal power of 2 exponent.
|
||||
#[stable(feature = "assoc_int_consts", since = "1.43.0")]
|
||||
pub const MIN_EXP: i32 = -1021;
|
||||
/// Maximum possible power of 2 exponent.
|
||||
#[stable(feature = "assoc_int_consts", since = "1.43.0")]
|
||||
pub const MAX_EXP: i32 = 1024;
|
||||
|
||||
/// Minimum possible normal power of 10 exponent.
|
||||
#[stable(feature = "assoc_int_consts", since = "1.43.0")]
|
||||
pub const MIN_10_EXP: i32 = -307;
|
||||
/// Maximum possible power of 10 exponent.
|
||||
#[stable(feature = "assoc_int_consts", since = "1.43.0")]
|
||||
pub const MAX_10_EXP: i32 = 308;
|
||||
|
||||
/// Not a Number (NaN).
|
||||
#[stable(feature = "assoc_int_consts", since = "1.43.0")]
|
||||
pub const NAN: f64 = 0.0_f64 / 0.0_f64;
|
||||
/// Infinity (∞).
|
||||
#[stable(feature = "assoc_int_consts", since = "1.43.0")]
|
||||
pub const INFINITY: f64 = 1.0_f64 / 0.0_f64;
|
||||
/// Negative infinity (−∞).
|
||||
#[stable(feature = "assoc_int_consts", since = "1.43.0")]
|
||||
pub const NEG_INFINITY: f64 = -1.0_f64 / 0.0_f64;
|
||||
|
||||
/// Returns `true` if this value is `NaN`.
|
||||
///
|
||||
/// ```
|
||||
/// let nan = f64::NAN;
|
||||
/// let f = 7.0_f64;
|
||||
///
|
||||
/// assert!(nan.is_nan());
|
||||
/// assert!(!f.is_nan());
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
|
||||
#[inline]
|
||||
pub const fn is_nan(self) -> bool {
|
||||
self != self
|
||||
}
|
||||
|
||||
// FIXME(#50145): `abs` is publicly unavailable in libcore due to
|
||||
// concerns about portability, so this implementation is for
|
||||
// private use internally.
|
||||
#[inline]
|
||||
#[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
|
||||
const fn abs_private(self) -> f64 {
|
||||
f64::from_bits(self.to_bits() & 0x7fff_ffff_ffff_ffff)
|
||||
}
|
||||
|
||||
/// Returns `true` if this value is positive infinity or negative infinity, and
|
||||
/// `false` otherwise.
|
||||
///
|
||||
/// ```
|
||||
/// let f = 7.0f64;
|
||||
/// let inf = f64::INFINITY;
|
||||
/// let neg_inf = f64::NEG_INFINITY;
|
||||
/// let nan = f64::NAN;
|
||||
///
|
||||
/// assert!(!f.is_infinite());
|
||||
/// assert!(!nan.is_infinite());
|
||||
///
|
||||
/// assert!(inf.is_infinite());
|
||||
/// assert!(neg_inf.is_infinite());
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
|
||||
#[inline]
|
||||
pub const fn is_infinite(self) -> bool {
|
||||
self.abs_private() == Self::INFINITY
|
||||
}
|
||||
|
||||
/// Returns `true` if this number is neither infinite nor `NaN`.
|
||||
///
|
||||
/// ```
|
||||
/// let f = 7.0f64;
|
||||
/// let inf: f64 = f64::INFINITY;
|
||||
/// let neg_inf: f64 = f64::NEG_INFINITY;
|
||||
/// let nan: f64 = f64::NAN;
|
||||
///
|
||||
/// assert!(f.is_finite());
|
||||
///
|
||||
/// assert!(!nan.is_finite());
|
||||
/// assert!(!inf.is_finite());
|
||||
/// assert!(!neg_inf.is_finite());
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
|
||||
#[inline]
|
||||
pub const fn is_finite(self) -> bool {
|
||||
// There's no need to handle NaN separately: if self is NaN,
|
||||
// the comparison is not true, exactly as desired.
|
||||
self.abs_private() < Self::INFINITY
|
||||
}
|
||||
|
||||
/// Returns `true` if the number is neither zero, infinite,
|
||||
/// [subnormal], or `NaN`.
|
||||
///
|
||||
/// ```
|
||||
/// let min = f64::MIN_POSITIVE; // 2.2250738585072014e-308f64
|
||||
/// let max = f64::MAX;
|
||||
/// let lower_than_min = 1.0e-308_f64;
|
||||
/// let zero = 0.0f64;
|
||||
///
|
||||
/// assert!(min.is_normal());
|
||||
/// assert!(max.is_normal());
|
||||
///
|
||||
/// assert!(!zero.is_normal());
|
||||
/// assert!(!f64::NAN.is_normal());
|
||||
/// assert!(!f64::INFINITY.is_normal());
|
||||
/// // Values between `0` and `min` are Subnormal.
|
||||
/// assert!(!lower_than_min.is_normal());
|
||||
/// ```
|
||||
/// [subnormal]: https://en.wikipedia.org/wiki/Denormal_number
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
|
||||
#[inline]
|
||||
pub const fn is_normal(self) -> bool {
|
||||
matches!(self.classify(), FpCategory::Normal)
|
||||
}
|
||||
|
||||
/// Returns the floating point category of the number. If only one property
|
||||
/// is going to be tested, it is generally faster to use the specific
|
||||
/// predicate instead.
|
||||
///
|
||||
/// ```
|
||||
/// use std::num::FpCategory;
|
||||
///
|
||||
/// let num = 12.4_f64;
|
||||
/// let inf = f64::INFINITY;
|
||||
///
|
||||
/// assert_eq!(num.classify(), FpCategory::Normal);
|
||||
/// assert_eq!(inf.classify(), FpCategory::Infinite);
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
|
||||
pub const fn classify(self) -> FpCategory {
|
||||
const EXP_MASK: u64 = 0x7ff0000000000000;
|
||||
const MAN_MASK: u64 = 0x000fffffffffffff;
|
||||
|
||||
let bits = self.to_bits();
|
||||
match (bits & MAN_MASK, bits & EXP_MASK) {
|
||||
(0, 0) => FpCategory::Zero,
|
||||
(_, 0) => FpCategory::Subnormal,
|
||||
(0, EXP_MASK) => FpCategory::Infinite,
|
||||
(_, EXP_MASK) => FpCategory::Nan,
|
||||
_ => FpCategory::Normal,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns `true` if `self` has a positive sign, including `+0.0`, `NaN`s with
|
||||
/// positive sign bit and positive infinity.
|
||||
///
|
||||
/// ```
|
||||
/// let f = 7.0_f64;
|
||||
/// let g = -7.0_f64;
|
||||
///
|
||||
/// assert!(f.is_sign_positive());
|
||||
/// assert!(!g.is_sign_positive());
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
|
||||
#[inline]
|
||||
pub const fn is_sign_positive(self) -> bool {
|
||||
!self.is_sign_negative()
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_deprecated(since = "1.0.0", reason = "renamed to is_sign_positive")]
|
||||
#[inline]
|
||||
#[doc(hidden)]
|
||||
pub fn is_positive(self) -> bool {
|
||||
self.is_sign_positive()
|
||||
}
|
||||
|
||||
/// Returns `true` if `self` has a negative sign, including `-0.0`, `NaN`s with
|
||||
/// negative sign bit and negative infinity.
|
||||
///
|
||||
/// ```
|
||||
/// let f = 7.0_f64;
|
||||
/// let g = -7.0_f64;
|
||||
///
|
||||
/// assert!(!f.is_sign_negative());
|
||||
/// assert!(g.is_sign_negative());
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_const_unstable(feature = "const_float_classify", issue = "72505")]
|
||||
#[inline]
|
||||
pub const fn is_sign_negative(self) -> bool {
|
||||
self.to_bits() & 0x8000_0000_0000_0000 != 0
|
||||
}
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_deprecated(since = "1.0.0", reason = "renamed to is_sign_negative")]
|
||||
#[inline]
|
||||
#[doc(hidden)]
|
||||
pub fn is_negative(self) -> bool {
|
||||
self.is_sign_negative()
|
||||
}
|
||||
|
||||
/// Takes the reciprocal (inverse) of a number, `1/x`.
|
||||
///
|
||||
/// ```
|
||||
/// let x = 2.0_f64;
|
||||
/// let abs_difference = (x.recip() - (1.0 / x)).abs();
|
||||
///
|
||||
/// assert!(abs_difference < 1e-10);
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[inline]
|
||||
pub fn recip(self) -> f64 {
|
||||
1.0 / self
|
||||
}
|
||||
|
||||
/// Converts radians to degrees.
|
||||
///
|
||||
/// ```
|
||||
/// let angle = std::f64::consts::PI;
|
||||
///
|
||||
/// let abs_difference = (angle.to_degrees() - 180.0).abs();
|
||||
///
|
||||
/// assert!(abs_difference < 1e-10);
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[inline]
|
||||
pub fn to_degrees(self) -> f64 {
|
||||
// The division here is correctly rounded with respect to the true
|
||||
// value of 180/π. (This differs from f32, where a constant must be
|
||||
// used to ensure a correctly rounded result.)
|
||||
self * (180.0f64 / consts::PI)
|
||||
}
|
||||
|
||||
/// Converts degrees to radians.
|
||||
///
|
||||
/// ```
|
||||
/// let angle = 180.0_f64;
|
||||
///
|
||||
/// let abs_difference = (angle.to_radians() - std::f64::consts::PI).abs();
|
||||
///
|
||||
/// assert!(abs_difference < 1e-10);
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[inline]
|
||||
pub fn to_radians(self) -> f64 {
|
||||
let value: f64 = consts::PI;
|
||||
self * (value / 180.0)
|
||||
}
|
||||
|
||||
/// Returns the maximum of the two numbers.
|
||||
///
|
||||
/// ```
|
||||
/// let x = 1.0_f64;
|
||||
/// let y = 2.0_f64;
|
||||
///
|
||||
/// assert_eq!(x.max(y), y);
|
||||
/// ```
|
||||
///
|
||||
/// If one of the arguments is NaN, then the other argument is returned.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[inline]
|
||||
pub fn max(self, other: f64) -> f64 {
|
||||
intrinsics::maxnumf64(self, other)
|
||||
}
|
||||
|
||||
/// Returns the minimum of the two numbers.
|
||||
///
|
||||
/// ```
|
||||
/// let x = 1.0_f64;
|
||||
/// let y = 2.0_f64;
|
||||
///
|
||||
/// assert_eq!(x.min(y), x);
|
||||
/// ```
|
||||
///
|
||||
/// If one of the arguments is NaN, then the other argument is returned.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[inline]
|
||||
pub fn min(self, other: f64) -> f64 {
|
||||
intrinsics::minnumf64(self, other)
|
||||
}
|
||||
|
||||
/// Rounds toward zero and converts to any primitive integer type,
|
||||
/// assuming that the value is finite and fits in that type.
|
||||
///
|
||||
/// ```
|
||||
/// let value = 4.6_f64;
|
||||
/// let rounded = unsafe { value.to_int_unchecked::<u16>() };
|
||||
/// assert_eq!(rounded, 4);
|
||||
///
|
||||
/// let value = -128.9_f64;
|
||||
/// let rounded = unsafe { value.to_int_unchecked::<i8>() };
|
||||
/// assert_eq!(rounded, i8::MIN);
|
||||
/// ```
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The value must:
|
||||
///
|
||||
/// * Not be `NaN`
|
||||
/// * Not be infinite
|
||||
/// * Be representable in the return type `Int`, after truncating off its fractional part
|
||||
#[stable(feature = "float_approx_unchecked_to", since = "1.44.0")]
|
||||
#[inline]
|
||||
pub unsafe fn to_int_unchecked<Int>(self) -> Int
|
||||
where
|
||||
Self: FloatToInt<Int>,
|
||||
{
|
||||
// SAFETY: the caller must uphold the safety contract for
|
||||
// `FloatToInt::to_int_unchecked`.
|
||||
unsafe { FloatToInt::<Int>::to_int_unchecked(self) }
|
||||
}
|
||||
|
||||
/// Raw transmutation to `u64`.
|
||||
///
|
||||
/// This is currently identical to `transmute::<f64, u64>(self)` on all platforms.
|
||||
///
|
||||
/// See `from_bits` for some discussion of the portability of this operation
|
||||
/// (there are almost no issues).
|
||||
///
|
||||
/// Note that this function is distinct from `as` casting, which attempts to
|
||||
/// preserve the *numeric* value, and not the bitwise value.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// assert!((1f64).to_bits() != 1f64 as u64); // to_bits() is not casting!
|
||||
/// assert_eq!((12.5f64).to_bits(), 0x4029000000000000);
|
||||
///
|
||||
/// ```
|
||||
#[stable(feature = "float_bits_conv", since = "1.20.0")]
|
||||
#[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")]
|
||||
#[inline]
|
||||
pub const fn to_bits(self) -> u64 {
|
||||
// SAFETY: `u64` is a plain old datatype so we can always transmute to it
|
||||
unsafe { mem::transmute(self) }
|
||||
}
|
||||
|
||||
/// Raw transmutation from `u64`.
|
||||
///
|
||||
/// This is currently identical to `transmute::<u64, f64>(v)` on all platforms.
|
||||
/// It turns out this is incredibly portable, for two reasons:
|
||||
///
|
||||
/// * Floats and Ints have the same endianness on all supported platforms.
|
||||
/// * IEEE-754 very precisely specifies the bit layout of floats.
|
||||
///
|
||||
/// However there is one caveat: prior to the 2008 version of IEEE-754, how
|
||||
/// to interpret the NaN signaling bit wasn't actually specified. Most platforms
|
||||
/// (notably x86 and ARM) picked the interpretation that was ultimately
|
||||
/// standardized in 2008, but some didn't (notably MIPS). As a result, all
|
||||
/// signaling NaNs on MIPS are quiet NaNs on x86, and vice-versa.
|
||||
///
|
||||
/// Rather than trying to preserve signaling-ness cross-platform, this
|
||||
/// implementation favors preserving the exact bits. This means that
|
||||
/// any payloads encoded in NaNs will be preserved even if the result of
|
||||
/// this method is sent over the network from an x86 machine to a MIPS one.
|
||||
///
|
||||
/// If the results of this method are only manipulated by the same
|
||||
/// architecture that produced them, then there is no portability concern.
|
||||
///
|
||||
/// If the input isn't NaN, then there is no portability concern.
|
||||
///
|
||||
/// If you don't care about signaling-ness (very likely), then there is no
|
||||
/// portability concern.
|
||||
///
|
||||
/// Note that this function is distinct from `as` casting, which attempts to
|
||||
/// preserve the *numeric* value, and not the bitwise value.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// let v = f64::from_bits(0x4029000000000000);
|
||||
/// assert_eq!(v, 12.5);
|
||||
/// ```
|
||||
#[stable(feature = "float_bits_conv", since = "1.20.0")]
|
||||
#[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")]
|
||||
#[inline]
|
||||
pub const fn from_bits(v: u64) -> Self {
|
||||
// SAFETY: `u64` is a plain old datatype so we can always transmute from it
|
||||
// It turns out the safety issues with sNaN were overblown! Hooray!
|
||||
unsafe { mem::transmute(v) }
|
||||
}
|
||||
|
||||
/// Return the memory representation of this floating point number as a byte array in
|
||||
/// big-endian (network) byte order.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// let bytes = 12.5f64.to_be_bytes();
|
||||
/// assert_eq!(bytes, [0x40, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
|
||||
/// ```
|
||||
#[stable(feature = "float_to_from_bytes", since = "1.40.0")]
|
||||
#[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")]
|
||||
#[inline]
|
||||
pub const fn to_be_bytes(self) -> [u8; 8] {
|
||||
self.to_bits().to_be_bytes()
|
||||
}
|
||||
|
||||
/// Return the memory representation of this floating point number as a byte array in
|
||||
/// little-endian byte order.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// let bytes = 12.5f64.to_le_bytes();
|
||||
/// assert_eq!(bytes, [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0x40]);
|
||||
/// ```
|
||||
#[stable(feature = "float_to_from_bytes", since = "1.40.0")]
|
||||
#[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")]
|
||||
#[inline]
|
||||
pub const fn to_le_bytes(self) -> [u8; 8] {
|
||||
self.to_bits().to_le_bytes()
|
||||
}
|
||||
|
||||
/// Return the memory representation of this floating point number as a byte array in
|
||||
/// native byte order.
|
||||
///
|
||||
/// As the target platform's native endianness is used, portable code
|
||||
/// should use [`to_be_bytes`] or [`to_le_bytes`], as appropriate, instead.
|
||||
///
|
||||
/// [`to_be_bytes`]: #method.to_be_bytes
|
||||
/// [`to_le_bytes`]: #method.to_le_bytes
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// let bytes = 12.5f64.to_ne_bytes();
|
||||
/// assert_eq!(
|
||||
/// bytes,
|
||||
/// if cfg!(target_endian = "big") {
|
||||
/// [0x40, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
|
||||
/// } else {
|
||||
/// [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0x40]
|
||||
/// }
|
||||
/// );
|
||||
/// ```
|
||||
#[stable(feature = "float_to_from_bytes", since = "1.40.0")]
|
||||
#[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")]
|
||||
#[inline]
|
||||
pub const fn to_ne_bytes(self) -> [u8; 8] {
|
||||
self.to_bits().to_ne_bytes()
|
||||
}
|
||||
|
||||
/// Return the memory representation of this floating point number as a byte array in
|
||||
/// native byte order.
|
||||
///
|
||||
/// [`to_ne_bytes`] should be preferred over this whenever possible.
|
||||
///
|
||||
/// [`to_ne_bytes`]: #method.to_ne_bytes
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// #![feature(num_as_ne_bytes)]
|
||||
/// let num = 12.5f64;
|
||||
/// let bytes = num.as_ne_bytes();
|
||||
/// assert_eq!(
|
||||
/// bytes,
|
||||
/// if cfg!(target_endian = "big") {
|
||||
/// &[0x40, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
|
||||
/// } else {
|
||||
/// &[0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0x40]
|
||||
/// }
|
||||
/// );
|
||||
/// ```
|
||||
#[unstable(feature = "num_as_ne_bytes", issue = "76976")]
|
||||
#[inline]
|
||||
pub fn as_ne_bytes(&self) -> &[u8; 8] {
|
||||
// SAFETY: `f64` is a plain old datatype so we can always transmute to it
|
||||
unsafe { &*(self as *const Self as *const _) }
|
||||
}
|
||||
|
||||
/// Create a floating point value from its representation as a byte array in big endian.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// let value = f64::from_be_bytes([0x40, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);
|
||||
/// assert_eq!(value, 12.5);
|
||||
/// ```
|
||||
#[stable(feature = "float_to_from_bytes", since = "1.40.0")]
|
||||
#[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")]
|
||||
#[inline]
|
||||
pub const fn from_be_bytes(bytes: [u8; 8]) -> Self {
|
||||
Self::from_bits(u64::from_be_bytes(bytes))
|
||||
}
|
||||
|
||||
/// Create a floating point value from its representation as a byte array in little endian.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// let value = f64::from_le_bytes([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0x40]);
|
||||
/// assert_eq!(value, 12.5);
|
||||
/// ```
|
||||
#[stable(feature = "float_to_from_bytes", since = "1.40.0")]
|
||||
#[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")]
|
||||
#[inline]
|
||||
pub const fn from_le_bytes(bytes: [u8; 8]) -> Self {
|
||||
Self::from_bits(u64::from_le_bytes(bytes))
|
||||
}
|
||||
|
||||
/// Create a floating point value from its representation as a byte array in native endian.
|
||||
///
|
||||
/// As the target platform's native endianness is used, portable code
|
||||
/// likely wants to use [`from_be_bytes`] or [`from_le_bytes`], as
|
||||
/// appropriate instead.
|
||||
///
|
||||
/// [`from_be_bytes`]: #method.from_be_bytes
|
||||
/// [`from_le_bytes`]: #method.from_le_bytes
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// let value = f64::from_ne_bytes(if cfg!(target_endian = "big") {
|
||||
/// [0x40, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
|
||||
/// } else {
|
||||
/// [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0x40]
|
||||
/// });
|
||||
/// assert_eq!(value, 12.5);
|
||||
/// ```
|
||||
#[stable(feature = "float_to_from_bytes", since = "1.40.0")]
|
||||
#[rustc_const_unstable(feature = "const_float_bits_conv", issue = "72447")]
|
||||
#[inline]
|
||||
pub const fn from_ne_bytes(bytes: [u8; 8]) -> Self {
|
||||
Self::from_bits(u64::from_ne_bytes(bytes))
|
||||
}
|
||||
|
||||
/// Returns an ordering between self and other values.
|
||||
/// Unlike the standard partial comparison between floating point numbers,
|
||||
/// this comparison always produces an ordering in accordance to
|
||||
/// the totalOrder predicate as defined in IEEE 754 (2008 revision)
|
||||
/// floating point standard. The values are ordered in following order:
|
||||
/// - Negative quiet NaN
|
||||
/// - Negative signaling NaN
|
||||
/// - Negative infinity
|
||||
/// - Negative numbers
|
||||
/// - Negative subnormal numbers
|
||||
/// - Negative zero
|
||||
/// - Positive zero
|
||||
/// - Positive subnormal numbers
|
||||
/// - Positive numbers
|
||||
/// - Positive infinity
|
||||
/// - Positive signaling NaN
|
||||
/// - Positive quiet NaN
|
||||
///
|
||||
/// Note that this function does not always agree with the [`PartialOrd`]
|
||||
/// and [`PartialEq`] implementations of `f64`. In particular, they regard
|
||||
/// negative and positive zero as equal, while `total_cmp` doesn't.
|
||||
///
|
||||
/// # Example
|
||||
/// ```
|
||||
/// #![feature(total_cmp)]
|
||||
/// struct GoodBoy {
|
||||
/// name: String,
|
||||
/// weight: f64,
|
||||
/// }
|
||||
///
|
||||
/// let mut bois = vec![
|
||||
/// GoodBoy { name: "Pucci".to_owned(), weight: 0.1 },
|
||||
/// GoodBoy { name: "Woofer".to_owned(), weight: 99.0 },
|
||||
/// GoodBoy { name: "Yapper".to_owned(), weight: 10.0 },
|
||||
/// GoodBoy { name: "Chonk".to_owned(), weight: f64::INFINITY },
|
||||
/// GoodBoy { name: "Abs. Unit".to_owned(), weight: f64::NAN },
|
||||
/// GoodBoy { name: "Floaty".to_owned(), weight: -5.0 },
|
||||
/// ];
|
||||
///
|
||||
/// bois.sort_by(|a, b| a.weight.total_cmp(&b.weight));
|
||||
/// # assert!(bois.into_iter().map(|b| b.weight)
|
||||
/// # .zip([-5.0, 0.1, 10.0, 99.0, f64::INFINITY, f64::NAN].iter())
|
||||
/// # .all(|(a, b)| a.to_bits() == b.to_bits()))
|
||||
/// ```
|
||||
#[unstable(feature = "total_cmp", issue = "72599")]
|
||||
#[inline]
|
||||
pub fn total_cmp(&self, other: &Self) -> crate::cmp::Ordering {
|
||||
let mut left = self.to_bits() as i64;
|
||||
let mut right = other.to_bits() as i64;
|
||||
|
||||
// In case of negatives, flip all the bits except the sign
|
||||
// to achieve a similar layout as two's complement integers
|
||||
//
|
||||
// Why does this work? IEEE 754 floats consist of three fields:
|
||||
// Sign bit, exponent and mantissa. The set of exponent and mantissa
|
||||
// fields as a whole have the property that their bitwise order is
|
||||
// equal to the numeric magnitude where the magnitude is defined.
|
||||
// The magnitude is not normally defined on NaN values, but
|
||||
// IEEE 754 totalOrder defines the NaN values also to follow the
|
||||
// bitwise order. This leads to order explained in the doc comment.
|
||||
// However, the representation of magnitude is the same for negative
|
||||
// and positive numbers – only the sign bit is different.
|
||||
// To easily compare the floats as signed integers, we need to
|
||||
// flip the exponent and mantissa bits in case of negative numbers.
|
||||
// We effectively convert the numbers to "two's complement" form.
|
||||
//
|
||||
// To do the flipping, we construct a mask and XOR against it.
|
||||
// We branchlessly calculate an "all-ones except for the sign bit"
|
||||
// mask from negative-signed values: right shifting sign-extends
|
||||
// the integer, so we "fill" the mask with sign bits, and then
|
||||
// convert to unsigned to push one more zero bit.
|
||||
// On positive values, the mask is all zeros, so it's a no-op.
|
||||
left ^= (((left >> 63) as u64) >> 1) as i64;
|
||||
right ^= (((right >> 63) as u64) >> 1) as i64;
|
||||
|
||||
left.cmp(&right)
|
||||
}
|
||||
}
|
||||
100
libgrust/rustc-lib/core/src/num/flt2dec/decoder.rs
Normal file
100
libgrust/rustc-lib/core/src/num/flt2dec/decoder.rs
Normal file
@@ -0,0 +1,100 @@
|
||||
//! Decodes a floating-point value into individual parts and error ranges.
|
||||
|
||||
use crate::num::dec2flt::rawfp::RawFloat;
|
||||
use crate::num::FpCategory;
|
||||
|
||||
/// Decoded unsigned finite value, such that:
|
||||
///
|
||||
/// - The original value equals to `mant * 2^exp`.
|
||||
///
|
||||
/// - Any number from `(mant - minus) * 2^exp` to `(mant + plus) * 2^exp` will
|
||||
/// round to the original value. The range is inclusive only when
|
||||
/// `inclusive` is `true`.
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
pub struct Decoded {
|
||||
/// The scaled mantissa.
|
||||
pub mant: u64,
|
||||
/// The lower error range.
|
||||
pub minus: u64,
|
||||
/// The upper error range.
|
||||
pub plus: u64,
|
||||
/// The shared exponent in base 2.
|
||||
pub exp: i16,
|
||||
/// True when the error range is inclusive.
|
||||
///
|
||||
/// In IEEE 754, this is true when the original mantissa was even.
|
||||
pub inclusive: bool,
|
||||
}
|
||||
|
||||
/// Decoded unsigned value.
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
pub enum FullDecoded {
|
||||
/// Not-a-number.
|
||||
Nan,
|
||||
/// Infinities, either positive or negative.
|
||||
Infinite,
|
||||
/// Zero, either positive or negative.
|
||||
Zero,
|
||||
/// Finite numbers with further decoded fields.
|
||||
Finite(Decoded),
|
||||
}
|
||||
|
||||
/// A floating point type which can be `decode`d.
|
||||
pub trait DecodableFloat: RawFloat + Copy {
|
||||
/// The minimum positive normalized value.
|
||||
fn min_pos_norm_value() -> Self;
|
||||
}
|
||||
|
||||
impl DecodableFloat for f32 {
|
||||
fn min_pos_norm_value() -> Self {
|
||||
f32::MIN_POSITIVE
|
||||
}
|
||||
}
|
||||
|
||||
impl DecodableFloat for f64 {
|
||||
fn min_pos_norm_value() -> Self {
|
||||
f64::MIN_POSITIVE
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a sign (true when negative) and `FullDecoded` value
|
||||
/// from given floating point number.
|
||||
pub fn decode<T: DecodableFloat>(v: T) -> (/*negative?*/ bool, FullDecoded) {
|
||||
let (mant, exp, sign) = v.integer_decode();
|
||||
let even = (mant & 1) == 0;
|
||||
let decoded = match v.classify() {
|
||||
FpCategory::Nan => FullDecoded::Nan,
|
||||
FpCategory::Infinite => FullDecoded::Infinite,
|
||||
FpCategory::Zero => FullDecoded::Zero,
|
||||
FpCategory::Subnormal => {
|
||||
// neighbors: (mant - 2, exp) -- (mant, exp) -- (mant + 2, exp)
|
||||
// Float::integer_decode always preserves the exponent,
|
||||
// so the mantissa is scaled for subnormals.
|
||||
FullDecoded::Finite(Decoded { mant, minus: 1, plus: 1, exp, inclusive: even })
|
||||
}
|
||||
FpCategory::Normal => {
|
||||
let minnorm = <T as DecodableFloat>::min_pos_norm_value().integer_decode();
|
||||
if mant == minnorm.0 {
|
||||
// neighbors: (maxmant, exp - 1) -- (minnormmant, exp) -- (minnormmant + 1, exp)
|
||||
// where maxmant = minnormmant * 2 - 1
|
||||
FullDecoded::Finite(Decoded {
|
||||
mant: mant << 2,
|
||||
minus: 1,
|
||||
plus: 2,
|
||||
exp: exp - 2,
|
||||
inclusive: even,
|
||||
})
|
||||
} else {
|
||||
// neighbors: (mant - 1, exp) -- (mant, exp) -- (mant + 1, exp)
|
||||
FullDecoded::Finite(Decoded {
|
||||
mant: mant << 1,
|
||||
minus: 1,
|
||||
plus: 1,
|
||||
exp: exp - 1,
|
||||
inclusive: even,
|
||||
})
|
||||
}
|
||||
}
|
||||
};
|
||||
(sign < 0, decoded)
|
||||
}
|
||||
14
libgrust/rustc-lib/core/src/num/flt2dec/estimator.rs
Normal file
14
libgrust/rustc-lib/core/src/num/flt2dec/estimator.rs
Normal file
@@ -0,0 +1,14 @@
|
||||
//! The exponent estimator.
|
||||
|
||||
/// Finds `k_0` such that `10^(k_0-1) < mant * 2^exp <= 10^(k_0+1)`.
|
||||
///
|
||||
/// This is used to approximate `k = ceil(log_10 (mant * 2^exp))`;
|
||||
/// the true `k` is either `k_0` or `k_0+1`.
|
||||
#[doc(hidden)]
|
||||
pub fn estimate_scaling_factor(mant: u64, exp: i16) -> i16 {
|
||||
// 2^(nbits-1) < mant <= 2^nbits if mant > 0
|
||||
let nbits = 64 - (mant - 1).leading_zeros() as i64;
|
||||
// 1292913986 = floor(2^32 * log_10 2)
|
||||
// therefore this always underestimates (or is exact), but not much.
|
||||
(((nbits + exp as i64) * 1292913986) >> 32) as i16
|
||||
}
|
||||
793
libgrust/rustc-lib/core/src/num/flt2dec/mod.rs
Normal file
793
libgrust/rustc-lib/core/src/num/flt2dec/mod.rs
Normal file
@@ -0,0 +1,793 @@
|
||||
/*!
|
||||
|
||||
Floating-point number to decimal conversion routines.
|
||||
|
||||
# Problem statement
|
||||
|
||||
We are given the floating-point number `v = f * 2^e` with an integer `f`,
|
||||
and its bounds `minus` and `plus` such that any number between `v - minus` and
|
||||
`v + plus` will be rounded to `v`. For the simplicity we assume that
|
||||
this range is exclusive. Then we would like to get the unique decimal
|
||||
representation `V = 0.d[0..n-1] * 10^k` such that:
|
||||
|
||||
- `d[0]` is non-zero.
|
||||
|
||||
- It's correctly rounded when parsed back: `v - minus < V < v + plus`.
|
||||
Furthermore it is shortest such one, i.e., there is no representation
|
||||
with less than `n` digits that is correctly rounded.
|
||||
|
||||
- It's closest to the original value: `abs(V - v) <= 10^(k-n) / 2`. Note that
|
||||
there might be two representations satisfying this uniqueness requirement,
|
||||
in which case some tie-breaking mechanism is used.
|
||||
|
||||
We will call this mode of operation as to the *shortest* mode. This mode is used
|
||||
when there is no additional constraint, and can be thought as a "natural" mode
|
||||
as it matches the ordinary intuition (it at least prints `0.1f32` as "0.1").
|
||||
|
||||
We have two more modes of operation closely related to each other. In these modes
|
||||
we are given either the number of significant digits `n` or the last-digit
|
||||
limitation `limit` (which determines the actual `n`), and we would like to get
|
||||
the representation `V = 0.d[0..n-1] * 10^k` such that:
|
||||
|
||||
- `d[0]` is non-zero, unless `n` was zero in which case only `k` is returned.
|
||||
|
||||
- It's closest to the original value: `abs(V - v) <= 10^(k-n) / 2`. Again,
|
||||
there might be some tie-breaking mechanism.
|
||||
|
||||
When `limit` is given but not `n`, we set `n` such that `k - n = limit`
|
||||
so that the last digit `d[n-1]` is scaled by `10^(k-n) = 10^limit`.
|
||||
If such `n` is negative, we clip it to zero so that we will only get `k`.
|
||||
We are also limited by the supplied buffer. This limitation is used to print
|
||||
the number up to given number of fractional digits without knowing
|
||||
the correct `k` beforehand.
|
||||
|
||||
We will call the mode of operation requiring `n` as to the *exact* mode,
|
||||
and one requiring `limit` as to the *fixed* mode. The exact mode is a subset of
|
||||
the fixed mode: the sufficiently large last-digit limitation will eventually fill
|
||||
the supplied buffer and let the algorithm to return.
|
||||
|
||||
# Implementation overview
|
||||
|
||||
It is easy to get the floating point printing correct but slow (Russ Cox has
|
||||
[demonstrated](http://research.swtch.com/ftoa) how it's easy), or incorrect but
|
||||
fast (naïve division and modulo). But it is surprisingly hard to print
|
||||
floating point numbers correctly *and* efficiently.
|
||||
|
||||
There are two classes of algorithms widely known to be correct.
|
||||
|
||||
- The "Dragon" family of algorithm is first described by Guy L. Steele Jr. and
|
||||
Jon L. White. They rely on the fixed-size big integer for their correctness.
|
||||
A slight improvement was found later, which is posthumously described by
|
||||
Robert G. Burger and R. Kent Dybvig. David Gay's `dtoa.c` routine is
|
||||
a popular implementation of this strategy.
|
||||
|
||||
- The "Grisu" family of algorithm is first described by Florian Loitsch.
|
||||
They use very cheap integer-only procedure to determine the close-to-correct
|
||||
representation which is at least guaranteed to be shortest. The variant,
|
||||
Grisu3, actively detects if the resulting representation is incorrect.
|
||||
|
||||
We implement both algorithms with necessary tweaks to suit our requirements.
|
||||
In particular, published literatures are short of the actual implementation
|
||||
difficulties like how to avoid arithmetic overflows. Each implementation,
|
||||
available in `strategy::dragon` and `strategy::grisu` respectively,
|
||||
extensively describes all necessary justifications and many proofs for them.
|
||||
(It is still difficult to follow though. You have been warned.)
|
||||
|
||||
Both implementations expose two public functions:
|
||||
|
||||
- `format_shortest(decoded, buf)`, which always needs at least
|
||||
`MAX_SIG_DIGITS` digits of buffer. Implements the shortest mode.
|
||||
|
||||
- `format_exact(decoded, buf, limit)`, which accepts as small as
|
||||
one digit of buffer. Implements exact and fixed modes.
|
||||
|
||||
They try to fill the `u8` buffer with digits and returns the number of digits
|
||||
written and the exponent `k`. They are total for all finite `f32` and `f64`
|
||||
inputs (Grisu internally falls back to Dragon if necessary).
|
||||
|
||||
The rendered digits are formatted into the actual string form with
|
||||
four functions:
|
||||
|
||||
- `to_shortest_str` prints the shortest representation, which can be padded by
|
||||
zeroes to make *at least* given number of fractional digits.
|
||||
|
||||
- `to_shortest_exp_str` prints the shortest representation, which can be
|
||||
padded by zeroes when its exponent is in the specified ranges,
|
||||
or can be printed in the exponential form such as `1.23e45`.
|
||||
|
||||
- `to_exact_exp_str` prints the exact representation with given number of
|
||||
digits in the exponential form.
|
||||
|
||||
- `to_exact_fixed_str` prints the fixed representation with *exactly*
|
||||
given number of fractional digits.
|
||||
|
||||
They all return a slice of preallocated `Part` array, which corresponds to
|
||||
the individual part of strings: a fixed string, a part of rendered digits,
|
||||
a number of zeroes or a small (`u16`) number. The caller is expected to
|
||||
provide a large enough buffer and `Part` array, and to assemble the final
|
||||
string from resulting `Part`s itself.
|
||||
|
||||
All algorithms and formatting functions are accompanied by extensive tests
|
||||
in `coretests::num::flt2dec` module. It also shows how to use individual
|
||||
functions.
|
||||
|
||||
*/
|
||||
|
||||
// while this is extensively documented, this is in principle private which is
|
||||
// only made public for testing. do not expose us.
|
||||
#![doc(hidden)]
|
||||
#![unstable(
|
||||
feature = "flt2dec",
|
||||
reason = "internal routines only exposed for testing",
|
||||
issue = "none"
|
||||
)]
|
||||
|
||||
pub use self::decoder::{decode, DecodableFloat, Decoded, FullDecoded};
|
||||
|
||||
use crate::mem::MaybeUninit;
|
||||
|
||||
pub mod decoder;
|
||||
pub mod estimator;
|
||||
|
||||
/// Digit-generation algorithms.
|
||||
pub mod strategy {
|
||||
pub mod dragon;
|
||||
pub mod grisu;
|
||||
}
|
||||
|
||||
/// The minimum size of buffer necessary for the shortest mode.
|
||||
///
|
||||
/// It is a bit non-trivial to derive, but this is one plus the maximal number of
|
||||
/// significant decimal digits from formatting algorithms with the shortest result.
|
||||
/// The exact formula is `ceil(# bits in mantissa * log_10 2 + 1)`.
|
||||
pub const MAX_SIG_DIGITS: usize = 17;
|
||||
|
||||
/// When `d` contains decimal digits, increase the last digit and propagate carry.
|
||||
/// Returns a next digit when it causes the length to change.
|
||||
#[doc(hidden)]
|
||||
pub fn round_up(d: &mut [u8]) -> Option<u8> {
|
||||
match d.iter().rposition(|&c| c != b'9') {
|
||||
Some(i) => {
|
||||
// d[i+1..n] is all nines
|
||||
d[i] += 1;
|
||||
for j in i + 1..d.len() {
|
||||
d[j] = b'0';
|
||||
}
|
||||
None
|
||||
}
|
||||
None if d.len() > 0 => {
|
||||
// 999..999 rounds to 1000..000 with an increased exponent
|
||||
d[0] = b'1';
|
||||
for j in 1..d.len() {
|
||||
d[j] = b'0';
|
||||
}
|
||||
Some(b'0')
|
||||
}
|
||||
None => {
|
||||
// an empty buffer rounds up (a bit strange but reasonable)
|
||||
Some(b'1')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Formatted parts.
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
||||
pub enum Part<'a> {
|
||||
/// Given number of zero digits.
|
||||
Zero(usize),
|
||||
/// A literal number up to 5 digits.
|
||||
Num(u16),
|
||||
/// A verbatim copy of given bytes.
|
||||
Copy(&'a [u8]),
|
||||
}
|
||||
|
||||
impl<'a> Part<'a> {
|
||||
/// Returns the exact byte length of given part.
|
||||
pub fn len(&self) -> usize {
|
||||
match *self {
|
||||
Part::Zero(nzeroes) => nzeroes,
|
||||
Part::Num(v) => {
|
||||
if v < 1_000 {
|
||||
if v < 10 {
|
||||
1
|
||||
} else if v < 100 {
|
||||
2
|
||||
} else {
|
||||
3
|
||||
}
|
||||
} else {
|
||||
if v < 10_000 { 4 } else { 5 }
|
||||
}
|
||||
}
|
||||
Part::Copy(buf) => buf.len(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Writes a part into the supplied buffer.
|
||||
/// Returns the number of written bytes, or `None` if the buffer is not enough.
|
||||
/// (It may still leave partially written bytes in the buffer; do not rely on that.)
|
||||
pub fn write(&self, out: &mut [u8]) -> Option<usize> {
|
||||
let len = self.len();
|
||||
if out.len() >= len {
|
||||
match *self {
|
||||
Part::Zero(nzeroes) => {
|
||||
for c in &mut out[..nzeroes] {
|
||||
*c = b'0';
|
||||
}
|
||||
}
|
||||
Part::Num(mut v) => {
|
||||
for c in out[..len].iter_mut().rev() {
|
||||
*c = b'0' + (v % 10) as u8;
|
||||
v /= 10;
|
||||
}
|
||||
}
|
||||
Part::Copy(buf) => {
|
||||
out[..buf.len()].copy_from_slice(buf);
|
||||
}
|
||||
}
|
||||
Some(len)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Formatted result containing one or more parts.
|
||||
/// This can be written to the byte buffer or converted to the allocated string.
|
||||
#[allow(missing_debug_implementations)]
|
||||
#[derive(Clone)]
|
||||
pub struct Formatted<'a> {
|
||||
/// A byte slice representing a sign, either `""`, `"-"` or `"+"`.
|
||||
pub sign: &'static str,
|
||||
/// Formatted parts to be rendered after a sign and optional zero padding.
|
||||
pub parts: &'a [Part<'a>],
|
||||
}
|
||||
|
||||
impl<'a> Formatted<'a> {
|
||||
/// Returns the exact byte length of combined formatted result.
|
||||
pub fn len(&self) -> usize {
|
||||
let mut len = self.sign.len();
|
||||
for part in self.parts {
|
||||
len += part.len();
|
||||
}
|
||||
len
|
||||
}
|
||||
|
||||
/// Writes all formatted parts into the supplied buffer.
|
||||
/// Returns the number of written bytes, or `None` if the buffer is not enough.
|
||||
/// (It may still leave partially written bytes in the buffer; do not rely on that.)
|
||||
pub fn write(&self, out: &mut [u8]) -> Option<usize> {
|
||||
if out.len() < self.sign.len() {
|
||||
return None;
|
||||
}
|
||||
out[..self.sign.len()].copy_from_slice(self.sign.as_bytes());
|
||||
|
||||
let mut written = self.sign.len();
|
||||
for part in self.parts {
|
||||
let len = part.write(&mut out[written..])?;
|
||||
written += len;
|
||||
}
|
||||
Some(written)
|
||||
}
|
||||
}
|
||||
|
||||
/// Formats given decimal digits `0.<...buf...> * 10^exp` into the decimal form
|
||||
/// with at least given number of fractional digits. The result is stored to
|
||||
/// the supplied parts array and a slice of written parts is returned.
|
||||
///
|
||||
/// `frac_digits` can be less than the number of actual fractional digits in `buf`;
|
||||
/// it will be ignored and full digits will be printed. It is only used to print
|
||||
/// additional zeroes after rendered digits. Thus `frac_digits` of 0 means that
|
||||
/// it will only print given digits and nothing else.
|
||||
fn digits_to_dec_str<'a>(
|
||||
buf: &'a [u8],
|
||||
exp: i16,
|
||||
frac_digits: usize,
|
||||
parts: &'a mut [MaybeUninit<Part<'a>>],
|
||||
) -> &'a [Part<'a>] {
|
||||
assert!(!buf.is_empty());
|
||||
assert!(buf[0] > b'0');
|
||||
assert!(parts.len() >= 4);
|
||||
|
||||
// if there is the restriction on the last digit position, `buf` is assumed to be
|
||||
// left-padded with the virtual zeroes. the number of virtual zeroes, `nzeroes`,
|
||||
// equals to `max(0, exp + frac_digits - buf.len())`, so that the position of
|
||||
// the last digit `exp - buf.len() - nzeroes` is no more than `-frac_digits`:
|
||||
//
|
||||
// |<-virtual->|
|
||||
// |<---- buf ---->| zeroes | exp
|
||||
// 0. 1 2 3 4 5 6 7 8 9 _ _ _ _ _ _ x 10
|
||||
// | | |
|
||||
// 10^exp 10^(exp-buf.len()) 10^(exp-buf.len()-nzeroes)
|
||||
//
|
||||
// `nzeroes` is individually calculated for each case in order to avoid overflow.
|
||||
|
||||
if exp <= 0 {
|
||||
// the decimal point is before rendered digits: [0.][000...000][1234][____]
|
||||
let minus_exp = -(exp as i32) as usize;
|
||||
parts[0] = MaybeUninit::new(Part::Copy(b"0."));
|
||||
parts[1] = MaybeUninit::new(Part::Zero(minus_exp));
|
||||
parts[2] = MaybeUninit::new(Part::Copy(buf));
|
||||
if frac_digits > buf.len() && frac_digits - buf.len() > minus_exp {
|
||||
parts[3] = MaybeUninit::new(Part::Zero((frac_digits - buf.len()) - minus_exp));
|
||||
// SAFETY: we just initialized the elements `..4`.
|
||||
unsafe { MaybeUninit::slice_assume_init_ref(&parts[..4]) }
|
||||
} else {
|
||||
// SAFETY: we just initialized the elements `..3`.
|
||||
unsafe { MaybeUninit::slice_assume_init_ref(&parts[..3]) }
|
||||
}
|
||||
} else {
|
||||
let exp = exp as usize;
|
||||
if exp < buf.len() {
|
||||
// the decimal point is inside rendered digits: [12][.][34][____]
|
||||
parts[0] = MaybeUninit::new(Part::Copy(&buf[..exp]));
|
||||
parts[1] = MaybeUninit::new(Part::Copy(b"."));
|
||||
parts[2] = MaybeUninit::new(Part::Copy(&buf[exp..]));
|
||||
if frac_digits > buf.len() - exp {
|
||||
parts[3] = MaybeUninit::new(Part::Zero(frac_digits - (buf.len() - exp)));
|
||||
// SAFETY: we just initialized the elements `..4`.
|
||||
unsafe { MaybeUninit::slice_assume_init_ref(&parts[..4]) }
|
||||
} else {
|
||||
// SAFETY: we just initialized the elements `..3`.
|
||||
unsafe { MaybeUninit::slice_assume_init_ref(&parts[..3]) }
|
||||
}
|
||||
} else {
|
||||
// the decimal point is after rendered digits: [1234][____0000] or [1234][__][.][__].
|
||||
parts[0] = MaybeUninit::new(Part::Copy(buf));
|
||||
parts[1] = MaybeUninit::new(Part::Zero(exp - buf.len()));
|
||||
if frac_digits > 0 {
|
||||
parts[2] = MaybeUninit::new(Part::Copy(b"."));
|
||||
parts[3] = MaybeUninit::new(Part::Zero(frac_digits));
|
||||
// SAFETY: we just initialized the elements `..4`.
|
||||
unsafe { MaybeUninit::slice_assume_init_ref(&parts[..4]) }
|
||||
} else {
|
||||
// SAFETY: we just initialized the elements `..2`.
|
||||
unsafe { MaybeUninit::slice_assume_init_ref(&parts[..2]) }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Formats the given decimal digits `0.<...buf...> * 10^exp` into the exponential
|
||||
/// form with at least the given number of significant digits. When `upper` is `true`,
|
||||
/// the exponent will be prefixed by `E`; otherwise that's `e`. The result is
|
||||
/// stored to the supplied parts array and a slice of written parts is returned.
|
||||
///
|
||||
/// `min_digits` can be less than the number of actual significant digits in `buf`;
|
||||
/// it will be ignored and full digits will be printed. It is only used to print
|
||||
/// additional zeroes after rendered digits. Thus, `min_digits == 0` means that
|
||||
/// it will only print the given digits and nothing else.
|
||||
fn digits_to_exp_str<'a>(
|
||||
buf: &'a [u8],
|
||||
exp: i16,
|
||||
min_ndigits: usize,
|
||||
upper: bool,
|
||||
parts: &'a mut [MaybeUninit<Part<'a>>],
|
||||
) -> &'a [Part<'a>] {
|
||||
assert!(!buf.is_empty());
|
||||
assert!(buf[0] > b'0');
|
||||
assert!(parts.len() >= 6);
|
||||
|
||||
let mut n = 0;
|
||||
|
||||
parts[n] = MaybeUninit::new(Part::Copy(&buf[..1]));
|
||||
n += 1;
|
||||
|
||||
if buf.len() > 1 || min_ndigits > 1 {
|
||||
parts[n] = MaybeUninit::new(Part::Copy(b"."));
|
||||
parts[n + 1] = MaybeUninit::new(Part::Copy(&buf[1..]));
|
||||
n += 2;
|
||||
if min_ndigits > buf.len() {
|
||||
parts[n] = MaybeUninit::new(Part::Zero(min_ndigits - buf.len()));
|
||||
n += 1;
|
||||
}
|
||||
}
|
||||
|
||||
// 0.1234 x 10^exp = 1.234 x 10^(exp-1)
|
||||
let exp = exp as i32 - 1; // avoid underflow when exp is i16::MIN
|
||||
if exp < 0 {
|
||||
parts[n] = MaybeUninit::new(Part::Copy(if upper { b"E-" } else { b"e-" }));
|
||||
parts[n + 1] = MaybeUninit::new(Part::Num(-exp as u16));
|
||||
} else {
|
||||
parts[n] = MaybeUninit::new(Part::Copy(if upper { b"E" } else { b"e" }));
|
||||
parts[n + 1] = MaybeUninit::new(Part::Num(exp as u16));
|
||||
}
|
||||
// SAFETY: we just initialized the elements `..n + 2`.
|
||||
unsafe { MaybeUninit::slice_assume_init_ref(&parts[..n + 2]) }
|
||||
}
|
||||
|
||||
/// Sign formatting options.
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
||||
pub enum Sign {
|
||||
/// Prints `-` only for the negative non-zero values.
|
||||
Minus, // -inf -1 0 0 1 inf nan
|
||||
/// Prints `-` only for any negative values (including the negative zero).
|
||||
MinusRaw, // -inf -1 -0 0 1 inf nan
|
||||
/// Prints `-` for the negative non-zero values, or `+` otherwise.
|
||||
MinusPlus, // -inf -1 +0 +0 +1 +inf nan
|
||||
/// Prints `-` for any negative values (including the negative zero), or `+` otherwise.
|
||||
MinusPlusRaw, // -inf -1 -0 +0 +1 +inf nan
|
||||
}
|
||||
|
||||
/// Returns the static byte string corresponding to the sign to be formatted.
|
||||
/// It can be either `""`, `"+"` or `"-"`.
|
||||
fn determine_sign(sign: Sign, decoded: &FullDecoded, negative: bool) -> &'static str {
|
||||
match (*decoded, sign) {
|
||||
(FullDecoded::Nan, _) => "",
|
||||
(FullDecoded::Zero, Sign::Minus) => "",
|
||||
(FullDecoded::Zero, Sign::MinusRaw) => {
|
||||
if negative {
|
||||
"-"
|
||||
} else {
|
||||
""
|
||||
}
|
||||
}
|
||||
(FullDecoded::Zero, Sign::MinusPlus) => "+",
|
||||
(FullDecoded::Zero, Sign::MinusPlusRaw) => {
|
||||
if negative {
|
||||
"-"
|
||||
} else {
|
||||
"+"
|
||||
}
|
||||
}
|
||||
(_, Sign::Minus | Sign::MinusRaw) => {
|
||||
if negative {
|
||||
"-"
|
||||
} else {
|
||||
""
|
||||
}
|
||||
}
|
||||
(_, Sign::MinusPlus | Sign::MinusPlusRaw) => {
|
||||
if negative {
|
||||
"-"
|
||||
} else {
|
||||
"+"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Formats the given floating point number into the decimal form with at least
|
||||
/// given number of fractional digits. The result is stored to the supplied parts
|
||||
/// array while utilizing given byte buffer as a scratch. `upper` is currently
|
||||
/// unused but left for the future decision to change the case of non-finite values,
|
||||
/// i.e., `inf` and `nan`. The first part to be rendered is always a `Part::Sign`
|
||||
/// (which can be an empty string if no sign is rendered).
|
||||
///
|
||||
/// `format_shortest` should be the underlying digit-generation function.
|
||||
/// It should return the part of the buffer that it initialized.
|
||||
/// You probably would want `strategy::grisu::format_shortest` for this.
|
||||
///
|
||||
/// `frac_digits` can be less than the number of actual fractional digits in `v`;
|
||||
/// it will be ignored and full digits will be printed. It is only used to print
|
||||
/// additional zeroes after rendered digits. Thus `frac_digits` of 0 means that
|
||||
/// it will only print given digits and nothing else.
|
||||
///
|
||||
/// The byte buffer should be at least `MAX_SIG_DIGITS` bytes long.
|
||||
/// There should be at least 4 parts available, due to the worst case like
|
||||
/// `[+][0.][0000][2][0000]` with `frac_digits = 10`.
|
||||
pub fn to_shortest_str<'a, T, F>(
|
||||
mut format_shortest: F,
|
||||
v: T,
|
||||
sign: Sign,
|
||||
frac_digits: usize,
|
||||
buf: &'a mut [MaybeUninit<u8>],
|
||||
parts: &'a mut [MaybeUninit<Part<'a>>],
|
||||
) -> Formatted<'a>
|
||||
where
|
||||
T: DecodableFloat,
|
||||
F: FnMut(&Decoded, &'a mut [MaybeUninit<u8>]) -> (&'a [u8], i16),
|
||||
{
|
||||
assert!(parts.len() >= 4);
|
||||
assert!(buf.len() >= MAX_SIG_DIGITS);
|
||||
|
||||
let (negative, full_decoded) = decode(v);
|
||||
let sign = determine_sign(sign, &full_decoded, negative);
|
||||
match full_decoded {
|
||||
FullDecoded::Nan => {
|
||||
parts[0] = MaybeUninit::new(Part::Copy(b"NaN"));
|
||||
// SAFETY: we just initialized the elements `..1`.
|
||||
Formatted { sign, parts: unsafe { MaybeUninit::slice_assume_init_ref(&parts[..1]) } }
|
||||
}
|
||||
FullDecoded::Infinite => {
|
||||
parts[0] = MaybeUninit::new(Part::Copy(b"inf"));
|
||||
// SAFETY: we just initialized the elements `..1`.
|
||||
Formatted { sign, parts: unsafe { MaybeUninit::slice_assume_init_ref(&parts[..1]) } }
|
||||
}
|
||||
FullDecoded::Zero => {
|
||||
if frac_digits > 0 {
|
||||
// [0.][0000]
|
||||
parts[0] = MaybeUninit::new(Part::Copy(b"0."));
|
||||
parts[1] = MaybeUninit::new(Part::Zero(frac_digits));
|
||||
Formatted {
|
||||
sign,
|
||||
// SAFETY: we just initialized the elements `..2`.
|
||||
parts: unsafe { MaybeUninit::slice_assume_init_ref(&parts[..2]) },
|
||||
}
|
||||
} else {
|
||||
parts[0] = MaybeUninit::new(Part::Copy(b"0"));
|
||||
Formatted {
|
||||
sign,
|
||||
// SAFETY: we just initialized the elements `..1`.
|
||||
parts: unsafe { MaybeUninit::slice_assume_init_ref(&parts[..1]) },
|
||||
}
|
||||
}
|
||||
}
|
||||
FullDecoded::Finite(ref decoded) => {
|
||||
let (buf, exp) = format_shortest(decoded, buf);
|
||||
Formatted { sign, parts: digits_to_dec_str(buf, exp, frac_digits, parts) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Formats the given floating point number into the decimal form or
|
||||
/// the exponential form, depending on the resulting exponent. The result is
|
||||
/// stored to the supplied parts array while utilizing given byte buffer
|
||||
/// as a scratch. `upper` is used to determine the case of non-finite values
|
||||
/// (`inf` and `nan`) or the case of the exponent prefix (`e` or `E`).
|
||||
/// The first part to be rendered is always a `Part::Sign` (which can be
|
||||
/// an empty string if no sign is rendered).
|
||||
///
|
||||
/// `format_shortest` should be the underlying digit-generation function.
|
||||
/// It should return the part of the buffer that it initialized.
|
||||
/// You probably would want `strategy::grisu::format_shortest` for this.
|
||||
///
|
||||
/// The `dec_bounds` is a tuple `(lo, hi)` such that the number is formatted
|
||||
/// as decimal only when `10^lo <= V < 10^hi`. Note that this is the *apparent* `V`
|
||||
/// instead of the actual `v`! Thus any printed exponent in the exponential form
|
||||
/// cannot be in this range, avoiding any confusion.
|
||||
///
|
||||
/// The byte buffer should be at least `MAX_SIG_DIGITS` bytes long.
|
||||
/// There should be at least 6 parts available, due to the worst case like
|
||||
/// `[+][1][.][2345][e][-][6]`.
|
||||
pub fn to_shortest_exp_str<'a, T, F>(
|
||||
mut format_shortest: F,
|
||||
v: T,
|
||||
sign: Sign,
|
||||
dec_bounds: (i16, i16),
|
||||
upper: bool,
|
||||
buf: &'a mut [MaybeUninit<u8>],
|
||||
parts: &'a mut [MaybeUninit<Part<'a>>],
|
||||
) -> Formatted<'a>
|
||||
where
|
||||
T: DecodableFloat,
|
||||
F: FnMut(&Decoded, &'a mut [MaybeUninit<u8>]) -> (&'a [u8], i16),
|
||||
{
|
||||
assert!(parts.len() >= 6);
|
||||
assert!(buf.len() >= MAX_SIG_DIGITS);
|
||||
assert!(dec_bounds.0 <= dec_bounds.1);
|
||||
|
||||
let (negative, full_decoded) = decode(v);
|
||||
let sign = determine_sign(sign, &full_decoded, negative);
|
||||
match full_decoded {
|
||||
FullDecoded::Nan => {
|
||||
parts[0] = MaybeUninit::new(Part::Copy(b"NaN"));
|
||||
// SAFETY: we just initialized the elements `..1`.
|
||||
Formatted { sign, parts: unsafe { MaybeUninit::slice_assume_init_ref(&parts[..1]) } }
|
||||
}
|
||||
FullDecoded::Infinite => {
|
||||
parts[0] = MaybeUninit::new(Part::Copy(b"inf"));
|
||||
// SAFETY: we just initialized the elements `..1`.
|
||||
Formatted { sign, parts: unsafe { MaybeUninit::slice_assume_init_ref(&parts[..1]) } }
|
||||
}
|
||||
FullDecoded::Zero => {
|
||||
parts[0] = if dec_bounds.0 <= 0 && 0 < dec_bounds.1 {
|
||||
MaybeUninit::new(Part::Copy(b"0"))
|
||||
} else {
|
||||
MaybeUninit::new(Part::Copy(if upper { b"0E0" } else { b"0e0" }))
|
||||
};
|
||||
// SAFETY: we just initialized the elements `..1`.
|
||||
Formatted { sign, parts: unsafe { MaybeUninit::slice_assume_init_ref(&parts[..1]) } }
|
||||
}
|
||||
FullDecoded::Finite(ref decoded) => {
|
||||
let (buf, exp) = format_shortest(decoded, buf);
|
||||
let vis_exp = exp as i32 - 1;
|
||||
let parts = if dec_bounds.0 as i32 <= vis_exp && vis_exp < dec_bounds.1 as i32 {
|
||||
digits_to_dec_str(buf, exp, 0, parts)
|
||||
} else {
|
||||
digits_to_exp_str(buf, exp, 0, upper, parts)
|
||||
};
|
||||
Formatted { sign, parts }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a rather crude approximation (upper bound) for the maximum buffer size
|
||||
/// calculated from the given decoded exponent.
|
||||
///
|
||||
/// The exact limit is:
|
||||
///
|
||||
/// - when `exp < 0`, the maximum length is `ceil(log_10 (5^-exp * (2^64 - 1)))`.
|
||||
/// - when `exp >= 0`, the maximum length is `ceil(log_10 (2^exp * (2^64 - 1)))`.
|
||||
///
|
||||
/// `ceil(log_10 (x^exp * (2^64 - 1)))` is less than `ceil(log_10 (2^64 - 1)) +
|
||||
/// ceil(exp * log_10 x)`, which is in turn less than `20 + (1 + exp * log_10 x)`.
|
||||
/// We use the facts that `log_10 2 < 5/16` and `log_10 5 < 12/16`, which is
|
||||
/// enough for our purposes.
|
||||
///
|
||||
/// Why do we need this? `format_exact` functions will fill the entire buffer
|
||||
/// unless limited by the last digit restriction, but it is possible that
|
||||
/// the number of digits requested is ridiculously large (say, 30,000 digits).
|
||||
/// The vast majority of buffer will be filled with zeroes, so we don't want to
|
||||
/// allocate all the buffer beforehand. Consequently, for any given arguments,
|
||||
/// 826 bytes of buffer should be sufficient for `f64`. Compare this with
|
||||
/// the actual number for the worst case: 770 bytes (when `exp = -1074`).
|
||||
fn estimate_max_buf_len(exp: i16) -> usize {
|
||||
21 + ((if exp < 0 { -12 } else { 5 } * exp as i32) as usize >> 4)
|
||||
}
|
||||
|
||||
/// Formats given floating point number into the exponential form with
|
||||
/// exactly given number of significant digits. The result is stored to
|
||||
/// the supplied parts array while utilizing given byte buffer as a scratch.
|
||||
/// `upper` is used to determine the case of the exponent prefix (`e` or `E`).
|
||||
/// The first part to be rendered is always a `Part::Sign` (which can be
|
||||
/// an empty string if no sign is rendered).
|
||||
///
|
||||
/// `format_exact` should be the underlying digit-generation function.
|
||||
/// It should return the part of the buffer that it initialized.
|
||||
/// You probably would want `strategy::grisu::format_exact` for this.
|
||||
///
|
||||
/// The byte buffer should be at least `ndigits` bytes long unless `ndigits` is
|
||||
/// so large that only the fixed number of digits will be ever written.
|
||||
/// (The tipping point for `f64` is about 800, so 1000 bytes should be enough.)
|
||||
/// There should be at least 6 parts available, due to the worst case like
|
||||
/// `[+][1][.][2345][e][-][6]`.
|
||||
pub fn to_exact_exp_str<'a, T, F>(
|
||||
mut format_exact: F,
|
||||
v: T,
|
||||
sign: Sign,
|
||||
ndigits: usize,
|
||||
upper: bool,
|
||||
buf: &'a mut [MaybeUninit<u8>],
|
||||
parts: &'a mut [MaybeUninit<Part<'a>>],
|
||||
) -> Formatted<'a>
|
||||
where
|
||||
T: DecodableFloat,
|
||||
F: FnMut(&Decoded, &'a mut [MaybeUninit<u8>], i16) -> (&'a [u8], i16),
|
||||
{
|
||||
assert!(parts.len() >= 6);
|
||||
assert!(ndigits > 0);
|
||||
|
||||
let (negative, full_decoded) = decode(v);
|
||||
let sign = determine_sign(sign, &full_decoded, negative);
|
||||
match full_decoded {
|
||||
FullDecoded::Nan => {
|
||||
parts[0] = MaybeUninit::new(Part::Copy(b"NaN"));
|
||||
// SAFETY: we just initialized the elements `..1`.
|
||||
Formatted { sign, parts: unsafe { MaybeUninit::slice_assume_init_ref(&parts[..1]) } }
|
||||
}
|
||||
FullDecoded::Infinite => {
|
||||
parts[0] = MaybeUninit::new(Part::Copy(b"inf"));
|
||||
// SAFETY: we just initialized the elements `..1`.
|
||||
Formatted { sign, parts: unsafe { MaybeUninit::slice_assume_init_ref(&parts[..1]) } }
|
||||
}
|
||||
FullDecoded::Zero => {
|
||||
if ndigits > 1 {
|
||||
// [0.][0000][e0]
|
||||
parts[0] = MaybeUninit::new(Part::Copy(b"0."));
|
||||
parts[1] = MaybeUninit::new(Part::Zero(ndigits - 1));
|
||||
parts[2] = MaybeUninit::new(Part::Copy(if upper { b"E0" } else { b"e0" }));
|
||||
Formatted {
|
||||
sign,
|
||||
// SAFETY: we just initialized the elements `..3`.
|
||||
parts: unsafe { MaybeUninit::slice_assume_init_ref(&parts[..3]) },
|
||||
}
|
||||
} else {
|
||||
parts[0] = MaybeUninit::new(Part::Copy(if upper { b"0E0" } else { b"0e0" }));
|
||||
Formatted {
|
||||
sign,
|
||||
// SAFETY: we just initialized the elements `..1`.
|
||||
parts: unsafe { MaybeUninit::slice_assume_init_ref(&parts[..1]) },
|
||||
}
|
||||
}
|
||||
}
|
||||
FullDecoded::Finite(ref decoded) => {
|
||||
let maxlen = estimate_max_buf_len(decoded.exp);
|
||||
assert!(buf.len() >= ndigits || buf.len() >= maxlen);
|
||||
|
||||
let trunc = if ndigits < maxlen { ndigits } else { maxlen };
|
||||
let (buf, exp) = format_exact(decoded, &mut buf[..trunc], i16::MIN);
|
||||
Formatted { sign, parts: digits_to_exp_str(buf, exp, ndigits, upper, parts) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Formats given floating point number into the decimal form with exactly
|
||||
/// given number of fractional digits. The result is stored to the supplied parts
|
||||
/// array while utilizing given byte buffer as a scratch. `upper` is currently
|
||||
/// unused but left for the future decision to change the case of non-finite values,
|
||||
/// i.e., `inf` and `nan`. The first part to be rendered is always a `Part::Sign`
|
||||
/// (which can be an empty string if no sign is rendered).
|
||||
///
|
||||
/// `format_exact` should be the underlying digit-generation function.
|
||||
/// It should return the part of the buffer that it initialized.
|
||||
/// You probably would want `strategy::grisu::format_exact` for this.
|
||||
///
|
||||
/// The byte buffer should be enough for the output unless `frac_digits` is
|
||||
/// so large that only the fixed number of digits will be ever written.
|
||||
/// (The tipping point for `f64` is about 800, and 1000 bytes should be enough.)
|
||||
/// There should be at least 4 parts available, due to the worst case like
|
||||
/// `[+][0.][0000][2][0000]` with `frac_digits = 10`.
|
||||
pub fn to_exact_fixed_str<'a, T, F>(
|
||||
mut format_exact: F,
|
||||
v: T,
|
||||
sign: Sign,
|
||||
frac_digits: usize,
|
||||
buf: &'a mut [MaybeUninit<u8>],
|
||||
parts: &'a mut [MaybeUninit<Part<'a>>],
|
||||
) -> Formatted<'a>
|
||||
where
|
||||
T: DecodableFloat,
|
||||
F: FnMut(&Decoded, &'a mut [MaybeUninit<u8>], i16) -> (&'a [u8], i16),
|
||||
{
|
||||
assert!(parts.len() >= 4);
|
||||
|
||||
let (negative, full_decoded) = decode(v);
|
||||
let sign = determine_sign(sign, &full_decoded, negative);
|
||||
match full_decoded {
|
||||
FullDecoded::Nan => {
|
||||
parts[0] = MaybeUninit::new(Part::Copy(b"NaN"));
|
||||
// SAFETY: we just initialized the elements `..1`.
|
||||
Formatted { sign, parts: unsafe { MaybeUninit::slice_assume_init_ref(&parts[..1]) } }
|
||||
}
|
||||
FullDecoded::Infinite => {
|
||||
parts[0] = MaybeUninit::new(Part::Copy(b"inf"));
|
||||
// SAFETY: we just initialized the elements `..1`.
|
||||
Formatted { sign, parts: unsafe { MaybeUninit::slice_assume_init_ref(&parts[..1]) } }
|
||||
}
|
||||
FullDecoded::Zero => {
|
||||
if frac_digits > 0 {
|
||||
// [0.][0000]
|
||||
parts[0] = MaybeUninit::new(Part::Copy(b"0."));
|
||||
parts[1] = MaybeUninit::new(Part::Zero(frac_digits));
|
||||
Formatted {
|
||||
sign,
|
||||
// SAFETY: we just initialized the elements `..2`.
|
||||
parts: unsafe { MaybeUninit::slice_assume_init_ref(&parts[..2]) },
|
||||
}
|
||||
} else {
|
||||
parts[0] = MaybeUninit::new(Part::Copy(b"0"));
|
||||
Formatted {
|
||||
sign,
|
||||
// SAFETY: we just initialized the elements `..1`.
|
||||
parts: unsafe { MaybeUninit::slice_assume_init_ref(&parts[..1]) },
|
||||
}
|
||||
}
|
||||
}
|
||||
FullDecoded::Finite(ref decoded) => {
|
||||
let maxlen = estimate_max_buf_len(decoded.exp);
|
||||
assert!(buf.len() >= maxlen);
|
||||
|
||||
// it *is* possible that `frac_digits` is ridiculously large.
|
||||
// `format_exact` will end rendering digits much earlier in this case,
|
||||
// because we are strictly limited by `maxlen`.
|
||||
let limit = if frac_digits < 0x8000 { -(frac_digits as i16) } else { i16::MIN };
|
||||
let (buf, exp) = format_exact(decoded, &mut buf[..maxlen], limit);
|
||||
if exp <= limit {
|
||||
// the restriction couldn't been met, so this should render like zero no matter
|
||||
// `exp` was. this does not include the case that the restriction has been met
|
||||
// only after the final rounding-up; it's a regular case with `exp = limit + 1`.
|
||||
debug_assert_eq!(buf.len(), 0);
|
||||
if frac_digits > 0 {
|
||||
// [0.][0000]
|
||||
parts[0] = MaybeUninit::new(Part::Copy(b"0."));
|
||||
parts[1] = MaybeUninit::new(Part::Zero(frac_digits));
|
||||
Formatted {
|
||||
sign,
|
||||
// SAFETY: we just initialized the elements `..2`.
|
||||
parts: unsafe { MaybeUninit::slice_assume_init_ref(&parts[..2]) },
|
||||
}
|
||||
} else {
|
||||
parts[0] = MaybeUninit::new(Part::Copy(b"0"));
|
||||
Formatted {
|
||||
sign,
|
||||
// SAFETY: we just initialized the elements `..1`.
|
||||
parts: unsafe { MaybeUninit::slice_assume_init_ref(&parts[..1]) },
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Formatted { sign, parts: digits_to_dec_str(buf, exp, frac_digits, parts) }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
388
libgrust/rustc-lib/core/src/num/flt2dec/strategy/dragon.rs
Normal file
388
libgrust/rustc-lib/core/src/num/flt2dec/strategy/dragon.rs
Normal file
@@ -0,0 +1,388 @@
|
||||
//! Almost direct (but slightly optimized) Rust translation of Figure 3 of "Printing
|
||||
//! Floating-Point Numbers Quickly and Accurately"[^1].
|
||||
//!
|
||||
//! [^1]: Burger, R. G. and Dybvig, R. K. 1996. Printing floating-point numbers
|
||||
//! quickly and accurately. SIGPLAN Not. 31, 5 (May. 1996), 108-116.
|
||||
|
||||
use crate::cmp::Ordering;
|
||||
use crate::mem::MaybeUninit;
|
||||
|
||||
use crate::num::bignum::Big32x40 as Big;
|
||||
use crate::num::bignum::Digit32 as Digit;
|
||||
use crate::num::flt2dec::estimator::estimate_scaling_factor;
|
||||
use crate::num::flt2dec::{round_up, Decoded, MAX_SIG_DIGITS};
|
||||
|
||||
static POW10: [Digit; 10] =
|
||||
[1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000];
|
||||
static TWOPOW10: [Digit; 10] =
|
||||
[2, 20, 200, 2000, 20000, 200000, 2000000, 20000000, 200000000, 2000000000];
|
||||
|
||||
// precalculated arrays of `Digit`s for 10^(2^n)
|
||||
static POW10TO16: [Digit; 2] = [0x6fc10000, 0x2386f2];
|
||||
static POW10TO32: [Digit; 4] = [0, 0x85acef81, 0x2d6d415b, 0x4ee];
|
||||
static POW10TO64: [Digit; 7] = [0, 0, 0xbf6a1f01, 0x6e38ed64, 0xdaa797ed, 0xe93ff9f4, 0x184f03];
|
||||
static POW10TO128: [Digit; 14] = [
|
||||
0, 0, 0, 0, 0x2e953e01, 0x3df9909, 0xf1538fd, 0x2374e42f, 0xd3cff5ec, 0xc404dc08, 0xbccdb0da,
|
||||
0xa6337f19, 0xe91f2603, 0x24e,
|
||||
];
|
||||
static POW10TO256: [Digit; 27] = [
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0x982e7c01, 0xbed3875b, 0xd8d99f72, 0x12152f87, 0x6bde50c6, 0xcf4a6e70,
|
||||
0xd595d80f, 0x26b2716e, 0xadc666b0, 0x1d153624, 0x3c42d35a, 0x63ff540e, 0xcc5573c0, 0x65f9ef17,
|
||||
0x55bc28f2, 0x80dcc7f7, 0xf46eeddc, 0x5fdcefce, 0x553f7,
|
||||
];
|
||||
|
||||
#[doc(hidden)]
|
||||
pub fn mul_pow10(x: &mut Big, n: usize) -> &mut Big {
|
||||
debug_assert!(n < 512);
|
||||
if n & 7 != 0 {
|
||||
x.mul_small(POW10[n & 7]);
|
||||
}
|
||||
if n & 8 != 0 {
|
||||
x.mul_small(POW10[8]);
|
||||
}
|
||||
if n & 16 != 0 {
|
||||
x.mul_digits(&POW10TO16);
|
||||
}
|
||||
if n & 32 != 0 {
|
||||
x.mul_digits(&POW10TO32);
|
||||
}
|
||||
if n & 64 != 0 {
|
||||
x.mul_digits(&POW10TO64);
|
||||
}
|
||||
if n & 128 != 0 {
|
||||
x.mul_digits(&POW10TO128);
|
||||
}
|
||||
if n & 256 != 0 {
|
||||
x.mul_digits(&POW10TO256);
|
||||
}
|
||||
x
|
||||
}
|
||||
|
||||
fn div_2pow10(x: &mut Big, mut n: usize) -> &mut Big {
|
||||
let largest = POW10.len() - 1;
|
||||
while n > largest {
|
||||
x.div_rem_small(POW10[largest]);
|
||||
n -= largest;
|
||||
}
|
||||
x.div_rem_small(TWOPOW10[n]);
|
||||
x
|
||||
}
|
||||
|
||||
// only usable when `x < 16 * scale`; `scaleN` should be `scale.mul_small(N)`
|
||||
fn div_rem_upto_16<'a>(
|
||||
x: &'a mut Big,
|
||||
scale: &Big,
|
||||
scale2: &Big,
|
||||
scale4: &Big,
|
||||
scale8: &Big,
|
||||
) -> (u8, &'a mut Big) {
|
||||
let mut d = 0;
|
||||
if *x >= *scale8 {
|
||||
x.sub(scale8);
|
||||
d += 8;
|
||||
}
|
||||
if *x >= *scale4 {
|
||||
x.sub(scale4);
|
||||
d += 4;
|
||||
}
|
||||
if *x >= *scale2 {
|
||||
x.sub(scale2);
|
||||
d += 2;
|
||||
}
|
||||
if *x >= *scale {
|
||||
x.sub(scale);
|
||||
d += 1;
|
||||
}
|
||||
debug_assert!(*x < *scale);
|
||||
(d, x)
|
||||
}
|
||||
|
||||
/// The shortest mode implementation for Dragon.
|
||||
pub fn format_shortest<'a>(
|
||||
d: &Decoded,
|
||||
buf: &'a mut [MaybeUninit<u8>],
|
||||
) -> (/*digits*/ &'a [u8], /*exp*/ i16) {
|
||||
// the number `v` to format is known to be:
|
||||
// - equal to `mant * 2^exp`;
|
||||
// - preceded by `(mant - 2 * minus) * 2^exp` in the original type; and
|
||||
// - followed by `(mant + 2 * plus) * 2^exp` in the original type.
|
||||
//
|
||||
// obviously, `minus` and `plus` cannot be zero. (for infinities, we use out-of-range values.)
|
||||
// also we assume that at least one digit is generated, i.e., `mant` cannot be zero too.
|
||||
//
|
||||
// this also means that any number between `low = (mant - minus) * 2^exp` and
|
||||
// `high = (mant + plus) * 2^exp` will map to this exact floating point number,
|
||||
// with bounds included when the original mantissa was even (i.e., `!mant_was_odd`).
|
||||
|
||||
assert!(d.mant > 0);
|
||||
assert!(d.minus > 0);
|
||||
assert!(d.plus > 0);
|
||||
assert!(d.mant.checked_add(d.plus).is_some());
|
||||
assert!(d.mant.checked_sub(d.minus).is_some());
|
||||
assert!(buf.len() >= MAX_SIG_DIGITS);
|
||||
|
||||
// `a.cmp(&b) < rounding` is `if d.inclusive {a <= b} else {a < b}`
|
||||
let rounding = if d.inclusive { Ordering::Greater } else { Ordering::Equal };
|
||||
|
||||
// estimate `k_0` from original inputs satisfying `10^(k_0-1) < high <= 10^(k_0+1)`.
|
||||
// the tight bound `k` satisfying `10^(k-1) < high <= 10^k` is calculated later.
|
||||
let mut k = estimate_scaling_factor(d.mant + d.plus, d.exp);
|
||||
|
||||
// convert `{mant, plus, minus} * 2^exp` into the fractional form so that:
|
||||
// - `v = mant / scale`
|
||||
// - `low = (mant - minus) / scale`
|
||||
// - `high = (mant + plus) / scale`
|
||||
let mut mant = Big::from_u64(d.mant);
|
||||
let mut minus = Big::from_u64(d.minus);
|
||||
let mut plus = Big::from_u64(d.plus);
|
||||
let mut scale = Big::from_small(1);
|
||||
if d.exp < 0 {
|
||||
scale.mul_pow2(-d.exp as usize);
|
||||
} else {
|
||||
mant.mul_pow2(d.exp as usize);
|
||||
minus.mul_pow2(d.exp as usize);
|
||||
plus.mul_pow2(d.exp as usize);
|
||||
}
|
||||
|
||||
// divide `mant` by `10^k`. now `scale / 10 < mant + plus <= scale * 10`.
|
||||
if k >= 0 {
|
||||
mul_pow10(&mut scale, k as usize);
|
||||
} else {
|
||||
mul_pow10(&mut mant, -k as usize);
|
||||
mul_pow10(&mut minus, -k as usize);
|
||||
mul_pow10(&mut plus, -k as usize);
|
||||
}
|
||||
|
||||
// fixup when `mant + plus > scale` (or `>=`).
|
||||
// we are not actually modifying `scale`, since we can skip the initial multiplication instead.
|
||||
// now `scale < mant + plus <= scale * 10` and we are ready to generate digits.
|
||||
//
|
||||
// note that `d[0]` *can* be zero, when `scale - plus < mant < scale`.
|
||||
// in this case rounding-up condition (`up` below) will be triggered immediately.
|
||||
if scale.cmp(mant.clone().add(&plus)) < rounding {
|
||||
// equivalent to scaling `scale` by 10
|
||||
k += 1;
|
||||
} else {
|
||||
mant.mul_small(10);
|
||||
minus.mul_small(10);
|
||||
plus.mul_small(10);
|
||||
}
|
||||
|
||||
// cache `(2, 4, 8) * scale` for digit generation.
|
||||
let mut scale2 = scale.clone();
|
||||
scale2.mul_pow2(1);
|
||||
let mut scale4 = scale.clone();
|
||||
scale4.mul_pow2(2);
|
||||
let mut scale8 = scale.clone();
|
||||
scale8.mul_pow2(3);
|
||||
|
||||
let mut down;
|
||||
let mut up;
|
||||
let mut i = 0;
|
||||
loop {
|
||||
// invariants, where `d[0..n-1]` are digits generated so far:
|
||||
// - `v = mant / scale * 10^(k-n-1) + d[0..n-1] * 10^(k-n)`
|
||||
// - `v - low = minus / scale * 10^(k-n-1)`
|
||||
// - `high - v = plus / scale * 10^(k-n-1)`
|
||||
// - `(mant + plus) / scale <= 10` (thus `mant / scale < 10`)
|
||||
// where `d[i..j]` is a shorthand for `d[i] * 10^(j-i) + ... + d[j-1] * 10 + d[j]`.
|
||||
|
||||
// generate one digit: `d[n] = floor(mant / scale) < 10`.
|
||||
let (d, _) = div_rem_upto_16(&mut mant, &scale, &scale2, &scale4, &scale8);
|
||||
debug_assert!(d < 10);
|
||||
buf[i] = MaybeUninit::new(b'0' + d);
|
||||
i += 1;
|
||||
|
||||
// this is a simplified description of the modified Dragon algorithm.
|
||||
// many intermediate derivations and completeness arguments are omitted for convenience.
|
||||
//
|
||||
// start with modified invariants, as we've updated `n`:
|
||||
// - `v = mant / scale * 10^(k-n) + d[0..n-1] * 10^(k-n)`
|
||||
// - `v - low = minus / scale * 10^(k-n)`
|
||||
// - `high - v = plus / scale * 10^(k-n)`
|
||||
//
|
||||
// assume that `d[0..n-1]` is the shortest representation between `low` and `high`,
|
||||
// i.e., `d[0..n-1]` satisfies both of the following but `d[0..n-2]` doesn't:
|
||||
// - `low < d[0..n-1] * 10^(k-n) < high` (bijectivity: digits round to `v`); and
|
||||
// - `abs(v / 10^(k-n) - d[0..n-1]) <= 1/2` (the last digit is correct).
|
||||
//
|
||||
// the second condition simplifies to `2 * mant <= scale`.
|
||||
// solving invariants in terms of `mant`, `low` and `high` yields
|
||||
// a simpler version of the first condition: `-plus < mant < minus`.
|
||||
// since `-plus < 0 <= mant`, we have the correct shortest representation
|
||||
// when `mant < minus` and `2 * mant <= scale`.
|
||||
// (the former becomes `mant <= minus` when the original mantissa is even.)
|
||||
//
|
||||
// when the second doesn't hold (`2 * mant > scale`), we need to increase the last digit.
|
||||
// this is enough for restoring that condition: we already know that
|
||||
// the digit generation guarantees `0 <= v / 10^(k-n) - d[0..n-1] < 1`.
|
||||
// in this case, the first condition becomes `-plus < mant - scale < minus`.
|
||||
// since `mant < scale` after the generation, we have `scale < mant + plus`.
|
||||
// (again, this becomes `scale <= mant + plus` when the original mantissa is even.)
|
||||
//
|
||||
// in short:
|
||||
// - stop and round `down` (keep digits as is) when `mant < minus` (or `<=`).
|
||||
// - stop and round `up` (increase the last digit) when `scale < mant + plus` (or `<=`).
|
||||
// - keep generating otherwise.
|
||||
down = mant.cmp(&minus) < rounding;
|
||||
up = scale.cmp(mant.clone().add(&plus)) < rounding;
|
||||
if down || up {
|
||||
break;
|
||||
} // we have the shortest representation, proceed to the rounding
|
||||
|
||||
// restore the invariants.
|
||||
// this makes the algorithm always terminating: `minus` and `plus` always increases,
|
||||
// but `mant` is clipped modulo `scale` and `scale` is fixed.
|
||||
mant.mul_small(10);
|
||||
minus.mul_small(10);
|
||||
plus.mul_small(10);
|
||||
}
|
||||
|
||||
// rounding up happens when
|
||||
// i) only the rounding-up condition was triggered, or
|
||||
// ii) both conditions were triggered and tie breaking prefers rounding up.
|
||||
if up && (!down || *mant.mul_pow2(1) >= scale) {
|
||||
// if rounding up changes the length, the exponent should also change.
|
||||
// it seems that this condition is very hard to satisfy (possibly impossible),
|
||||
// but we are just being safe and consistent here.
|
||||
// SAFETY: we initialized that memory above.
|
||||
if let Some(c) = round_up(unsafe { MaybeUninit::slice_assume_init_mut(&mut buf[..i]) }) {
|
||||
buf[i] = MaybeUninit::new(c);
|
||||
i += 1;
|
||||
k += 1;
|
||||
}
|
||||
}
|
||||
|
||||
// SAFETY: we initialized that memory above.
|
||||
(unsafe { MaybeUninit::slice_assume_init_ref(&buf[..i]) }, k)
|
||||
}
|
||||
|
||||
/// The exact and fixed mode implementation for Dragon.
|
||||
pub fn format_exact<'a>(
|
||||
d: &Decoded,
|
||||
buf: &'a mut [MaybeUninit<u8>],
|
||||
limit: i16,
|
||||
) -> (/*digits*/ &'a [u8], /*exp*/ i16) {
|
||||
assert!(d.mant > 0);
|
||||
assert!(d.minus > 0);
|
||||
assert!(d.plus > 0);
|
||||
assert!(d.mant.checked_add(d.plus).is_some());
|
||||
assert!(d.mant.checked_sub(d.minus).is_some());
|
||||
|
||||
// estimate `k_0` from original inputs satisfying `10^(k_0-1) < v <= 10^(k_0+1)`.
|
||||
let mut k = estimate_scaling_factor(d.mant, d.exp);
|
||||
|
||||
// `v = mant / scale`.
|
||||
let mut mant = Big::from_u64(d.mant);
|
||||
let mut scale = Big::from_small(1);
|
||||
if d.exp < 0 {
|
||||
scale.mul_pow2(-d.exp as usize);
|
||||
} else {
|
||||
mant.mul_pow2(d.exp as usize);
|
||||
}
|
||||
|
||||
// divide `mant` by `10^k`. now `scale / 10 < mant <= scale * 10`.
|
||||
if k >= 0 {
|
||||
mul_pow10(&mut scale, k as usize);
|
||||
} else {
|
||||
mul_pow10(&mut mant, -k as usize);
|
||||
}
|
||||
|
||||
// fixup when `mant + plus >= scale`, where `plus / scale = 10^-buf.len() / 2`.
|
||||
// in order to keep the fixed-size bignum, we actually use `mant + floor(plus) >= scale`.
|
||||
// we are not actually modifying `scale`, since we can skip the initial multiplication instead.
|
||||
// again with the shortest algorithm, `d[0]` can be zero but will be eventually rounded up.
|
||||
if *div_2pow10(&mut scale.clone(), buf.len()).add(&mant) >= scale {
|
||||
// equivalent to scaling `scale` by 10
|
||||
k += 1;
|
||||
} else {
|
||||
mant.mul_small(10);
|
||||
}
|
||||
|
||||
// if we are working with the last-digit limitation, we need to shorten the buffer
|
||||
// before the actual rendering in order to avoid double rounding.
|
||||
// note that we have to enlarge the buffer again when rounding up happens!
|
||||
let mut len = if k < limit {
|
||||
// oops, we cannot even produce *one* digit.
|
||||
// this is possible when, say, we've got something like 9.5 and it's being rounded to 10.
|
||||
// we return an empty buffer, with an exception of the later rounding-up case
|
||||
// which occurs when `k == limit` and has to produce exactly one digit.
|
||||
0
|
||||
} else if ((k as i32 - limit as i32) as usize) < buf.len() {
|
||||
(k - limit) as usize
|
||||
} else {
|
||||
buf.len()
|
||||
};
|
||||
|
||||
if len > 0 {
|
||||
// cache `(2, 4, 8) * scale` for digit generation.
|
||||
// (this can be expensive, so do not calculate them when the buffer is empty.)
|
||||
let mut scale2 = scale.clone();
|
||||
scale2.mul_pow2(1);
|
||||
let mut scale4 = scale.clone();
|
||||
scale4.mul_pow2(2);
|
||||
let mut scale8 = scale.clone();
|
||||
scale8.mul_pow2(3);
|
||||
|
||||
for i in 0..len {
|
||||
if mant.is_zero() {
|
||||
// following digits are all zeroes, we stop here
|
||||
// do *not* try to perform rounding! rather, fill remaining digits.
|
||||
for c in &mut buf[i..len] {
|
||||
*c = MaybeUninit::new(b'0');
|
||||
}
|
||||
// SAFETY: we initialized that memory above.
|
||||
return (unsafe { MaybeUninit::slice_assume_init_ref(&buf[..len]) }, k);
|
||||
}
|
||||
|
||||
let mut d = 0;
|
||||
if mant >= scale8 {
|
||||
mant.sub(&scale8);
|
||||
d += 8;
|
||||
}
|
||||
if mant >= scale4 {
|
||||
mant.sub(&scale4);
|
||||
d += 4;
|
||||
}
|
||||
if mant >= scale2 {
|
||||
mant.sub(&scale2);
|
||||
d += 2;
|
||||
}
|
||||
if mant >= scale {
|
||||
mant.sub(&scale);
|
||||
d += 1;
|
||||
}
|
||||
debug_assert!(mant < scale);
|
||||
debug_assert!(d < 10);
|
||||
buf[i] = MaybeUninit::new(b'0' + d);
|
||||
mant.mul_small(10);
|
||||
}
|
||||
}
|
||||
|
||||
// rounding up if we stop in the middle of digits
|
||||
// if the following digits are exactly 5000..., check the prior digit and try to
|
||||
// round to even (i.e., avoid rounding up when the prior digit is even).
|
||||
let order = mant.cmp(scale.mul_small(5));
|
||||
if order == Ordering::Greater
|
||||
|| (order == Ordering::Equal
|
||||
// SAFETY: `buf[len-1]` is initialized.
|
||||
&& (len == 0 || unsafe { buf[len - 1].assume_init() } & 1 == 1))
|
||||
{
|
||||
// if rounding up changes the length, the exponent should also change.
|
||||
// but we've been requested a fixed number of digits, so do not alter the buffer...
|
||||
// SAFETY: we initialized that memory above.
|
||||
if let Some(c) = round_up(unsafe { MaybeUninit::slice_assume_init_mut(&mut buf[..len]) }) {
|
||||
// ...unless we've been requested the fixed precision instead.
|
||||
// we also need to check that, if the original buffer was empty,
|
||||
// the additional digit can only be added when `k == limit` (edge case).
|
||||
k += 1;
|
||||
if k > limit && len < buf.len() {
|
||||
buf[len] = MaybeUninit::new(c);
|
||||
len += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// SAFETY: we initialized that memory above.
|
||||
(unsafe { MaybeUninit::slice_assume_init_ref(&buf[..len]) }, k)
|
||||
}
|
||||
764
libgrust/rustc-lib/core/src/num/flt2dec/strategy/grisu.rs
Normal file
764
libgrust/rustc-lib/core/src/num/flt2dec/strategy/grisu.rs
Normal file
@@ -0,0 +1,764 @@
|
||||
//! Rust adaptation of the Grisu3 algorithm described in "Printing Floating-Point Numbers Quickly
|
||||
//! and Accurately with Integers"[^1]. It uses about 1KB of precomputed table, and in turn, it's
|
||||
//! very quick for most inputs.
|
||||
//!
|
||||
//! [^1]: Florian Loitsch. 2010. Printing floating-point numbers quickly and
|
||||
//! accurately with integers. SIGPLAN Not. 45, 6 (June 2010), 233-243.
|
||||
|
||||
use crate::mem::MaybeUninit;
|
||||
use crate::num::diy_float::Fp;
|
||||
use crate::num::flt2dec::{round_up, Decoded, MAX_SIG_DIGITS};
|
||||
|
||||
// see the comments in `format_shortest_opt` for the rationale.
|
||||
#[doc(hidden)]
|
||||
pub const ALPHA: i16 = -60;
|
||||
#[doc(hidden)]
|
||||
pub const GAMMA: i16 = -32;
|
||||
|
||||
/*
|
||||
# the following Python code generates this table:
|
||||
for i in xrange(-308, 333, 8):
|
||||
if i >= 0: f = 10**i; e = 0
|
||||
else: f = 2**(80-4*i) // 10**-i; e = 4 * i - 80
|
||||
l = f.bit_length()
|
||||
f = ((f << 64 >> (l-1)) + 1) >> 1; e += l - 64
|
||||
print ' (%#018x, %5d, %4d),' % (f, e, i)
|
||||
*/
|
||||
|
||||
#[doc(hidden)]
|
||||
pub static CACHED_POW10: [(u64, i16, i16); 81] = [
|
||||
// (f, e, k)
|
||||
(0xe61acf033d1a45df, -1087, -308),
|
||||
(0xab70fe17c79ac6ca, -1060, -300),
|
||||
(0xff77b1fcbebcdc4f, -1034, -292),
|
||||
(0xbe5691ef416bd60c, -1007, -284),
|
||||
(0x8dd01fad907ffc3c, -980, -276),
|
||||
(0xd3515c2831559a83, -954, -268),
|
||||
(0x9d71ac8fada6c9b5, -927, -260),
|
||||
(0xea9c227723ee8bcb, -901, -252),
|
||||
(0xaecc49914078536d, -874, -244),
|
||||
(0x823c12795db6ce57, -847, -236),
|
||||
(0xc21094364dfb5637, -821, -228),
|
||||
(0x9096ea6f3848984f, -794, -220),
|
||||
(0xd77485cb25823ac7, -768, -212),
|
||||
(0xa086cfcd97bf97f4, -741, -204),
|
||||
(0xef340a98172aace5, -715, -196),
|
||||
(0xb23867fb2a35b28e, -688, -188),
|
||||
(0x84c8d4dfd2c63f3b, -661, -180),
|
||||
(0xc5dd44271ad3cdba, -635, -172),
|
||||
(0x936b9fcebb25c996, -608, -164),
|
||||
(0xdbac6c247d62a584, -582, -156),
|
||||
(0xa3ab66580d5fdaf6, -555, -148),
|
||||
(0xf3e2f893dec3f126, -529, -140),
|
||||
(0xb5b5ada8aaff80b8, -502, -132),
|
||||
(0x87625f056c7c4a8b, -475, -124),
|
||||
(0xc9bcff6034c13053, -449, -116),
|
||||
(0x964e858c91ba2655, -422, -108),
|
||||
(0xdff9772470297ebd, -396, -100),
|
||||
(0xa6dfbd9fb8e5b88f, -369, -92),
|
||||
(0xf8a95fcf88747d94, -343, -84),
|
||||
(0xb94470938fa89bcf, -316, -76),
|
||||
(0x8a08f0f8bf0f156b, -289, -68),
|
||||
(0xcdb02555653131b6, -263, -60),
|
||||
(0x993fe2c6d07b7fac, -236, -52),
|
||||
(0xe45c10c42a2b3b06, -210, -44),
|
||||
(0xaa242499697392d3, -183, -36),
|
||||
(0xfd87b5f28300ca0e, -157, -28),
|
||||
(0xbce5086492111aeb, -130, -20),
|
||||
(0x8cbccc096f5088cc, -103, -12),
|
||||
(0xd1b71758e219652c, -77, -4),
|
||||
(0x9c40000000000000, -50, 4),
|
||||
(0xe8d4a51000000000, -24, 12),
|
||||
(0xad78ebc5ac620000, 3, 20),
|
||||
(0x813f3978f8940984, 30, 28),
|
||||
(0xc097ce7bc90715b3, 56, 36),
|
||||
(0x8f7e32ce7bea5c70, 83, 44),
|
||||
(0xd5d238a4abe98068, 109, 52),
|
||||
(0x9f4f2726179a2245, 136, 60),
|
||||
(0xed63a231d4c4fb27, 162, 68),
|
||||
(0xb0de65388cc8ada8, 189, 76),
|
||||
(0x83c7088e1aab65db, 216, 84),
|
||||
(0xc45d1df942711d9a, 242, 92),
|
||||
(0x924d692ca61be758, 269, 100),
|
||||
(0xda01ee641a708dea, 295, 108),
|
||||
(0xa26da3999aef774a, 322, 116),
|
||||
(0xf209787bb47d6b85, 348, 124),
|
||||
(0xb454e4a179dd1877, 375, 132),
|
||||
(0x865b86925b9bc5c2, 402, 140),
|
||||
(0xc83553c5c8965d3d, 428, 148),
|
||||
(0x952ab45cfa97a0b3, 455, 156),
|
||||
(0xde469fbd99a05fe3, 481, 164),
|
||||
(0xa59bc234db398c25, 508, 172),
|
||||
(0xf6c69a72a3989f5c, 534, 180),
|
||||
(0xb7dcbf5354e9bece, 561, 188),
|
||||
(0x88fcf317f22241e2, 588, 196),
|
||||
(0xcc20ce9bd35c78a5, 614, 204),
|
||||
(0x98165af37b2153df, 641, 212),
|
||||
(0xe2a0b5dc971f303a, 667, 220),
|
||||
(0xa8d9d1535ce3b396, 694, 228),
|
||||
(0xfb9b7cd9a4a7443c, 720, 236),
|
||||
(0xbb764c4ca7a44410, 747, 244),
|
||||
(0x8bab8eefb6409c1a, 774, 252),
|
||||
(0xd01fef10a657842c, 800, 260),
|
||||
(0x9b10a4e5e9913129, 827, 268),
|
||||
(0xe7109bfba19c0c9d, 853, 276),
|
||||
(0xac2820d9623bf429, 880, 284),
|
||||
(0x80444b5e7aa7cf85, 907, 292),
|
||||
(0xbf21e44003acdd2d, 933, 300),
|
||||
(0x8e679c2f5e44ff8f, 960, 308),
|
||||
(0xd433179d9c8cb841, 986, 316),
|
||||
(0x9e19db92b4e31ba9, 1013, 324),
|
||||
(0xeb96bf6ebadf77d9, 1039, 332),
|
||||
];
|
||||
|
||||
#[doc(hidden)]
|
||||
pub const CACHED_POW10_FIRST_E: i16 = -1087;
|
||||
#[doc(hidden)]
|
||||
pub const CACHED_POW10_LAST_E: i16 = 1039;
|
||||
|
||||
#[doc(hidden)]
|
||||
pub fn cached_power(alpha: i16, gamma: i16) -> (i16, Fp) {
|
||||
let offset = CACHED_POW10_FIRST_E as i32;
|
||||
let range = (CACHED_POW10.len() as i32) - 1;
|
||||
let domain = (CACHED_POW10_LAST_E - CACHED_POW10_FIRST_E) as i32;
|
||||
let idx = ((gamma as i32) - offset) * range / domain;
|
||||
let (f, e, k) = CACHED_POW10[idx as usize];
|
||||
debug_assert!(alpha <= e && e <= gamma);
|
||||
(k, Fp { f, e })
|
||||
}
|
||||
|
||||
/// Given `x > 0`, returns `(k, 10^k)` such that `10^k <= x < 10^(k+1)`.
|
||||
#[doc(hidden)]
|
||||
pub fn max_pow10_no_more_than(x: u32) -> (u8, u32) {
|
||||
debug_assert!(x > 0);
|
||||
|
||||
const X9: u32 = 10_0000_0000;
|
||||
const X8: u32 = 1_0000_0000;
|
||||
const X7: u32 = 1000_0000;
|
||||
const X6: u32 = 100_0000;
|
||||
const X5: u32 = 10_0000;
|
||||
const X4: u32 = 1_0000;
|
||||
const X3: u32 = 1000;
|
||||
const X2: u32 = 100;
|
||||
const X1: u32 = 10;
|
||||
|
||||
if x < X4 {
|
||||
if x < X2 {
|
||||
if x < X1 { (0, 1) } else { (1, X1) }
|
||||
} else {
|
||||
if x < X3 { (2, X2) } else { (3, X3) }
|
||||
}
|
||||
} else {
|
||||
if x < X6 {
|
||||
if x < X5 { (4, X4) } else { (5, X5) }
|
||||
} else if x < X8 {
|
||||
if x < X7 { (6, X6) } else { (7, X7) }
|
||||
} else {
|
||||
if x < X9 { (8, X8) } else { (9, X9) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The shortest mode implementation for Grisu.
|
||||
///
|
||||
/// It returns `None` when it would return an inexact representation otherwise.
|
||||
pub fn format_shortest_opt<'a>(
|
||||
d: &Decoded,
|
||||
buf: &'a mut [MaybeUninit<u8>],
|
||||
) -> Option<(/*digits*/ &'a [u8], /*exp*/ i16)> {
|
||||
assert!(d.mant > 0);
|
||||
assert!(d.minus > 0);
|
||||
assert!(d.plus > 0);
|
||||
assert!(d.mant.checked_add(d.plus).is_some());
|
||||
assert!(d.mant.checked_sub(d.minus).is_some());
|
||||
assert!(buf.len() >= MAX_SIG_DIGITS);
|
||||
assert!(d.mant + d.plus < (1 << 61)); // we need at least three bits of additional precision
|
||||
|
||||
// start with the normalized values with the shared exponent
|
||||
let plus = Fp { f: d.mant + d.plus, e: d.exp }.normalize();
|
||||
let minus = Fp { f: d.mant - d.minus, e: d.exp }.normalize_to(plus.e);
|
||||
let v = Fp { f: d.mant, e: d.exp }.normalize_to(plus.e);
|
||||
|
||||
// find any `cached = 10^minusk` such that `ALPHA <= minusk + plus.e + 64 <= GAMMA`.
|
||||
// since `plus` is normalized, this means `2^(62 + ALPHA) <= plus * cached < 2^(64 + GAMMA)`;
|
||||
// given our choices of `ALPHA` and `GAMMA`, this puts `plus * cached` into `[4, 2^32)`.
|
||||
//
|
||||
// it is obviously desirable to maximize `GAMMA - ALPHA`,
|
||||
// so that we don't need many cached powers of 10, but there are some considerations:
|
||||
//
|
||||
// 1. we want to keep `floor(plus * cached)` within `u32` since it needs a costly division.
|
||||
// (this is not really avoidable, remainder is required for accuracy estimation.)
|
||||
// 2. the remainder of `floor(plus * cached)` repeatedly gets multiplied by 10,
|
||||
// and it should not overflow.
|
||||
//
|
||||
// the first gives `64 + GAMMA <= 32`, while the second gives `10 * 2^-ALPHA <= 2^64`;
|
||||
// -60 and -32 is the maximal range with this constraint, and V8 also uses them.
|
||||
let (minusk, cached) = cached_power(ALPHA - plus.e - 64, GAMMA - plus.e - 64);
|
||||
|
||||
// scale fps. this gives the maximal error of 1 ulp (proved from Theorem 5.1).
|
||||
let plus = plus.mul(&cached);
|
||||
let minus = minus.mul(&cached);
|
||||
let v = v.mul(&cached);
|
||||
debug_assert_eq!(plus.e, minus.e);
|
||||
debug_assert_eq!(plus.e, v.e);
|
||||
|
||||
// +- actual range of minus
|
||||
// | <---|---------------------- unsafe region --------------------------> |
|
||||
// | | |
|
||||
// | |<--->| | <--------------- safe region ---------------> | |
|
||||
// | | | | | |
|
||||
// |1 ulp|1 ulp| |1 ulp|1 ulp| |1 ulp|1 ulp|
|
||||
// |<--->|<--->| |<--->|<--->| |<--->|<--->|
|
||||
// |-----|-----|-------...-------|-----|-----|-------...-------|-----|-----|
|
||||
// | minus | | v | | plus |
|
||||
// minus1 minus0 v - 1 ulp v + 1 ulp plus0 plus1
|
||||
//
|
||||
// above `minus`, `v` and `plus` are *quantized* approximations (error < 1 ulp).
|
||||
// as we don't know the error is positive or negative, we use two approximations spaced equally
|
||||
// and have the maximal error of 2 ulps.
|
||||
//
|
||||
// the "unsafe region" is a liberal interval which we initially generate.
|
||||
// the "safe region" is a conservative interval which we only accept.
|
||||
// we start with the correct repr within the unsafe region, and try to find the closest repr
|
||||
// to `v` which is also within the safe region. if we can't, we give up.
|
||||
let plus1 = plus.f + 1;
|
||||
// let plus0 = plus.f - 1; // only for explanation
|
||||
// let minus0 = minus.f + 1; // only for explanation
|
||||
let minus1 = minus.f - 1;
|
||||
let e = -plus.e as usize; // shared exponent
|
||||
|
||||
// divide `plus1` into integral and fractional parts.
|
||||
// integral parts are guaranteed to fit in u32, since cached power guarantees `plus < 2^32`
|
||||
// and normalized `plus.f` is always less than `2^64 - 2^4` due to the precision requirement.
|
||||
let plus1int = (plus1 >> e) as u32;
|
||||
let plus1frac = plus1 & ((1 << e) - 1);
|
||||
|
||||
// calculate the largest `10^max_kappa` no more than `plus1` (thus `plus1 < 10^(max_kappa+1)`).
|
||||
// this is an upper bound of `kappa` below.
|
||||
let (max_kappa, max_ten_kappa) = max_pow10_no_more_than(plus1int);
|
||||
|
||||
let mut i = 0;
|
||||
let exp = max_kappa as i16 - minusk + 1;
|
||||
|
||||
// Theorem 6.2: if `k` is the greatest integer s.t. `0 <= y mod 10^k <= y - x`,
|
||||
// then `V = floor(y / 10^k) * 10^k` is in `[x, y]` and one of the shortest
|
||||
// representations (with the minimal number of significant digits) in that range.
|
||||
//
|
||||
// find the digit length `kappa` between `(minus1, plus1)` as per Theorem 6.2.
|
||||
// Theorem 6.2 can be adopted to exclude `x` by requiring `y mod 10^k < y - x` instead.
|
||||
// (e.g., `x` = 32000, `y` = 32777; `kappa` = 2 since `y mod 10^3 = 777 < y - x = 777`.)
|
||||
// the algorithm relies on the later verification phase to exclude `y`.
|
||||
let delta1 = plus1 - minus1;
|
||||
// let delta1int = (delta1 >> e) as usize; // only for explanation
|
||||
let delta1frac = delta1 & ((1 << e) - 1);
|
||||
|
||||
// render integral parts, while checking for the accuracy at each step.
|
||||
let mut kappa = max_kappa as i16;
|
||||
let mut ten_kappa = max_ten_kappa; // 10^kappa
|
||||
let mut remainder = plus1int; // digits yet to be rendered
|
||||
loop {
|
||||
// we always have at least one digit to render, as `plus1 >= 10^kappa`
|
||||
// invariants:
|
||||
// - `delta1int <= remainder < 10^(kappa+1)`
|
||||
// - `plus1int = d[0..n-1] * 10^(kappa+1) + remainder`
|
||||
// (it follows that `remainder = plus1int % 10^(kappa+1)`)
|
||||
|
||||
// divide `remainder` by `10^kappa`. both are scaled by `2^-e`.
|
||||
let q = remainder / ten_kappa;
|
||||
let r = remainder % ten_kappa;
|
||||
debug_assert!(q < 10);
|
||||
buf[i] = MaybeUninit::new(b'0' + q as u8);
|
||||
i += 1;
|
||||
|
||||
let plus1rem = ((r as u64) << e) + plus1frac; // == (plus1 % 10^kappa) * 2^e
|
||||
if plus1rem < delta1 {
|
||||
// `plus1 % 10^kappa < delta1 = plus1 - minus1`; we've found the correct `kappa`.
|
||||
let ten_kappa = (ten_kappa as u64) << e; // scale 10^kappa back to the shared exponent
|
||||
return round_and_weed(
|
||||
// SAFETY: we initialized that memory above.
|
||||
unsafe { MaybeUninit::slice_assume_init_mut(&mut buf[..i]) },
|
||||
exp,
|
||||
plus1rem,
|
||||
delta1,
|
||||
plus1 - v.f,
|
||||
ten_kappa,
|
||||
1,
|
||||
);
|
||||
}
|
||||
|
||||
// break the loop when we have rendered all integral digits.
|
||||
// the exact number of digits is `max_kappa + 1` as `plus1 < 10^(max_kappa+1)`.
|
||||
if i > max_kappa as usize {
|
||||
debug_assert_eq!(ten_kappa, 1);
|
||||
debug_assert_eq!(kappa, 0);
|
||||
break;
|
||||
}
|
||||
|
||||
// restore invariants
|
||||
kappa -= 1;
|
||||
ten_kappa /= 10;
|
||||
remainder = r;
|
||||
}
|
||||
|
||||
// render fractional parts, while checking for the accuracy at each step.
|
||||
// this time we rely on repeated multiplications, as division will lose the precision.
|
||||
let mut remainder = plus1frac;
|
||||
let mut threshold = delta1frac;
|
||||
let mut ulp = 1;
|
||||
loop {
|
||||
// the next digit should be significant as we've tested that before breaking out
|
||||
// invariants, where `m = max_kappa + 1` (# of digits in the integral part):
|
||||
// - `remainder < 2^e`
|
||||
// - `plus1frac * 10^(n-m) = d[m..n-1] * 2^e + remainder`
|
||||
|
||||
remainder *= 10; // won't overflow, `2^e * 10 < 2^64`
|
||||
threshold *= 10;
|
||||
ulp *= 10;
|
||||
|
||||
// divide `remainder` by `10^kappa`.
|
||||
// both are scaled by `2^e / 10^kappa`, so the latter is implicit here.
|
||||
let q = remainder >> e;
|
||||
let r = remainder & ((1 << e) - 1);
|
||||
debug_assert!(q < 10);
|
||||
buf[i] = MaybeUninit::new(b'0' + q as u8);
|
||||
i += 1;
|
||||
|
||||
if r < threshold {
|
||||
let ten_kappa = 1 << e; // implicit divisor
|
||||
return round_and_weed(
|
||||
// SAFETY: we initialized that memory above.
|
||||
unsafe { MaybeUninit::slice_assume_init_mut(&mut buf[..i]) },
|
||||
exp,
|
||||
r,
|
||||
threshold,
|
||||
(plus1 - v.f) * ulp,
|
||||
ten_kappa,
|
||||
ulp,
|
||||
);
|
||||
}
|
||||
|
||||
// restore invariants
|
||||
kappa -= 1;
|
||||
remainder = r;
|
||||
}
|
||||
|
||||
// we've generated all significant digits of `plus1`, but not sure if it's the optimal one.
|
||||
// for example, if `minus1` is 3.14153... and `plus1` is 3.14158..., there are 5 different
|
||||
// shortest representation from 3.14154 to 3.14158 but we only have the greatest one.
|
||||
// we have to successively decrease the last digit and check if this is the optimal repr.
|
||||
// there are at most 9 candidates (..1 to ..9), so this is fairly quick. ("rounding" phase)
|
||||
//
|
||||
// the function checks if this "optimal" repr is actually within the ulp ranges,
|
||||
// and also, it is possible that the "second-to-optimal" repr can actually be optimal
|
||||
// due to the rounding error. in either cases this returns `None`. ("weeding" phase)
|
||||
//
|
||||
// all arguments here are scaled by the common (but implicit) value `k`, so that:
|
||||
// - `remainder = (plus1 % 10^kappa) * k`
|
||||
// - `threshold = (plus1 - minus1) * k` (and also, `remainder < threshold`)
|
||||
// - `plus1v = (plus1 - v) * k` (and also, `threshold > plus1v` from prior invariants)
|
||||
// - `ten_kappa = 10^kappa * k`
|
||||
// - `ulp = 2^-e * k`
|
||||
fn round_and_weed(
|
||||
buf: &mut [u8],
|
||||
exp: i16,
|
||||
remainder: u64,
|
||||
threshold: u64,
|
||||
plus1v: u64,
|
||||
ten_kappa: u64,
|
||||
ulp: u64,
|
||||
) -> Option<(&[u8], i16)> {
|
||||
assert!(!buf.is_empty());
|
||||
|
||||
// produce two approximations to `v` (actually `plus1 - v`) within 1.5 ulps.
|
||||
// the resulting representation should be the closest representation to both.
|
||||
//
|
||||
// here `plus1 - v` is used since calculations are done with respect to `plus1`
|
||||
// in order to avoid overflow/underflow (hence the seemingly swapped names).
|
||||
let plus1v_down = plus1v + ulp; // plus1 - (v - 1 ulp)
|
||||
let plus1v_up = plus1v - ulp; // plus1 - (v + 1 ulp)
|
||||
|
||||
// decrease the last digit and stop at the closest representation to `v + 1 ulp`.
|
||||
let mut plus1w = remainder; // plus1w(n) = plus1 - w(n)
|
||||
{
|
||||
let last = buf.last_mut().unwrap();
|
||||
|
||||
// we work with the approximated digits `w(n)`, which is initially equal to `plus1 -
|
||||
// plus1 % 10^kappa`. after running the loop body `n` times, `w(n) = plus1 -
|
||||
// plus1 % 10^kappa - n * 10^kappa`. we set `plus1w(n) = plus1 - w(n) =
|
||||
// plus1 % 10^kappa + n * 10^kappa` (thus `remainder = plus1w(0)`) to simplify checks.
|
||||
// note that `plus1w(n)` is always increasing.
|
||||
//
|
||||
// we have three conditions to terminate. any of them will make the loop unable to
|
||||
// proceed, but we then have at least one valid representation known to be closest to
|
||||
// `v + 1 ulp` anyway. we will denote them as TC1 through TC3 for brevity.
|
||||
//
|
||||
// TC1: `w(n) <= v + 1 ulp`, i.e., this is the last repr that can be the closest one.
|
||||
// this is equivalent to `plus1 - w(n) = plus1w(n) >= plus1 - (v + 1 ulp) = plus1v_up`.
|
||||
// combined with TC2 (which checks if `w(n+1)` is valid), this prevents the possible
|
||||
// overflow on the calculation of `plus1w(n)`.
|
||||
//
|
||||
// TC2: `w(n+1) < minus1`, i.e., the next repr definitely does not round to `v`.
|
||||
// this is equivalent to `plus1 - w(n) + 10^kappa = plus1w(n) + 10^kappa >
|
||||
// plus1 - minus1 = threshold`. the left hand side can overflow, but we know
|
||||
// `threshold > plus1v`, so if TC1 is false, `threshold - plus1w(n) >
|
||||
// threshold - (plus1v - 1 ulp) > 1 ulp` and we can safely test if
|
||||
// `threshold - plus1w(n) < 10^kappa` instead.
|
||||
//
|
||||
// TC3: `abs(w(n) - (v + 1 ulp)) <= abs(w(n+1) - (v + 1 ulp))`, i.e., the next repr is
|
||||
// no closer to `v + 1 ulp` than the current repr. given `z(n) = plus1v_up - plus1w(n)`,
|
||||
// this becomes `abs(z(n)) <= abs(z(n+1))`. again assuming that TC1 is false, we have
|
||||
// `z(n) > 0`. we have two cases to consider:
|
||||
//
|
||||
// - when `z(n+1) >= 0`: TC3 becomes `z(n) <= z(n+1)`. as `plus1w(n)` is increasing,
|
||||
// `z(n)` should be decreasing and this is clearly false.
|
||||
// - when `z(n+1) < 0`:
|
||||
// - TC3a: the precondition is `plus1v_up < plus1w(n) + 10^kappa`. assuming TC2 is
|
||||
// false, `threshold >= plus1w(n) + 10^kappa` so it cannot overflow.
|
||||
// - TC3b: TC3 becomes `z(n) <= -z(n+1)`, i.e., `plus1v_up - plus1w(n) >=
|
||||
// plus1w(n+1) - plus1v_up = plus1w(n) + 10^kappa - plus1v_up`. the negated TC1
|
||||
// gives `plus1v_up > plus1w(n)`, so it cannot overflow or underflow when
|
||||
// combined with TC3a.
|
||||
//
|
||||
// consequently, we should stop when `TC1 || TC2 || (TC3a && TC3b)`. the following is
|
||||
// equal to its inverse, `!TC1 && !TC2 && (!TC3a || !TC3b)`.
|
||||
while plus1w < plus1v_up
|
||||
&& threshold - plus1w >= ten_kappa
|
||||
&& (plus1w + ten_kappa < plus1v_up
|
||||
|| plus1v_up - plus1w >= plus1w + ten_kappa - plus1v_up)
|
||||
{
|
||||
*last -= 1;
|
||||
debug_assert!(*last > b'0'); // the shortest repr cannot end with `0`
|
||||
plus1w += ten_kappa;
|
||||
}
|
||||
}
|
||||
|
||||
// check if this representation is also the closest representation to `v - 1 ulp`.
|
||||
//
|
||||
// this is simply same to the terminating conditions for `v + 1 ulp`, with all `plus1v_up`
|
||||
// replaced by `plus1v_down` instead. overflow analysis equally holds.
|
||||
if plus1w < plus1v_down
|
||||
&& threshold - plus1w >= ten_kappa
|
||||
&& (plus1w + ten_kappa < plus1v_down
|
||||
|| plus1v_down - plus1w >= plus1w + ten_kappa - plus1v_down)
|
||||
{
|
||||
return None;
|
||||
}
|
||||
|
||||
// now we have the closest representation to `v` between `plus1` and `minus1`.
|
||||
// this is too liberal, though, so we reject any `w(n)` not between `plus0` and `minus0`,
|
||||
// i.e., `plus1 - plus1w(n) <= minus0` or `plus1 - plus1w(n) >= plus0`. we utilize the facts
|
||||
// that `threshold = plus1 - minus1` and `plus1 - plus0 = minus0 - minus1 = 2 ulp`.
|
||||
if 2 * ulp <= plus1w && plus1w <= threshold - 4 * ulp { Some((buf, exp)) } else { None }
|
||||
}
|
||||
}
|
||||
|
||||
/// The shortest mode implementation for Grisu with Dragon fallback.
|
||||
///
|
||||
/// This should be used for most cases.
|
||||
pub fn format_shortest<'a>(
|
||||
d: &Decoded,
|
||||
buf: &'a mut [MaybeUninit<u8>],
|
||||
) -> (/*digits*/ &'a [u8], /*exp*/ i16) {
|
||||
use crate::num::flt2dec::strategy::dragon::format_shortest as fallback;
|
||||
// SAFETY: The borrow checker is not smart enough to let us use `buf`
|
||||
// in the second branch, so we launder the lifetime here. But we only re-use
|
||||
// `buf` if `format_shortest_opt` returned `None` so this is okay.
|
||||
match format_shortest_opt(d, unsafe { &mut *(buf as *mut _) }) {
|
||||
Some(ret) => ret,
|
||||
None => fallback(d, buf),
|
||||
}
|
||||
}
|
||||
|
||||
/// The exact and fixed mode implementation for Grisu.
|
||||
///
|
||||
/// It returns `None` when it would return an inexact representation otherwise.
|
||||
pub fn format_exact_opt<'a>(
|
||||
d: &Decoded,
|
||||
buf: &'a mut [MaybeUninit<u8>],
|
||||
limit: i16,
|
||||
) -> Option<(/*digits*/ &'a [u8], /*exp*/ i16)> {
|
||||
assert!(d.mant > 0);
|
||||
assert!(d.mant < (1 << 61)); // we need at least three bits of additional precision
|
||||
assert!(!buf.is_empty());
|
||||
|
||||
// normalize and scale `v`.
|
||||
let v = Fp { f: d.mant, e: d.exp }.normalize();
|
||||
let (minusk, cached) = cached_power(ALPHA - v.e - 64, GAMMA - v.e - 64);
|
||||
let v = v.mul(&cached);
|
||||
|
||||
// divide `v` into integral and fractional parts.
|
||||
let e = -v.e as usize;
|
||||
let vint = (v.f >> e) as u32;
|
||||
let vfrac = v.f & ((1 << e) - 1);
|
||||
|
||||
// both old `v` and new `v` (scaled by `10^-k`) has an error of < 1 ulp (Theorem 5.1).
|
||||
// as we don't know the error is positive or negative, we use two approximations
|
||||
// spaced equally and have the maximal error of 2 ulps (same to the shortest case).
|
||||
//
|
||||
// the goal is to find the exactly rounded series of digits that are common to
|
||||
// both `v - 1 ulp` and `v + 1 ulp`, so that we are maximally confident.
|
||||
// if this is not possible, we don't know which one is the correct output for `v`,
|
||||
// so we give up and fall back.
|
||||
//
|
||||
// `err` is defined as `1 ulp * 2^e` here (same to the ulp in `vfrac`),
|
||||
// and we will scale it whenever `v` gets scaled.
|
||||
let mut err = 1;
|
||||
|
||||
// calculate the largest `10^max_kappa` no more than `v` (thus `v < 10^(max_kappa+1)`).
|
||||
// this is an upper bound of `kappa` below.
|
||||
let (max_kappa, max_ten_kappa) = max_pow10_no_more_than(vint);
|
||||
|
||||
let mut i = 0;
|
||||
let exp = max_kappa as i16 - minusk + 1;
|
||||
|
||||
// if we are working with the last-digit limitation, we need to shorten the buffer
|
||||
// before the actual rendering in order to avoid double rounding.
|
||||
// note that we have to enlarge the buffer again when rounding up happens!
|
||||
let len = if exp <= limit {
|
||||
// oops, we cannot even produce *one* digit.
|
||||
// this is possible when, say, we've got something like 9.5 and it's being rounded to 10.
|
||||
//
|
||||
// in principle we can immediately call `possibly_round` with an empty buffer,
|
||||
// but scaling `max_ten_kappa << e` by 10 can result in overflow.
|
||||
// thus we are being sloppy here and widen the error range by a factor of 10.
|
||||
// this will increase the false negative rate, but only very, *very* slightly;
|
||||
// it can only matter noticeably when the mantissa is bigger than 60 bits.
|
||||
//
|
||||
// SAFETY: `len=0`, so the obligation of having initialized this memory is trivial.
|
||||
return unsafe {
|
||||
possibly_round(buf, 0, exp, limit, v.f / 10, (max_ten_kappa as u64) << e, err << e)
|
||||
};
|
||||
} else if ((exp as i32 - limit as i32) as usize) < buf.len() {
|
||||
(exp - limit) as usize
|
||||
} else {
|
||||
buf.len()
|
||||
};
|
||||
debug_assert!(len > 0);
|
||||
|
||||
// render integral parts.
|
||||
// the error is entirely fractional, so we don't need to check it in this part.
|
||||
let mut kappa = max_kappa as i16;
|
||||
let mut ten_kappa = max_ten_kappa; // 10^kappa
|
||||
let mut remainder = vint; // digits yet to be rendered
|
||||
loop {
|
||||
// we always have at least one digit to render
|
||||
// invariants:
|
||||
// - `remainder < 10^(kappa+1)`
|
||||
// - `vint = d[0..n-1] * 10^(kappa+1) + remainder`
|
||||
// (it follows that `remainder = vint % 10^(kappa+1)`)
|
||||
|
||||
// divide `remainder` by `10^kappa`. both are scaled by `2^-e`.
|
||||
let q = remainder / ten_kappa;
|
||||
let r = remainder % ten_kappa;
|
||||
debug_assert!(q < 10);
|
||||
buf[i] = MaybeUninit::new(b'0' + q as u8);
|
||||
i += 1;
|
||||
|
||||
// is the buffer full? run the rounding pass with the remainder.
|
||||
if i == len {
|
||||
let vrem = ((r as u64) << e) + vfrac; // == (v % 10^kappa) * 2^e
|
||||
// SAFETY: we have initialized `len` many bytes.
|
||||
return unsafe {
|
||||
possibly_round(buf, len, exp, limit, vrem, (ten_kappa as u64) << e, err << e)
|
||||
};
|
||||
}
|
||||
|
||||
// break the loop when we have rendered all integral digits.
|
||||
// the exact number of digits is `max_kappa + 1` as `plus1 < 10^(max_kappa+1)`.
|
||||
if i > max_kappa as usize {
|
||||
debug_assert_eq!(ten_kappa, 1);
|
||||
debug_assert_eq!(kappa, 0);
|
||||
break;
|
||||
}
|
||||
|
||||
// restore invariants
|
||||
kappa -= 1;
|
||||
ten_kappa /= 10;
|
||||
remainder = r;
|
||||
}
|
||||
|
||||
// render fractional parts.
|
||||
//
|
||||
// in principle we can continue to the last available digit and check for the accuracy.
|
||||
// unfortunately we are working with the finite-sized integers, so we need some criterion
|
||||
// to detect the overflow. V8 uses `remainder > err`, which becomes false when
|
||||
// the first `i` significant digits of `v - 1 ulp` and `v` differ. however this rejects
|
||||
// too many otherwise valid input.
|
||||
//
|
||||
// since the later phase has a correct overflow detection, we instead use tighter criterion:
|
||||
// we continue til `err` exceeds `10^kappa / 2`, so that the range between `v - 1 ulp` and
|
||||
// `v + 1 ulp` definitely contains two or more rounded representations. this is same to
|
||||
// the first two comparisons from `possibly_round`, for the reference.
|
||||
let mut remainder = vfrac;
|
||||
let maxerr = 1 << (e - 1);
|
||||
while err < maxerr {
|
||||
// invariants, where `m = max_kappa + 1` (# of digits in the integral part):
|
||||
// - `remainder < 2^e`
|
||||
// - `vfrac * 10^(n-m) = d[m..n-1] * 2^e + remainder`
|
||||
// - `err = 10^(n-m)`
|
||||
|
||||
remainder *= 10; // won't overflow, `2^e * 10 < 2^64`
|
||||
err *= 10; // won't overflow, `err * 10 < 2^e * 5 < 2^64`
|
||||
|
||||
// divide `remainder` by `10^kappa`.
|
||||
// both are scaled by `2^e / 10^kappa`, so the latter is implicit here.
|
||||
let q = remainder >> e;
|
||||
let r = remainder & ((1 << e) - 1);
|
||||
debug_assert!(q < 10);
|
||||
buf[i] = MaybeUninit::new(b'0' + q as u8);
|
||||
i += 1;
|
||||
|
||||
// is the buffer full? run the rounding pass with the remainder.
|
||||
if i == len {
|
||||
// SAFETY: we have initialized `len` many bytes.
|
||||
return unsafe { possibly_round(buf, len, exp, limit, r, 1 << e, err) };
|
||||
}
|
||||
|
||||
// restore invariants
|
||||
remainder = r;
|
||||
}
|
||||
|
||||
// further calculation is useless (`possibly_round` definitely fails), so we give up.
|
||||
return None;
|
||||
|
||||
// we've generated all requested digits of `v`, which should be also same to corresponding
|
||||
// digits of `v - 1 ulp`. now we check if there is a unique representation shared by
|
||||
// both `v - 1 ulp` and `v + 1 ulp`; this can be either same to generated digits, or
|
||||
// to the rounded-up version of those digits. if the range contains multiple representations
|
||||
// of the same length, we cannot be sure and should return `None` instead.
|
||||
//
|
||||
// all arguments here are scaled by the common (but implicit) value `k`, so that:
|
||||
// - `remainder = (v % 10^kappa) * k`
|
||||
// - `ten_kappa = 10^kappa * k`
|
||||
// - `ulp = 2^-e * k`
|
||||
//
|
||||
// SAFETY: the first `len` bytes of `buf` must be initialized.
|
||||
unsafe fn possibly_round(
|
||||
buf: &mut [MaybeUninit<u8>],
|
||||
mut len: usize,
|
||||
mut exp: i16,
|
||||
limit: i16,
|
||||
remainder: u64,
|
||||
ten_kappa: u64,
|
||||
ulp: u64,
|
||||
) -> Option<(&[u8], i16)> {
|
||||
debug_assert!(remainder < ten_kappa);
|
||||
|
||||
// 10^kappa
|
||||
// : : :<->: :
|
||||
// : : : : :
|
||||
// :|1 ulp|1 ulp| :
|
||||
// :|<--->|<--->| :
|
||||
// ----|-----|-----|----
|
||||
// | v |
|
||||
// v - 1 ulp v + 1 ulp
|
||||
//
|
||||
// (for the reference, the dotted line indicates the exact value for
|
||||
// possible representations in given number of digits.)
|
||||
//
|
||||
// error is too large that there are at least three possible representations
|
||||
// between `v - 1 ulp` and `v + 1 ulp`. we cannot determine which one is correct.
|
||||
if ulp >= ten_kappa {
|
||||
return None;
|
||||
}
|
||||
|
||||
// 10^kappa
|
||||
// :<------->:
|
||||
// : :
|
||||
// : |1 ulp|1 ulp|
|
||||
// : |<--->|<--->|
|
||||
// ----|-----|-----|----
|
||||
// | v |
|
||||
// v - 1 ulp v + 1 ulp
|
||||
//
|
||||
// in fact, 1/2 ulp is enough to introduce two possible representations.
|
||||
// (remember that we need a unique representation for both `v - 1 ulp` and `v + 1 ulp`.)
|
||||
// this won't overflow, as `ulp < ten_kappa` from the first check.
|
||||
if ten_kappa - ulp <= ulp {
|
||||
return None;
|
||||
}
|
||||
|
||||
// remainder
|
||||
// :<->| :
|
||||
// : | :
|
||||
// :<--------- 10^kappa ---------->:
|
||||
// | : | :
|
||||
// |1 ulp|1 ulp| :
|
||||
// |<--->|<--->| :
|
||||
// ----|-----|-----|------------------------
|
||||
// | v |
|
||||
// v - 1 ulp v + 1 ulp
|
||||
//
|
||||
// if `v + 1 ulp` is closer to the rounded-down representation (which is already in `buf`),
|
||||
// then we can safely return. note that `v - 1 ulp` *can* be less than the current
|
||||
// representation, but as `1 ulp < 10^kappa / 2`, this condition is enough:
|
||||
// the distance between `v - 1 ulp` and the current representation
|
||||
// cannot exceed `10^kappa / 2`.
|
||||
//
|
||||
// the condition equals to `remainder + ulp < 10^kappa / 2`.
|
||||
// since this can easily overflow, first check if `remainder < 10^kappa / 2`.
|
||||
// we've already verified that `ulp < 10^kappa / 2`, so as long as
|
||||
// `10^kappa` did not overflow after all, the second check is fine.
|
||||
if ten_kappa - remainder > remainder && ten_kappa - 2 * remainder >= 2 * ulp {
|
||||
// SAFETY: our caller initialized that memory.
|
||||
return Some((unsafe { MaybeUninit::slice_assume_init_ref(&buf[..len]) }, exp));
|
||||
}
|
||||
|
||||
// :<------- remainder ------>| :
|
||||
// : | :
|
||||
// :<--------- 10^kappa --------->:
|
||||
// : | | : |
|
||||
// : |1 ulp|1 ulp|
|
||||
// : |<--->|<--->|
|
||||
// -----------------------|-----|-----|-----
|
||||
// | v |
|
||||
// v - 1 ulp v + 1 ulp
|
||||
//
|
||||
// on the other hands, if `v - 1 ulp` is closer to the rounded-up representation,
|
||||
// we should round up and return. for the same reason we don't need to check `v + 1 ulp`.
|
||||
//
|
||||
// the condition equals to `remainder - ulp >= 10^kappa / 2`.
|
||||
// again we first check if `remainder > ulp` (note that this is not `remainder >= ulp`,
|
||||
// as `10^kappa` is never zero). also note that `remainder - ulp <= 10^kappa`,
|
||||
// so the second check does not overflow.
|
||||
if remainder > ulp && ten_kappa - (remainder - ulp) <= remainder - ulp {
|
||||
if let Some(c) =
|
||||
// SAFETY: our caller must have initialized that memory.
|
||||
round_up(unsafe { MaybeUninit::slice_assume_init_mut(&mut buf[..len]) })
|
||||
{
|
||||
// only add an additional digit when we've been requested the fixed precision.
|
||||
// we also need to check that, if the original buffer was empty,
|
||||
// the additional digit can only be added when `exp == limit` (edge case).
|
||||
exp += 1;
|
||||
if exp > limit && len < buf.len() {
|
||||
buf[len] = MaybeUninit::new(c);
|
||||
len += 1;
|
||||
}
|
||||
}
|
||||
// SAFETY: we and our caller initialized that memory.
|
||||
return Some((unsafe { MaybeUninit::slice_assume_init_ref(&buf[..len]) }, exp));
|
||||
}
|
||||
|
||||
// otherwise we are doomed (i.e., some values between `v - 1 ulp` and `v + 1 ulp` are
|
||||
// rounding down and others are rounding up) and give up.
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
/// The exact and fixed mode implementation for Grisu with Dragon fallback.
|
||||
///
|
||||
/// This should be used for most cases.
|
||||
pub fn format_exact<'a>(
|
||||
d: &Decoded,
|
||||
buf: &'a mut [MaybeUninit<u8>],
|
||||
limit: i16,
|
||||
) -> (/*digits*/ &'a [u8], /*exp*/ i16) {
|
||||
use crate::num::flt2dec::strategy::dragon::format_exact as fallback;
|
||||
// SAFETY: The borrow checker is not smart enough to let us use `buf`
|
||||
// in the second branch, so we launder the lifetime here. But we only re-use
|
||||
// `buf` if `format_exact_opt` returned `None` so this is okay.
|
||||
match format_exact_opt(d, unsafe { &mut *(buf as *mut _) }, limit) {
|
||||
Some(ret) => ret,
|
||||
None => fallback(d, buf, limit),
|
||||
}
|
||||
}
|
||||
2240
libgrust/rustc-lib/core/src/num/int_macros.rs
Normal file
2240
libgrust/rustc-lib/core/src/num/int_macros.rs
Normal file
File diff suppressed because it is too large
Load Diff
881
libgrust/rustc-lib/core/src/num/mod.rs
Normal file
881
libgrust/rustc-lib/core/src/num/mod.rs
Normal file
@@ -0,0 +1,881 @@
|
||||
//! Numeric traits and functions for the built-in numeric types.
|
||||
|
||||
#![stable(feature = "rust1", since = "1.0.0")]
|
||||
|
||||
use crate::intrinsics;
|
||||
use crate::mem;
|
||||
use crate::str::FromStr;
|
||||
|
||||
// Used because the `?` operator is not allowed in a const context.
|
||||
macro_rules! try_opt {
|
||||
($e:expr) => {
|
||||
match $e {
|
||||
Some(x) => x,
|
||||
None => return None,
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[allow_internal_unstable(const_likely)]
|
||||
macro_rules! unlikely {
|
||||
($e: expr) => {
|
||||
intrinsics::unlikely($e)
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! doc_comment {
|
||||
($x:expr, $($tt:tt)*) => {
|
||||
#[doc = $x]
|
||||
$($tt)*
|
||||
};
|
||||
}
|
||||
|
||||
// All these modules are technically private and only exposed for coretests:
|
||||
pub mod bignum;
|
||||
pub mod dec2flt;
|
||||
pub mod diy_float;
|
||||
pub mod flt2dec;
|
||||
|
||||
#[macro_use]
|
||||
mod int_macros; // import int_impl!
|
||||
#[macro_use]
|
||||
mod uint_macros; // import uint_impl!
|
||||
|
||||
mod error;
|
||||
mod nonzero;
|
||||
mod wrapping;
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use wrapping::Wrapping;
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use dec2flt::ParseFloatError;
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub use error::ParseIntError;
|
||||
|
||||
#[stable(feature = "nonzero", since = "1.28.0")]
|
||||
pub use nonzero::{NonZeroU128, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, NonZeroUsize};
|
||||
|
||||
#[stable(feature = "signed_nonzero", since = "1.34.0")]
|
||||
pub use nonzero::{NonZeroI128, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI8, NonZeroIsize};
|
||||
|
||||
#[stable(feature = "try_from", since = "1.34.0")]
|
||||
pub use error::TryFromIntError;
|
||||
|
||||
#[unstable(
|
||||
feature = "int_error_matching",
|
||||
reason = "it can be useful to match errors when making error messages \
|
||||
for integer parsing",
|
||||
issue = "22639"
|
||||
)]
|
||||
pub use error::IntErrorKind;
|
||||
|
||||
macro_rules! usize_isize_to_xe_bytes_doc {
|
||||
() => {
|
||||
"
|
||||
|
||||
**Note**: This function returns an array of length 2, 4 or 8 bytes
|
||||
depending on the target pointer size.
|
||||
|
||||
"
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! usize_isize_from_xe_bytes_doc {
|
||||
() => {
|
||||
"
|
||||
|
||||
**Note**: This function takes an array of length 2, 4 or 8 bytes
|
||||
depending on the target pointer size.
|
||||
|
||||
"
|
||||
};
|
||||
}
|
||||
|
||||
#[lang = "i8"]
|
||||
impl i8 {
|
||||
int_impl! { i8, i8, u8, 8, -128, 127, "", "", 2, "-0x7e", "0xa", "0x12", "0x12", "0x48",
|
||||
"[0x12]", "[0x12]", "", "" }
|
||||
}
|
||||
|
||||
#[lang = "i16"]
|
||||
impl i16 {
|
||||
int_impl! { i16, i16, u16, 16, -32768, 32767, "", "", 4, "-0x5ffd", "0x3a", "0x1234", "0x3412",
|
||||
"0x2c48", "[0x34, 0x12]", "[0x12, 0x34]", "", "" }
|
||||
}
|
||||
|
||||
#[lang = "i32"]
|
||||
impl i32 {
|
||||
int_impl! { i32, i32, u32, 32, -2147483648, 2147483647, "", "", 8, "0x10000b3", "0xb301",
|
||||
"0x12345678", "0x78563412", "0x1e6a2c48", "[0x78, 0x56, 0x34, 0x12]",
|
||||
"[0x12, 0x34, 0x56, 0x78]", "", "" }
|
||||
}
|
||||
|
||||
#[lang = "i64"]
|
||||
impl i64 {
|
||||
int_impl! { i64, i64, u64, 64, -9223372036854775808, 9223372036854775807, "", "", 12,
|
||||
"0xaa00000000006e1", "0x6e10aa", "0x1234567890123456", "0x5634129078563412",
|
||||
"0x6a2c48091e6a2c48", "[0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]",
|
||||
"[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]", "", "" }
|
||||
}
|
||||
|
||||
#[lang = "i128"]
|
||||
impl i128 {
|
||||
int_impl! { i128, i128, u128, 128, -170141183460469231731687303715884105728,
|
||||
170141183460469231731687303715884105727, "", "", 16,
|
||||
"0x13f40000000000000000000000004f76", "0x4f7613f4", "0x12345678901234567890123456789012",
|
||||
"0x12907856341290785634129078563412", "0x48091e6a2c48091e6a2c48091e6a2c48",
|
||||
"[0x12, 0x90, 0x78, 0x56, 0x34, 0x12, 0x90, 0x78, \
|
||||
0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]",
|
||||
"[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56, \
|
||||
0x78, 0x90, 0x12, 0x34, 0x56, 0x78, 0x90, 0x12]", "", "" }
|
||||
}
|
||||
|
||||
#[cfg(target_pointer_width = "16")]
|
||||
#[lang = "isize"]
|
||||
impl isize {
|
||||
int_impl! { isize, i16, usize, 16, -32768, 32767, "", "", 4, "-0x5ffd", "0x3a", "0x1234",
|
||||
"0x3412", "0x2c48", "[0x34, 0x12]", "[0x12, 0x34]",
|
||||
usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!() }
|
||||
}
|
||||
|
||||
#[cfg(target_pointer_width = "32")]
|
||||
#[lang = "isize"]
|
||||
impl isize {
|
||||
int_impl! { isize, i32, usize, 32, -2147483648, 2147483647, "", "", 8, "0x10000b3", "0xb301",
|
||||
"0x12345678", "0x78563412", "0x1e6a2c48", "[0x78, 0x56, 0x34, 0x12]",
|
||||
"[0x12, 0x34, 0x56, 0x78]",
|
||||
usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!() }
|
||||
}
|
||||
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
#[lang = "isize"]
|
||||
impl isize {
|
||||
int_impl! { isize, i64, usize, 64, -9223372036854775808, 9223372036854775807, "", "",
|
||||
12, "0xaa00000000006e1", "0x6e10aa", "0x1234567890123456", "0x5634129078563412",
|
||||
"0x6a2c48091e6a2c48", "[0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]",
|
||||
"[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]",
|
||||
usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!() }
|
||||
}
|
||||
|
||||
#[lang = "u8"]
|
||||
impl u8 {
|
||||
uint_impl! { u8, u8, 8, 255, "", "", 2, "0x82", "0xa", "0x12", "0x12", "0x48", "[0x12]",
|
||||
"[0x12]", "", "" }
|
||||
|
||||
/// Checks if the value is within the ASCII range.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// let ascii = 97u8;
|
||||
/// let non_ascii = 150u8;
|
||||
///
|
||||
/// assert!(ascii.is_ascii());
|
||||
/// assert!(!non_ascii.is_ascii());
|
||||
/// ```
|
||||
#[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
|
||||
#[rustc_const_stable(feature = "const_ascii_methods_on_intrinsics", since = "1.43.0")]
|
||||
#[inline]
|
||||
pub const fn is_ascii(&self) -> bool {
|
||||
*self & 128 == 0
|
||||
}
|
||||
|
||||
/// Makes a copy of the value in its ASCII upper case equivalent.
|
||||
///
|
||||
/// 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`].
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// let lowercase_a = 97u8;
|
||||
///
|
||||
/// assert_eq!(65, lowercase_a.to_ascii_uppercase());
|
||||
/// ```
|
||||
///
|
||||
/// [`make_ascii_uppercase`]: #method.make_ascii_uppercase
|
||||
#[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
|
||||
#[inline]
|
||||
pub fn to_ascii_uppercase(&self) -> u8 {
|
||||
// Unset the fifth bit if this is a lowercase letter
|
||||
*self & !((self.is_ascii_lowercase() as u8) << 5)
|
||||
}
|
||||
|
||||
/// Makes a copy of the value in its ASCII lower case equivalent.
|
||||
///
|
||||
/// 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`].
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// let uppercase_a = 65u8;
|
||||
///
|
||||
/// assert_eq!(97, uppercase_a.to_ascii_lowercase());
|
||||
/// ```
|
||||
///
|
||||
/// [`make_ascii_lowercase`]: #method.make_ascii_lowercase
|
||||
#[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
|
||||
#[inline]
|
||||
pub fn to_ascii_lowercase(&self) -> u8 {
|
||||
// Set the fifth bit if this is an uppercase letter
|
||||
*self | ((self.is_ascii_uppercase() as u8) << 5)
|
||||
}
|
||||
|
||||
/// Checks that two values are an ASCII case-insensitive match.
|
||||
///
|
||||
/// This is equivalent to `to_ascii_lowercase(a) == to_ascii_lowercase(b)`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// let lowercase_a = 97u8;
|
||||
/// let uppercase_a = 65u8;
|
||||
///
|
||||
/// assert!(lowercase_a.eq_ignore_ascii_case(&uppercase_a));
|
||||
/// ```
|
||||
#[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
|
||||
#[inline]
|
||||
pub fn eq_ignore_ascii_case(&self, other: &u8) -> bool {
|
||||
self.to_ascii_lowercase() == other.to_ascii_lowercase()
|
||||
}
|
||||
|
||||
/// Converts this value to its ASCII upper case equivalent in-place.
|
||||
///
|
||||
/// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z',
|
||||
/// but non-ASCII letters are unchanged.
|
||||
///
|
||||
/// To return a new uppercased value without modifying the existing one, use
|
||||
/// [`to_ascii_uppercase`].
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// let mut byte = b'a';
|
||||
///
|
||||
/// byte.make_ascii_uppercase();
|
||||
///
|
||||
/// assert_eq!(b'A', byte);
|
||||
/// ```
|
||||
///
|
||||
/// [`to_ascii_uppercase`]: #method.to_ascii_uppercase
|
||||
#[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
|
||||
#[inline]
|
||||
pub fn make_ascii_uppercase(&mut self) {
|
||||
*self = self.to_ascii_uppercase();
|
||||
}
|
||||
|
||||
/// Converts this value to its ASCII lower case equivalent in-place.
|
||||
///
|
||||
/// ASCII letters 'A' to 'Z' are mapped to 'a' to 'z',
|
||||
/// but non-ASCII letters are unchanged.
|
||||
///
|
||||
/// To return a new lowercased value without modifying the existing one, use
|
||||
/// [`to_ascii_lowercase`].
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// let mut byte = b'A';
|
||||
///
|
||||
/// byte.make_ascii_lowercase();
|
||||
///
|
||||
/// assert_eq!(b'a', byte);
|
||||
/// ```
|
||||
///
|
||||
/// [`to_ascii_lowercase`]: #method.to_ascii_lowercase
|
||||
#[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
|
||||
#[inline]
|
||||
pub fn make_ascii_lowercase(&mut self) {
|
||||
*self = self.to_ascii_lowercase();
|
||||
}
|
||||
|
||||
/// Checks if the value is an ASCII alphabetic character:
|
||||
///
|
||||
/// - U+0041 'A' ..= U+005A 'Z', or
|
||||
/// - U+0061 'a' ..= U+007A 'z'.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// let uppercase_a = b'A';
|
||||
/// let uppercase_g = b'G';
|
||||
/// let a = b'a';
|
||||
/// let g = b'g';
|
||||
/// let zero = b'0';
|
||||
/// let percent = b'%';
|
||||
/// let space = b' ';
|
||||
/// let lf = b'\n';
|
||||
/// let esc = 0x1b_u8;
|
||||
///
|
||||
/// assert!(uppercase_a.is_ascii_alphabetic());
|
||||
/// assert!(uppercase_g.is_ascii_alphabetic());
|
||||
/// assert!(a.is_ascii_alphabetic());
|
||||
/// assert!(g.is_ascii_alphabetic());
|
||||
/// assert!(!zero.is_ascii_alphabetic());
|
||||
/// assert!(!percent.is_ascii_alphabetic());
|
||||
/// assert!(!space.is_ascii_alphabetic());
|
||||
/// assert!(!lf.is_ascii_alphabetic());
|
||||
/// assert!(!esc.is_ascii_alphabetic());
|
||||
/// ```
|
||||
#[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")]
|
||||
#[rustc_const_stable(feature = "const_ascii_ctype_on_intrinsics", since = "1.47.0")]
|
||||
#[inline]
|
||||
pub const fn is_ascii_alphabetic(&self) -> bool {
|
||||
matches!(*self, b'A'..=b'Z' | b'a'..=b'z')
|
||||
}
|
||||
|
||||
/// Checks if the value is an ASCII uppercase character:
|
||||
/// U+0041 'A' ..= U+005A 'Z'.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// let uppercase_a = b'A';
|
||||
/// let uppercase_g = b'G';
|
||||
/// let a = b'a';
|
||||
/// let g = b'g';
|
||||
/// let zero = b'0';
|
||||
/// let percent = b'%';
|
||||
/// let space = b' ';
|
||||
/// let lf = b'\n';
|
||||
/// let esc = 0x1b_u8;
|
||||
///
|
||||
/// assert!(uppercase_a.is_ascii_uppercase());
|
||||
/// assert!(uppercase_g.is_ascii_uppercase());
|
||||
/// assert!(!a.is_ascii_uppercase());
|
||||
/// assert!(!g.is_ascii_uppercase());
|
||||
/// assert!(!zero.is_ascii_uppercase());
|
||||
/// assert!(!percent.is_ascii_uppercase());
|
||||
/// assert!(!space.is_ascii_uppercase());
|
||||
/// assert!(!lf.is_ascii_uppercase());
|
||||
/// assert!(!esc.is_ascii_uppercase());
|
||||
/// ```
|
||||
#[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")]
|
||||
#[rustc_const_stable(feature = "const_ascii_ctype_on_intrinsics", since = "1.47.0")]
|
||||
#[inline]
|
||||
pub const fn is_ascii_uppercase(&self) -> bool {
|
||||
matches!(*self, b'A'..=b'Z')
|
||||
}
|
||||
|
||||
/// Checks if the value is an ASCII lowercase character:
|
||||
/// U+0061 'a' ..= U+007A 'z'.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// let uppercase_a = b'A';
|
||||
/// let uppercase_g = b'G';
|
||||
/// let a = b'a';
|
||||
/// let g = b'g';
|
||||
/// let zero = b'0';
|
||||
/// let percent = b'%';
|
||||
/// let space = b' ';
|
||||
/// let lf = b'\n';
|
||||
/// let esc = 0x1b_u8;
|
||||
///
|
||||
/// assert!(!uppercase_a.is_ascii_lowercase());
|
||||
/// assert!(!uppercase_g.is_ascii_lowercase());
|
||||
/// assert!(a.is_ascii_lowercase());
|
||||
/// assert!(g.is_ascii_lowercase());
|
||||
/// assert!(!zero.is_ascii_lowercase());
|
||||
/// assert!(!percent.is_ascii_lowercase());
|
||||
/// assert!(!space.is_ascii_lowercase());
|
||||
/// assert!(!lf.is_ascii_lowercase());
|
||||
/// assert!(!esc.is_ascii_lowercase());
|
||||
/// ```
|
||||
#[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")]
|
||||
#[rustc_const_stable(feature = "const_ascii_ctype_on_intrinsics", since = "1.47.0")]
|
||||
#[inline]
|
||||
pub const fn is_ascii_lowercase(&self) -> bool {
|
||||
matches!(*self, b'a'..=b'z')
|
||||
}
|
||||
|
||||
/// Checks if the value is an ASCII alphanumeric character:
|
||||
///
|
||||
/// - U+0041 'A' ..= U+005A 'Z', or
|
||||
/// - U+0061 'a' ..= U+007A 'z', or
|
||||
/// - U+0030 '0' ..= U+0039 '9'.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// let uppercase_a = b'A';
|
||||
/// let uppercase_g = b'G';
|
||||
/// let a = b'a';
|
||||
/// let g = b'g';
|
||||
/// let zero = b'0';
|
||||
/// let percent = b'%';
|
||||
/// let space = b' ';
|
||||
/// let lf = b'\n';
|
||||
/// let esc = 0x1b_u8;
|
||||
///
|
||||
/// assert!(uppercase_a.is_ascii_alphanumeric());
|
||||
/// assert!(uppercase_g.is_ascii_alphanumeric());
|
||||
/// assert!(a.is_ascii_alphanumeric());
|
||||
/// assert!(g.is_ascii_alphanumeric());
|
||||
/// assert!(zero.is_ascii_alphanumeric());
|
||||
/// assert!(!percent.is_ascii_alphanumeric());
|
||||
/// assert!(!space.is_ascii_alphanumeric());
|
||||
/// assert!(!lf.is_ascii_alphanumeric());
|
||||
/// assert!(!esc.is_ascii_alphanumeric());
|
||||
/// ```
|
||||
#[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")]
|
||||
#[rustc_const_stable(feature = "const_ascii_ctype_on_intrinsics", since = "1.47.0")]
|
||||
#[inline]
|
||||
pub const fn is_ascii_alphanumeric(&self) -> bool {
|
||||
matches!(*self, b'0'..=b'9' | b'A'..=b'Z' | b'a'..=b'z')
|
||||
}
|
||||
|
||||
/// Checks if the value is an ASCII decimal digit:
|
||||
/// U+0030 '0' ..= U+0039 '9'.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// let uppercase_a = b'A';
|
||||
/// let uppercase_g = b'G';
|
||||
/// let a = b'a';
|
||||
/// let g = b'g';
|
||||
/// let zero = b'0';
|
||||
/// let percent = b'%';
|
||||
/// let space = b' ';
|
||||
/// let lf = b'\n';
|
||||
/// let esc = 0x1b_u8;
|
||||
///
|
||||
/// assert!(!uppercase_a.is_ascii_digit());
|
||||
/// assert!(!uppercase_g.is_ascii_digit());
|
||||
/// assert!(!a.is_ascii_digit());
|
||||
/// assert!(!g.is_ascii_digit());
|
||||
/// assert!(zero.is_ascii_digit());
|
||||
/// assert!(!percent.is_ascii_digit());
|
||||
/// assert!(!space.is_ascii_digit());
|
||||
/// assert!(!lf.is_ascii_digit());
|
||||
/// assert!(!esc.is_ascii_digit());
|
||||
/// ```
|
||||
#[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")]
|
||||
#[rustc_const_stable(feature = "const_ascii_ctype_on_intrinsics", since = "1.47.0")]
|
||||
#[inline]
|
||||
pub const fn is_ascii_digit(&self) -> bool {
|
||||
matches!(*self, b'0'..=b'9')
|
||||
}
|
||||
|
||||
/// Checks if the value is an ASCII hexadecimal digit:
|
||||
///
|
||||
/// - U+0030 '0' ..= U+0039 '9', or
|
||||
/// - U+0041 'A' ..= U+0046 'F', or
|
||||
/// - U+0061 'a' ..= U+0066 'f'.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// let uppercase_a = b'A';
|
||||
/// let uppercase_g = b'G';
|
||||
/// let a = b'a';
|
||||
/// let g = b'g';
|
||||
/// let zero = b'0';
|
||||
/// let percent = b'%';
|
||||
/// let space = b' ';
|
||||
/// let lf = b'\n';
|
||||
/// let esc = 0x1b_u8;
|
||||
///
|
||||
/// assert!(uppercase_a.is_ascii_hexdigit());
|
||||
/// assert!(!uppercase_g.is_ascii_hexdigit());
|
||||
/// assert!(a.is_ascii_hexdigit());
|
||||
/// assert!(!g.is_ascii_hexdigit());
|
||||
/// assert!(zero.is_ascii_hexdigit());
|
||||
/// assert!(!percent.is_ascii_hexdigit());
|
||||
/// assert!(!space.is_ascii_hexdigit());
|
||||
/// assert!(!lf.is_ascii_hexdigit());
|
||||
/// assert!(!esc.is_ascii_hexdigit());
|
||||
/// ```
|
||||
#[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")]
|
||||
#[rustc_const_stable(feature = "const_ascii_ctype_on_intrinsics", since = "1.47.0")]
|
||||
#[inline]
|
||||
pub const fn is_ascii_hexdigit(&self) -> bool {
|
||||
matches!(*self, b'0'..=b'9' | b'A'..=b'F' | b'a'..=b'f')
|
||||
}
|
||||
|
||||
/// Checks if the value is an ASCII punctuation character:
|
||||
///
|
||||
/// - U+0021 ..= U+002F `! " # $ % & ' ( ) * + , - . /`, or
|
||||
/// - U+003A ..= U+0040 `: ; < = > ? @`, or
|
||||
/// - U+005B ..= U+0060 ``[ \ ] ^ _ ` ``, or
|
||||
/// - U+007B ..= U+007E `{ | } ~`
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// let uppercase_a = b'A';
|
||||
/// let uppercase_g = b'G';
|
||||
/// let a = b'a';
|
||||
/// let g = b'g';
|
||||
/// let zero = b'0';
|
||||
/// let percent = b'%';
|
||||
/// let space = b' ';
|
||||
/// let lf = b'\n';
|
||||
/// let esc = 0x1b_u8;
|
||||
///
|
||||
/// assert!(!uppercase_a.is_ascii_punctuation());
|
||||
/// assert!(!uppercase_g.is_ascii_punctuation());
|
||||
/// assert!(!a.is_ascii_punctuation());
|
||||
/// assert!(!g.is_ascii_punctuation());
|
||||
/// assert!(!zero.is_ascii_punctuation());
|
||||
/// assert!(percent.is_ascii_punctuation());
|
||||
/// assert!(!space.is_ascii_punctuation());
|
||||
/// assert!(!lf.is_ascii_punctuation());
|
||||
/// assert!(!esc.is_ascii_punctuation());
|
||||
/// ```
|
||||
#[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")]
|
||||
#[rustc_const_stable(feature = "const_ascii_ctype_on_intrinsics", since = "1.47.0")]
|
||||
#[inline]
|
||||
pub const fn is_ascii_punctuation(&self) -> bool {
|
||||
matches!(*self, b'!'..=b'/' | b':'..=b'@' | b'['..=b'`' | b'{'..=b'~')
|
||||
}
|
||||
|
||||
/// Checks if the value is an ASCII graphic character:
|
||||
/// U+0021 '!' ..= U+007E '~'.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// let uppercase_a = b'A';
|
||||
/// let uppercase_g = b'G';
|
||||
/// let a = b'a';
|
||||
/// let g = b'g';
|
||||
/// let zero = b'0';
|
||||
/// let percent = b'%';
|
||||
/// let space = b' ';
|
||||
/// let lf = b'\n';
|
||||
/// let esc = 0x1b_u8;
|
||||
///
|
||||
/// assert!(uppercase_a.is_ascii_graphic());
|
||||
/// assert!(uppercase_g.is_ascii_graphic());
|
||||
/// assert!(a.is_ascii_graphic());
|
||||
/// assert!(g.is_ascii_graphic());
|
||||
/// assert!(zero.is_ascii_graphic());
|
||||
/// assert!(percent.is_ascii_graphic());
|
||||
/// assert!(!space.is_ascii_graphic());
|
||||
/// assert!(!lf.is_ascii_graphic());
|
||||
/// assert!(!esc.is_ascii_graphic());
|
||||
/// ```
|
||||
#[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")]
|
||||
#[rustc_const_stable(feature = "const_ascii_ctype_on_intrinsics", since = "1.47.0")]
|
||||
#[inline]
|
||||
pub const fn is_ascii_graphic(&self) -> bool {
|
||||
matches!(*self, b'!'..=b'~')
|
||||
}
|
||||
|
||||
/// Checks if the value is an ASCII whitespace character:
|
||||
/// U+0020 SPACE, U+0009 HORIZONTAL TAB, U+000A LINE FEED,
|
||||
/// U+000C FORM FEED, or U+000D CARRIAGE RETURN.
|
||||
///
|
||||
/// Rust uses the WhatWG Infra Standard's [definition of ASCII
|
||||
/// whitespace][infra-aw]. There are several other definitions in
|
||||
/// wide use. For instance, [the POSIX locale][pct] includes
|
||||
/// U+000B VERTICAL TAB as well as all the above characters,
|
||||
/// but—from the very same specification—[the default rule for
|
||||
/// "field splitting" in the Bourne shell][bfs] considers *only*
|
||||
/// SPACE, HORIZONTAL TAB, and LINE FEED as whitespace.
|
||||
///
|
||||
/// If you are writing a program that will process an existing
|
||||
/// file format, check what that format's definition of whitespace is
|
||||
/// before using this function.
|
||||
///
|
||||
/// [infra-aw]: https://infra.spec.whatwg.org/#ascii-whitespace
|
||||
/// [pct]: http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap07.html#tag_07_03_01
|
||||
/// [bfs]: http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_06_05
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// let uppercase_a = b'A';
|
||||
/// let uppercase_g = b'G';
|
||||
/// let a = b'a';
|
||||
/// let g = b'g';
|
||||
/// let zero = b'0';
|
||||
/// let percent = b'%';
|
||||
/// let space = b' ';
|
||||
/// let lf = b'\n';
|
||||
/// let esc = 0x1b_u8;
|
||||
///
|
||||
/// assert!(!uppercase_a.is_ascii_whitespace());
|
||||
/// assert!(!uppercase_g.is_ascii_whitespace());
|
||||
/// assert!(!a.is_ascii_whitespace());
|
||||
/// assert!(!g.is_ascii_whitespace());
|
||||
/// assert!(!zero.is_ascii_whitespace());
|
||||
/// assert!(!percent.is_ascii_whitespace());
|
||||
/// assert!(space.is_ascii_whitespace());
|
||||
/// assert!(lf.is_ascii_whitespace());
|
||||
/// assert!(!esc.is_ascii_whitespace());
|
||||
/// ```
|
||||
#[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")]
|
||||
#[rustc_const_stable(feature = "const_ascii_ctype_on_intrinsics", since = "1.47.0")]
|
||||
#[inline]
|
||||
pub const fn is_ascii_whitespace(&self) -> bool {
|
||||
matches!(*self, b'\t' | b'\n' | b'\x0C' | b'\r' | b' ')
|
||||
}
|
||||
|
||||
/// Checks if the value is an ASCII control character:
|
||||
/// U+0000 NUL ..= U+001F UNIT SEPARATOR, or U+007F DELETE.
|
||||
/// Note that most ASCII whitespace characters are control
|
||||
/// characters, but SPACE is not.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// let uppercase_a = b'A';
|
||||
/// let uppercase_g = b'G';
|
||||
/// let a = b'a';
|
||||
/// let g = b'g';
|
||||
/// let zero = b'0';
|
||||
/// let percent = b'%';
|
||||
/// let space = b' ';
|
||||
/// let lf = b'\n';
|
||||
/// let esc = 0x1b_u8;
|
||||
///
|
||||
/// assert!(!uppercase_a.is_ascii_control());
|
||||
/// assert!(!uppercase_g.is_ascii_control());
|
||||
/// assert!(!a.is_ascii_control());
|
||||
/// assert!(!g.is_ascii_control());
|
||||
/// assert!(!zero.is_ascii_control());
|
||||
/// assert!(!percent.is_ascii_control());
|
||||
/// assert!(!space.is_ascii_control());
|
||||
/// assert!(lf.is_ascii_control());
|
||||
/// assert!(esc.is_ascii_control());
|
||||
/// ```
|
||||
#[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")]
|
||||
#[rustc_const_stable(feature = "const_ascii_ctype_on_intrinsics", since = "1.47.0")]
|
||||
#[inline]
|
||||
pub const fn is_ascii_control(&self) -> bool {
|
||||
matches!(*self, b'\0'..=b'\x1F' | b'\x7F')
|
||||
}
|
||||
}
|
||||
|
||||
#[lang = "u16"]
|
||||
impl u16 {
|
||||
uint_impl! { u16, u16, 16, 65535, "", "", 4, "0xa003", "0x3a", "0x1234", "0x3412", "0x2c48",
|
||||
"[0x34, 0x12]", "[0x12, 0x34]", "", "" }
|
||||
}
|
||||
|
||||
#[lang = "u32"]
|
||||
impl u32 {
|
||||
uint_impl! { u32, u32, 32, 4294967295, "", "", 8, "0x10000b3", "0xb301", "0x12345678",
|
||||
"0x78563412", "0x1e6a2c48", "[0x78, 0x56, 0x34, 0x12]", "[0x12, 0x34, 0x56, 0x78]", "", "" }
|
||||
}
|
||||
|
||||
#[lang = "u64"]
|
||||
impl u64 {
|
||||
uint_impl! { u64, u64, 64, 18446744073709551615, "", "", 12, "0xaa00000000006e1", "0x6e10aa",
|
||||
"0x1234567890123456", "0x5634129078563412", "0x6a2c48091e6a2c48",
|
||||
"[0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]",
|
||||
"[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]",
|
||||
"", ""}
|
||||
}
|
||||
|
||||
#[lang = "u128"]
|
||||
impl u128 {
|
||||
uint_impl! { u128, u128, 128, 340282366920938463463374607431768211455, "", "", 16,
|
||||
"0x13f40000000000000000000000004f76", "0x4f7613f4", "0x12345678901234567890123456789012",
|
||||
"0x12907856341290785634129078563412", "0x48091e6a2c48091e6a2c48091e6a2c48",
|
||||
"[0x12, 0x90, 0x78, 0x56, 0x34, 0x12, 0x90, 0x78, \
|
||||
0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]",
|
||||
"[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56, \
|
||||
0x78, 0x90, 0x12, 0x34, 0x56, 0x78, 0x90, 0x12]",
|
||||
"", ""}
|
||||
}
|
||||
|
||||
#[cfg(target_pointer_width = "16")]
|
||||
#[lang = "usize"]
|
||||
impl usize {
|
||||
uint_impl! { usize, u16, 16, 65535, "", "", 4, "0xa003", "0x3a", "0x1234", "0x3412", "0x2c48",
|
||||
"[0x34, 0x12]", "[0x12, 0x34]",
|
||||
usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!() }
|
||||
}
|
||||
#[cfg(target_pointer_width = "32")]
|
||||
#[lang = "usize"]
|
||||
impl usize {
|
||||
uint_impl! { usize, u32, 32, 4294967295, "", "", 8, "0x10000b3", "0xb301", "0x12345678",
|
||||
"0x78563412", "0x1e6a2c48", "[0x78, 0x56, 0x34, 0x12]", "[0x12, 0x34, 0x56, 0x78]",
|
||||
usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!() }
|
||||
}
|
||||
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
#[lang = "usize"]
|
||||
impl usize {
|
||||
uint_impl! { usize, u64, 64, 18446744073709551615, "", "", 12, "0xaa00000000006e1", "0x6e10aa",
|
||||
"0x1234567890123456", "0x5634129078563412", "0x6a2c48091e6a2c48",
|
||||
"[0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]",
|
||||
"[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]",
|
||||
usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!() }
|
||||
}
|
||||
|
||||
/// A classification of floating point numbers.
|
||||
///
|
||||
/// This `enum` is used as the return type for [`f32::classify`] and [`f64::classify`]. See
|
||||
/// their documentation for more.
|
||||
///
|
||||
/// [`f32::classify`]: ../../std/primitive.f32.html#method.classify
|
||||
/// [`f64::classify`]: ../../std/primitive.f64.html#method.classify
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::num::FpCategory;
|
||||
///
|
||||
/// let num = 12.4_f32;
|
||||
/// let inf = f32::INFINITY;
|
||||
/// let zero = 0f32;
|
||||
/// let sub: f32 = 1.1754942e-38;
|
||||
/// let nan = f32::NAN;
|
||||
///
|
||||
/// assert_eq!(num.classify(), FpCategory::Normal);
|
||||
/// assert_eq!(inf.classify(), FpCategory::Infinite);
|
||||
/// assert_eq!(zero.classify(), FpCategory::Zero);
|
||||
/// assert_eq!(nan.classify(), FpCategory::Nan);
|
||||
/// assert_eq!(sub.classify(), FpCategory::Subnormal);
|
||||
/// ```
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub enum FpCategory {
|
||||
/// "Not a Number", often obtained by dividing by zero.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
Nan,
|
||||
|
||||
/// Positive or negative infinity.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
Infinite,
|
||||
|
||||
/// Positive or negative zero.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
Zero,
|
||||
|
||||
/// De-normalized floating point representation (less precise than `Normal`).
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
Subnormal,
|
||||
|
||||
/// A regular floating point number.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
Normal,
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
trait FromStrRadixHelper: PartialOrd + Copy {
|
||||
fn min_value() -> Self;
|
||||
fn max_value() -> Self;
|
||||
fn from_u32(u: u32) -> Self;
|
||||
fn checked_mul(&self, other: u32) -> Option<Self>;
|
||||
fn checked_sub(&self, other: u32) -> Option<Self>;
|
||||
fn checked_add(&self, other: u32) -> Option<Self>;
|
||||
}
|
||||
|
||||
macro_rules! from_str_radix_int_impl {
|
||||
($($t:ty)*) => {$(
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl FromStr for $t {
|
||||
type Err = ParseIntError;
|
||||
fn from_str(src: &str) -> Result<Self, ParseIntError> {
|
||||
from_str_radix(src, 10)
|
||||
}
|
||||
}
|
||||
)*}
|
||||
}
|
||||
from_str_radix_int_impl! { isize i8 i16 i32 i64 i128 usize u8 u16 u32 u64 u128 }
|
||||
|
||||
macro_rules! doit {
|
||||
($($t:ty)*) => ($(impl FromStrRadixHelper for $t {
|
||||
#[inline]
|
||||
fn min_value() -> Self { Self::MIN }
|
||||
#[inline]
|
||||
fn max_value() -> Self { Self::MAX }
|
||||
#[inline]
|
||||
fn from_u32(u: u32) -> Self { u as Self }
|
||||
#[inline]
|
||||
fn checked_mul(&self, other: u32) -> Option<Self> {
|
||||
Self::checked_mul(*self, other as Self)
|
||||
}
|
||||
#[inline]
|
||||
fn checked_sub(&self, other: u32) -> Option<Self> {
|
||||
Self::checked_sub(*self, other as Self)
|
||||
}
|
||||
#[inline]
|
||||
fn checked_add(&self, other: u32) -> Option<Self> {
|
||||
Self::checked_add(*self, other as Self)
|
||||
}
|
||||
})*)
|
||||
}
|
||||
doit! { i8 i16 i32 i64 i128 isize u8 u16 u32 u64 u128 usize }
|
||||
|
||||
fn from_str_radix<T: FromStrRadixHelper>(src: &str, radix: u32) -> Result<T, ParseIntError> {
|
||||
use self::IntErrorKind::*;
|
||||
use self::ParseIntError as PIE;
|
||||
|
||||
assert!(
|
||||
radix >= 2 && radix <= 36,
|
||||
"from_str_radix_int: must lie in the range `[2, 36]` - found {}",
|
||||
radix
|
||||
);
|
||||
|
||||
if src.is_empty() {
|
||||
return Err(PIE { kind: Empty });
|
||||
}
|
||||
|
||||
let is_signed_ty = T::from_u32(0) > T::min_value();
|
||||
|
||||
// all valid digits are ascii, so we will just iterate over the utf8 bytes
|
||||
// and cast them to chars. .to_digit() will safely return None for anything
|
||||
// other than a valid ascii digit for the given radix, including the first-byte
|
||||
// of multi-byte sequences
|
||||
let src = src.as_bytes();
|
||||
|
||||
let (is_positive, digits) = match src[0] {
|
||||
b'+' | b'-' if src[1..].is_empty() => {
|
||||
return Err(PIE { kind: InvalidDigit });
|
||||
}
|
||||
b'+' => (true, &src[1..]),
|
||||
b'-' if is_signed_ty => (false, &src[1..]),
|
||||
_ => (true, src),
|
||||
};
|
||||
|
||||
let mut result = T::from_u32(0);
|
||||
if is_positive {
|
||||
// The number is positive
|
||||
for &c in digits {
|
||||
let x = match (c as char).to_digit(radix) {
|
||||
Some(x) => x,
|
||||
None => return Err(PIE { kind: InvalidDigit }),
|
||||
};
|
||||
result = match result.checked_mul(radix) {
|
||||
Some(result) => result,
|
||||
None => return Err(PIE { kind: PosOverflow }),
|
||||
};
|
||||
result = match result.checked_add(x) {
|
||||
Some(result) => result,
|
||||
None => return Err(PIE { kind: PosOverflow }),
|
||||
};
|
||||
}
|
||||
} else {
|
||||
// The number is negative
|
||||
for &c in digits {
|
||||
let x = match (c as char).to_digit(radix) {
|
||||
Some(x) => x,
|
||||
None => return Err(PIE { kind: InvalidDigit }),
|
||||
};
|
||||
result = match result.checked_mul(radix) {
|
||||
Some(result) => result,
|
||||
None => return Err(PIE { kind: NegOverflow }),
|
||||
};
|
||||
result = match result.checked_sub(x) {
|
||||
Some(result) => result,
|
||||
None => return Err(PIE { kind: NegOverflow }),
|
||||
};
|
||||
}
|
||||
}
|
||||
Ok(result)
|
||||
}
|
||||
191
libgrust/rustc-lib/core/src/num/nonzero.rs
Normal file
191
libgrust/rustc-lib/core/src/num/nonzero.rs
Normal file
@@ -0,0 +1,191 @@
|
||||
//! Definitions of integer that is known not to equal zero.
|
||||
|
||||
use crate::fmt;
|
||||
use crate::ops::{BitOr, BitOrAssign};
|
||||
use crate::str::FromStr;
|
||||
|
||||
use super::from_str_radix;
|
||||
use super::{IntErrorKind, ParseIntError};
|
||||
|
||||
macro_rules! doc_comment {
|
||||
($x:expr, $($tt:tt)*) => {
|
||||
#[doc = $x]
|
||||
$($tt)*
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! impl_nonzero_fmt {
|
||||
( #[$stability: meta] ( $( $Trait: ident ),+ ) for $Ty: ident ) => {
|
||||
$(
|
||||
#[$stability]
|
||||
impl fmt::$Trait for $Ty {
|
||||
#[inline]
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
self.get().fmt(f)
|
||||
}
|
||||
}
|
||||
)+
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! nonzero_integers {
|
||||
( $( #[$stability: meta] $Ty: ident($Int: ty); )+ ) => {
|
||||
$(
|
||||
doc_comment! {
|
||||
concat!("An integer that is known not to equal zero.
|
||||
|
||||
This enables some memory layout optimization.
|
||||
For example, `Option<", stringify!($Ty), ">` is the same size as `", stringify!($Int), "`:
|
||||
|
||||
```rust
|
||||
use std::mem::size_of;
|
||||
assert_eq!(size_of::<Option<core::num::", stringify!($Ty), ">>(), size_of::<", stringify!($Int),
|
||||
">());
|
||||
```"),
|
||||
#[$stability]
|
||||
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
|
||||
#[repr(transparent)]
|
||||
#[rustc_layout_scalar_valid_range_start(1)]
|
||||
#[rustc_nonnull_optimization_guaranteed]
|
||||
pub struct $Ty($Int);
|
||||
}
|
||||
|
||||
impl $Ty {
|
||||
/// Creates a non-zero without checking the value.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// The value must not be zero.
|
||||
#[$stability]
|
||||
#[rustc_const_stable(feature = "nonzero", since = "1.34.0")]
|
||||
#[inline]
|
||||
pub const unsafe fn new_unchecked(n: $Int) -> Self {
|
||||
// SAFETY: this is guaranteed to be safe by the caller.
|
||||
unsafe { Self(n) }
|
||||
}
|
||||
|
||||
/// Creates a non-zero if the given value is not zero.
|
||||
#[$stability]
|
||||
#[rustc_const_stable(feature = "const_nonzero_int_methods", since = "1.47.0")]
|
||||
#[inline]
|
||||
pub const fn new(n: $Int) -> Option<Self> {
|
||||
if n != 0 {
|
||||
// SAFETY: we just checked that there's no `0`
|
||||
Some(unsafe { Self(n) })
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the value as a primitive type.
|
||||
#[$stability]
|
||||
#[inline]
|
||||
#[rustc_const_stable(feature = "nonzero", since = "1.34.0")]
|
||||
pub const fn get(self) -> $Int {
|
||||
self.0
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#[stable(feature = "from_nonzero", since = "1.31.0")]
|
||||
impl From<$Ty> for $Int {
|
||||
doc_comment! {
|
||||
concat!(
|
||||
"Converts a `", stringify!($Ty), "` into an `", stringify!($Int), "`"),
|
||||
#[inline]
|
||||
fn from(nonzero: $Ty) -> Self {
|
||||
nonzero.0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "nonzero_bitor", since = "1.45.0")]
|
||||
impl BitOr for $Ty {
|
||||
type Output = Self;
|
||||
#[inline]
|
||||
fn bitor(self, rhs: Self) -> Self::Output {
|
||||
// SAFETY: since `self` and `rhs` are both nonzero, the
|
||||
// result of the bitwise-or will be nonzero.
|
||||
unsafe { $Ty::new_unchecked(self.get() | rhs.get()) }
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "nonzero_bitor", since = "1.45.0")]
|
||||
impl BitOr<$Int> for $Ty {
|
||||
type Output = Self;
|
||||
#[inline]
|
||||
fn bitor(self, rhs: $Int) -> Self::Output {
|
||||
// SAFETY: since `self` is nonzero, the result of the
|
||||
// bitwise-or will be nonzero regardless of the value of
|
||||
// `rhs`.
|
||||
unsafe { $Ty::new_unchecked(self.get() | rhs) }
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "nonzero_bitor", since = "1.45.0")]
|
||||
impl BitOr<$Ty> for $Int {
|
||||
type Output = $Ty;
|
||||
#[inline]
|
||||
fn bitor(self, rhs: $Ty) -> Self::Output {
|
||||
// SAFETY: since `rhs` is nonzero, the result of the
|
||||
// bitwise-or will be nonzero regardless of the value of
|
||||
// `self`.
|
||||
unsafe { $Ty::new_unchecked(self | rhs.get()) }
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "nonzero_bitor", since = "1.45.0")]
|
||||
impl BitOrAssign for $Ty {
|
||||
#[inline]
|
||||
fn bitor_assign(&mut self, rhs: Self) {
|
||||
*self = *self | rhs;
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "nonzero_bitor", since = "1.45.0")]
|
||||
impl BitOrAssign<$Int> for $Ty {
|
||||
#[inline]
|
||||
fn bitor_assign(&mut self, rhs: $Int) {
|
||||
*self = *self | rhs;
|
||||
}
|
||||
}
|
||||
|
||||
impl_nonzero_fmt! {
|
||||
#[$stability] (Debug, Display, Binary, Octal, LowerHex, UpperHex) for $Ty
|
||||
}
|
||||
)+
|
||||
}
|
||||
}
|
||||
|
||||
nonzero_integers! {
|
||||
#[stable(feature = "nonzero", since = "1.28.0")] NonZeroU8(u8);
|
||||
#[stable(feature = "nonzero", since = "1.28.0")] NonZeroU16(u16);
|
||||
#[stable(feature = "nonzero", since = "1.28.0")] NonZeroU32(u32);
|
||||
#[stable(feature = "nonzero", since = "1.28.0")] NonZeroU64(u64);
|
||||
#[stable(feature = "nonzero", since = "1.28.0")] NonZeroU128(u128);
|
||||
#[stable(feature = "nonzero", since = "1.28.0")] NonZeroUsize(usize);
|
||||
#[stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroI8(i8);
|
||||
#[stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroI16(i16);
|
||||
#[stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroI32(i32);
|
||||
#[stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroI64(i64);
|
||||
#[stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroI128(i128);
|
||||
#[stable(feature = "signed_nonzero", since = "1.34.0")] NonZeroIsize(isize);
|
||||
}
|
||||
|
||||
macro_rules! from_str_radix_nzint_impl {
|
||||
($($t:ty)*) => {$(
|
||||
#[stable(feature = "nonzero_parse", since = "1.35.0")]
|
||||
impl FromStr for $t {
|
||||
type Err = ParseIntError;
|
||||
fn from_str(src: &str) -> Result<Self, Self::Err> {
|
||||
Self::new(from_str_radix(src, 10)?)
|
||||
.ok_or(ParseIntError {
|
||||
kind: IntErrorKind::Zero
|
||||
})
|
||||
}
|
||||
}
|
||||
)*}
|
||||
}
|
||||
|
||||
from_str_radix_nzint_impl! { NonZeroU8 NonZeroU16 NonZeroU32 NonZeroU64 NonZeroU128 NonZeroUsize
|
||||
NonZeroI8 NonZeroI16 NonZeroI32 NonZeroI64 NonZeroI128 NonZeroIsize }
|
||||
10
libgrust/rustc-lib/core/src/num/shells/i128.rs
Normal file
10
libgrust/rustc-lib/core/src/num/shells/i128.rs
Normal file
@@ -0,0 +1,10 @@
|
||||
//! The 128-bit signed integer type.
|
||||
//!
|
||||
//! *[See also the `i128` primitive type](../../std/primitive.i128.html).*
|
||||
//!
|
||||
//! Although using these constants won’t cause compilation warnings,
|
||||
//! new code should use the associated constants directly on the primitive type.
|
||||
|
||||
#![stable(feature = "i128", since = "1.26.0")]
|
||||
|
||||
int_module! { i128, #[stable(feature = "i128", since="1.26.0")] }
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user