Auto merge of #59471 - cuviper:rollup, r=cuviper
Rollup of 18 pull requests Successful merges: - #57293 (Make some lints incremental) - #57565 (syntax: Remove warning for unnecessary path disambiguators) - #58253 (librustc_driver => 2018) - #58837 (librustc_interface => 2018) - #59268 (Add suggestion to use `&*var` when `&str: From<String>` is expected) - #59283 (Make ASCII case conversions more than 4× faster) - #59284 (adjust MaybeUninit API to discussions) - #59372 (add rustfix-able suggestions to trim_{left,right} deprecations) - #59390 (Make `ptr::eq` documentation mention fat-pointer behavior) - #59393 (Refactor tuple comparison tests) - #59420 ([CI] record docker image info for reuse) - #59421 (Reject integer suffix when tuple indexing) - #59430 (Renames `EvalContext` to `InterpretCx`) - #59439 (Generalize diagnostic for `x = y` where `bool` is the expected type) - #59449 (fix: Make incremental artifact deletion more robust) - #59451 (Add `Default` to `std::alloc::System`) - #59459 (Add some tests) - #59460 (Include id in Thread's Debug implementation) Failed merges: r? @ghost
This commit is contained in:
commit
d20e000272
84 changed files with 1474 additions and 698 deletions
|
|
@ -12,6 +12,9 @@ ci_dir="`dirname $docker_dir`"
|
|||
src_dir="`dirname $ci_dir`"
|
||||
root_dir="`dirname $src_dir`"
|
||||
|
||||
objdir=$root_dir/obj
|
||||
dist=$objdir/build/dist
|
||||
|
||||
source "$ci_dir/shared.sh"
|
||||
|
||||
travis_fold start build_docker
|
||||
|
|
@ -77,6 +80,11 @@ if [ -f "$docker_dir/$image/Dockerfile" ]; then
|
|||
else
|
||||
echo "Looks like docker image is the same as before, not uploading"
|
||||
fi
|
||||
# Record the container image for reuse, e.g. by rustup.rs builds
|
||||
info="$dist/image-$image.txt"
|
||||
mkdir -p "$dist"
|
||||
echo "$url" >"$info"
|
||||
echo "$digest" >>"$info"
|
||||
fi
|
||||
elif [ -f "$docker_dir/disabled/$image/Dockerfile" ]; then
|
||||
if [ -n "$TRAVIS_OS_NAME" ]; then
|
||||
|
|
@ -99,8 +107,6 @@ fi
|
|||
travis_fold end build_docker
|
||||
travis_time_finish
|
||||
|
||||
objdir=$root_dir/obj
|
||||
|
||||
mkdir -p $HOME/.cargo
|
||||
mkdir -p $objdir/tmp
|
||||
mkdir -p $objdir/cores
|
||||
|
|
|
|||
|
|
@ -138,3 +138,16 @@ error[E0277]: `&str` is not an iterator
|
|||
= help: the trait `std::iter::Iterator` is not implemented for `&str`
|
||||
= note: required by `std::iter::IntoIterator::into_iter`
|
||||
```
|
||||
|
||||
If you need to filter on multiple attributes, you can use `all`, `any` or
|
||||
`not` in the following way:
|
||||
|
||||
```rust,compile_fail
|
||||
#[rustc_on_unimplemented(
|
||||
on(
|
||||
all(_Self="&str", T="std::string::String"),
|
||||
note="you can coerce a `{T}` into a `{Self}` by writing `&*variable`"
|
||||
)
|
||||
)]
|
||||
pub trait From<T>: Sized { /* ... */ }
|
||||
```
|
||||
|
|
|
|||
|
|
@ -109,7 +109,7 @@ impl<K, V> LeafNode<K, V> {
|
|||
keys: uninitialized_array![_; CAPACITY],
|
||||
vals: uninitialized_array![_; CAPACITY],
|
||||
parent: ptr::null(),
|
||||
parent_idx: MaybeUninit::uninitialized(),
|
||||
parent_idx: MaybeUninit::uninit(),
|
||||
len: 0
|
||||
}
|
||||
}
|
||||
|
|
@ -129,7 +129,7 @@ unsafe impl Sync for NodeHeader<(), ()> {}
|
|||
// ever take a pointer past the first key.
|
||||
static EMPTY_ROOT_NODE: NodeHeader<(), ()> = NodeHeader {
|
||||
parent: ptr::null(),
|
||||
parent_idx: MaybeUninit::uninitialized(),
|
||||
parent_idx: MaybeUninit::uninit(),
|
||||
len: 0,
|
||||
keys_start: [],
|
||||
};
|
||||
|
|
@ -261,7 +261,7 @@ impl<K, V> Root<K, V> {
|
|||
-> NodeRef<marker::Mut<'_>, K, V, marker::Internal> {
|
||||
debug_assert!(!self.is_shared_root());
|
||||
let mut new_node = Box::new(unsafe { InternalNode::new() });
|
||||
new_node.edges[0].set(unsafe { BoxedNode::from_ptr(self.node.as_ptr()) });
|
||||
new_node.edges[0].write(unsafe { BoxedNode::from_ptr(self.node.as_ptr()) });
|
||||
|
||||
self.node = BoxedNode::from_internal(new_node);
|
||||
self.height += 1;
|
||||
|
|
@ -737,7 +737,7 @@ impl<'a, K, V> NodeRef<marker::Mut<'a>, K, V, marker::Internal> {
|
|||
unsafe {
|
||||
ptr::write(self.keys_mut().get_unchecked_mut(idx), key);
|
||||
ptr::write(self.vals_mut().get_unchecked_mut(idx), val);
|
||||
self.as_internal_mut().edges.get_unchecked_mut(idx + 1).set(edge.node);
|
||||
self.as_internal_mut().edges.get_unchecked_mut(idx + 1).write(edge.node);
|
||||
|
||||
(*self.as_leaf_mut()).len += 1;
|
||||
|
||||
|
|
@ -1080,7 +1080,7 @@ impl<'a, K, V> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Internal>, marker::
|
|||
let mut child = self.descend();
|
||||
unsafe {
|
||||
(*child.as_leaf_mut()).parent = ptr;
|
||||
(*child.as_leaf_mut()).parent_idx.set(idx);
|
||||
(*child.as_leaf_mut()).parent_idx.write(idx);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
349
src/libcore/benches/ascii.rs
Normal file
349
src/libcore/benches/ascii.rs
Normal file
|
|
@ -0,0 +1,349 @@
|
|||
// 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 == 0b10011000
|
||||
//
|
||||
// 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]) {
|
||||
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]) {
|
||||
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: &'static str = "Alice's";
|
||||
const MEDIUM: &'static str = "Alice's Adventures in Wonderland";
|
||||
const LONG: &'static 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]
|
||||
"#);
|
||||
|
||||
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::*;
|
||||
|
||||
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,
|
||||
];
|
||||
|
|
@ -5,6 +5,7 @@ extern crate core;
|
|||
extern crate test;
|
||||
|
||||
mod any;
|
||||
mod ascii;
|
||||
mod char;
|
||||
mod hash;
|
||||
mod iter;
|
||||
|
|
|
|||
|
|
@ -363,6 +363,12 @@ pub trait Into<T>: Sized {
|
|||
/// [`from`]: trait.From.html#tymethod.from
|
||||
/// [book]: ../../book/ch09-00-error-handling.html
|
||||
#[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.
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
|
|
|
|||
|
|
@ -10,8 +10,8 @@ fn float_to_decimal_common_exact<T>(fmt: &mut Formatter, num: &T,
|
|||
where T: flt2dec::DecodableFloat
|
||||
{
|
||||
unsafe {
|
||||
let mut buf = MaybeUninit::<[u8; 1024]>::uninitialized(); // enough for f32 and f64
|
||||
let mut parts = MaybeUninit::<[flt2dec::Part; 4]>::uninitialized();
|
||||
let mut buf = MaybeUninit::<[u8; 1024]>::uninit(); // enough for f32 and f64
|
||||
let mut parts = MaybeUninit::<[flt2dec::Part; 4]>::uninit();
|
||||
// FIXME(#53491): Technically, this is calling `get_mut` on an uninitialized
|
||||
// `MaybeUninit` (here and elsewhere in this file). Revisit this once
|
||||
// we decided whether that is valid or not.
|
||||
|
|
@ -32,8 +32,8 @@ fn float_to_decimal_common_shortest<T>(fmt: &mut Formatter, num: &T,
|
|||
{
|
||||
unsafe {
|
||||
// enough for f32 and f64
|
||||
let mut buf = MaybeUninit::<[u8; flt2dec::MAX_SIG_DIGITS]>::uninitialized();
|
||||
let mut parts = MaybeUninit::<[flt2dec::Part; 4]>::uninitialized();
|
||||
let mut buf = MaybeUninit::<[u8; flt2dec::MAX_SIG_DIGITS]>::uninit();
|
||||
let mut parts = MaybeUninit::<[flt2dec::Part; 4]>::uninit();
|
||||
// FIXME(#53491)
|
||||
let formatted = flt2dec::to_shortest_str(flt2dec::strategy::grisu::format_shortest, *num,
|
||||
sign, precision, false, buf.get_mut(),
|
||||
|
|
@ -71,8 +71,8 @@ fn float_to_exponential_common_exact<T>(fmt: &mut Formatter, num: &T,
|
|||
where T: flt2dec::DecodableFloat
|
||||
{
|
||||
unsafe {
|
||||
let mut buf = MaybeUninit::<[u8; 1024]>::uninitialized(); // enough for f32 and f64
|
||||
let mut parts = MaybeUninit::<[flt2dec::Part; 6]>::uninitialized();
|
||||
let mut buf = MaybeUninit::<[u8; 1024]>::uninit(); // enough for f32 and f64
|
||||
let mut parts = MaybeUninit::<[flt2dec::Part; 6]>::uninit();
|
||||
// FIXME(#53491)
|
||||
let formatted = flt2dec::to_exact_exp_str(flt2dec::strategy::grisu::format_exact,
|
||||
*num, sign, precision,
|
||||
|
|
@ -91,8 +91,8 @@ fn float_to_exponential_common_shortest<T>(fmt: &mut Formatter,
|
|||
{
|
||||
unsafe {
|
||||
// enough for f32 and f64
|
||||
let mut buf = MaybeUninit::<[u8; flt2dec::MAX_SIG_DIGITS]>::uninitialized();
|
||||
let mut parts = MaybeUninit::<[flt2dec::Part; 6]>::uninitialized();
|
||||
let mut buf = MaybeUninit::<[u8; flt2dec::MAX_SIG_DIGITS]>::uninit();
|
||||
let mut parts = MaybeUninit::<[flt2dec::Part; 6]>::uninit();
|
||||
// FIXME(#53491)
|
||||
let formatted = flt2dec::to_shortest_exp_str(flt2dec::strategy::grisu::format_shortest,
|
||||
*num, sign, (0, 0), upper,
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ trait GenericRadix {
|
|||
for byte in buf.iter_mut().rev() {
|
||||
let n = x % base; // Get the current place value.
|
||||
x = x / base; // Deaccumulate the number.
|
||||
byte.set(Self::digit(n.to_u8())); // Store the digit in the buffer.
|
||||
byte.write(Self::digit(n.to_u8())); // Store the digit in the buffer.
|
||||
curr -= 1;
|
||||
if x == zero {
|
||||
// No more digits left to accumulate.
|
||||
|
|
@ -72,7 +72,7 @@ trait GenericRadix {
|
|||
for byte in buf.iter_mut().rev() {
|
||||
let n = zero - (x % base); // Get the current place value.
|
||||
x = x / base; // Deaccumulate the number.
|
||||
byte.set(Self::digit(n.to_u8())); // Store the digit in the buffer.
|
||||
byte.write(Self::digit(n.to_u8())); // Store the digit in the buffer.
|
||||
curr -= 1;
|
||||
if x == zero {
|
||||
// No more digits left to accumulate.
|
||||
|
|
|
|||
|
|
@ -626,12 +626,12 @@ macro_rules! todo {
|
|||
#[macro_export]
|
||||
#[unstable(feature = "maybe_uninit_array", issue = "53491")]
|
||||
macro_rules! uninitialized_array {
|
||||
// This `into_initialized` is safe because an array of `MaybeUninit` does not
|
||||
// This `assume_init` is safe because an array of `MaybeUninit` does not
|
||||
// require initialization.
|
||||
// FIXME(#49147): Could be replaced by an array initializer, once those can
|
||||
// be any const expression.
|
||||
($t:ty; $size:expr) => (unsafe {
|
||||
MaybeUninit::<[MaybeUninit<$t>; $size]>::uninitialized().into_initialized()
|
||||
MaybeUninit::<[MaybeUninit<$t>; $size]>::uninit().assume_init()
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -622,7 +622,7 @@ pub unsafe fn zeroed<T>() -> T {
|
|||
/// [copy_no]: ../intrinsics/fn.copy_nonoverlapping.html
|
||||
/// [`Drop`]: ../ops/trait.Drop.html
|
||||
#[inline]
|
||||
#[rustc_deprecated(since = "2.0.0", reason = "use `mem::MaybeUninit::uninitialized` instead")]
|
||||
#[rustc_deprecated(since = "2.0.0", reason = "use `mem::MaybeUninit::uninit` instead")]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub unsafe fn uninitialized<T>() -> T {
|
||||
intrinsics::panic_if_uninhabited::<T>();
|
||||
|
|
@ -1058,7 +1058,7 @@ impl<T: ?Sized> DerefMut for ManuallyDrop<T> {
|
|||
///
|
||||
/// let x: &i32 = unsafe { mem::zeroed() }; // undefined behavior!
|
||||
/// // The equivalent code with `MaybeUninit<&i32>`:
|
||||
/// let x: &i32 = unsafe { MaybeUninit::zeroed().into_initialized() }; // undefined behavior!
|
||||
/// let x: &i32 = unsafe { MaybeUninit::zeroed().assume_init() }; // undefined behavior!
|
||||
/// ```
|
||||
///
|
||||
/// This is exploited by the compiler for various optimizations, such as eliding
|
||||
|
|
@ -1073,7 +1073,7 @@ impl<T: ?Sized> DerefMut for ManuallyDrop<T> {
|
|||
///
|
||||
/// let b: bool = unsafe { mem::uninitialized() }; // undefined behavior!
|
||||
/// // The equivalent code with `MaybeUninit<bool>`:
|
||||
/// let b: bool = unsafe { MaybeUninit::uninitialized().into_initialized() }; // undefined behavior!
|
||||
/// let b: bool = unsafe { MaybeUninit::uninit().assume_init() }; // undefined behavior!
|
||||
/// ```
|
||||
///
|
||||
/// Moreover, uninitialized memory is special in that the compiler knows that
|
||||
|
|
@ -1087,7 +1087,7 @@ impl<T: ?Sized> DerefMut for ManuallyDrop<T> {
|
|||
///
|
||||
/// let x: i32 = unsafe { mem::uninitialized() }; // undefined behavior!
|
||||
/// // The equivalent code with `MaybeUninit<i32>`:
|
||||
/// let x: i32 = unsafe { MaybeUninit::uninitialized().into_initialized() }; // undefined behavior!
|
||||
/// 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.)
|
||||
|
|
@ -1102,12 +1102,12 @@ impl<T: ?Sized> DerefMut for ManuallyDrop<T> {
|
|||
///
|
||||
/// // 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>::uninitialized();
|
||||
/// let mut x = MaybeUninit::<&i32>::uninit();
|
||||
/// // Set it to a valid value.
|
||||
/// x.set(&0);
|
||||
/// x.write(&0);
|
||||
/// // Extract the initialized data -- this is only allowed *after* properly
|
||||
/// // initializing `x`!
|
||||
/// let x = unsafe { x.into_initialized() };
|
||||
/// let x = unsafe { x.assume_init() };
|
||||
/// ```
|
||||
///
|
||||
/// The compiler then knows to not make any incorrect assumptions or optimizations on this code.
|
||||
|
|
@ -1148,10 +1148,19 @@ impl<T> MaybeUninit<T> {
|
|||
/// It is your responsibility to make sure `T` gets dropped if it got initialized.
|
||||
#[unstable(feature = "maybe_uninit", issue = "53491")]
|
||||
#[inline(always)]
|
||||
pub const fn uninitialized() -> MaybeUninit<T> {
|
||||
pub const fn uninit() -> MaybeUninit<T> {
|
||||
MaybeUninit { uninit: () }
|
||||
}
|
||||
|
||||
/// Deprecated before stabilization.
|
||||
#[unstable(feature = "maybe_uninit", issue = "53491")]
|
||||
#[inline(always)]
|
||||
// FIXME: still used by stdsimd
|
||||
// #[rustc_deprecated(since = "1.35.0", reason = "use `uninit` instead")]
|
||||
pub const fn uninitialized() -> MaybeUninit<T> {
|
||||
Self::uninit()
|
||||
}
|
||||
|
||||
/// 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,
|
||||
|
|
@ -1171,7 +1180,7 @@ impl<T> MaybeUninit<T> {
|
|||
/// use std::mem::MaybeUninit;
|
||||
///
|
||||
/// let x = MaybeUninit::<(u8, bool)>::zeroed();
|
||||
/// let x = unsafe { x.into_initialized() };
|
||||
/// let x = unsafe { x.assume_init() };
|
||||
/// assert_eq!(x, (0, false));
|
||||
/// ```
|
||||
///
|
||||
|
|
@ -1185,14 +1194,14 @@ impl<T> MaybeUninit<T> {
|
|||
/// enum NotZero { One = 1, Two = 2 };
|
||||
///
|
||||
/// let x = MaybeUninit::<(u8, NotZero)>::zeroed();
|
||||
/// let x = unsafe { x.into_initialized() };
|
||||
/// let x = unsafe { x.assume_init() };
|
||||
/// // Inside a pair, we create a `NotZero` that does not have a valid discriminant.
|
||||
/// // This is undefined behavior.
|
||||
/// ```
|
||||
#[unstable(feature = "maybe_uninit", issue = "53491")]
|
||||
#[inline]
|
||||
pub fn zeroed() -> MaybeUninit<T> {
|
||||
let mut u = MaybeUninit::<T>::uninitialized();
|
||||
let mut u = MaybeUninit::<T>::uninit();
|
||||
unsafe {
|
||||
u.as_mut_ptr().write_bytes(0u8, 1);
|
||||
}
|
||||
|
|
@ -1205,13 +1214,21 @@ impl<T> MaybeUninit<T> {
|
|||
/// reference to the (now safely initialized) contents of `self`.
|
||||
#[unstable(feature = "maybe_uninit", issue = "53491")]
|
||||
#[inline(always)]
|
||||
pub fn set(&mut self, val: T) -> &mut T {
|
||||
pub fn write(&mut self, val: T) -> &mut T {
|
||||
unsafe {
|
||||
self.value = ManuallyDrop::new(val);
|
||||
self.get_mut()
|
||||
}
|
||||
}
|
||||
|
||||
/// Deprecated before stabilization.
|
||||
#[unstable(feature = "maybe_uninit", issue = "53491")]
|
||||
#[inline(always)]
|
||||
#[rustc_deprecated(since = "1.35.0", reason = "use `write` instead")]
|
||||
pub fn set(&mut self, val: T) -> &mut T {
|
||||
self.write(val)
|
||||
}
|
||||
|
||||
/// 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.
|
||||
///
|
||||
|
|
@ -1223,7 +1240,7 @@ impl<T> MaybeUninit<T> {
|
|||
/// #![feature(maybe_uninit)]
|
||||
/// use std::mem::MaybeUninit;
|
||||
///
|
||||
/// let mut x = MaybeUninit::<Vec<u32>>::uninitialized();
|
||||
/// 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() };
|
||||
|
|
@ -1236,7 +1253,7 @@ impl<T> MaybeUninit<T> {
|
|||
/// #![feature(maybe_uninit)]
|
||||
/// use std::mem::MaybeUninit;
|
||||
///
|
||||
/// let x = MaybeUninit::<Vec<u32>>::uninitialized();
|
||||
/// 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.
|
||||
/// ```
|
||||
|
|
@ -1260,7 +1277,7 @@ impl<T> MaybeUninit<T> {
|
|||
/// #![feature(maybe_uninit)]
|
||||
/// use std::mem::MaybeUninit;
|
||||
///
|
||||
/// let mut x = MaybeUninit::<Vec<u32>>::uninitialized();
|
||||
/// 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.
|
||||
|
|
@ -1275,7 +1292,7 @@ impl<T> MaybeUninit<T> {
|
|||
/// #![feature(maybe_uninit)]
|
||||
/// use std::mem::MaybeUninit;
|
||||
///
|
||||
/// let mut x = MaybeUninit::<Vec<u32>>::uninitialized();
|
||||
/// 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.
|
||||
/// ```
|
||||
|
|
@ -1306,9 +1323,9 @@ impl<T> MaybeUninit<T> {
|
|||
/// #![feature(maybe_uninit)]
|
||||
/// use std::mem::MaybeUninit;
|
||||
///
|
||||
/// let mut x = MaybeUninit::<bool>::uninitialized();
|
||||
/// let mut x = MaybeUninit::<bool>::uninit();
|
||||
/// unsafe { x.as_mut_ptr().write(true); }
|
||||
/// let x_init = unsafe { x.into_initialized() };
|
||||
/// let x_init = unsafe { x.assume_init() };
|
||||
/// assert_eq!(x_init, true);
|
||||
/// ```
|
||||
///
|
||||
|
|
@ -1318,21 +1335,30 @@ impl<T> MaybeUninit<T> {
|
|||
/// #![feature(maybe_uninit)]
|
||||
/// use std::mem::MaybeUninit;
|
||||
///
|
||||
/// let x = MaybeUninit::<Vec<u32>>::uninitialized();
|
||||
/// let x_init = unsafe { x.into_initialized() };
|
||||
/// 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.
|
||||
/// ```
|
||||
#[unstable(feature = "maybe_uninit", issue = "53491")]
|
||||
#[inline(always)]
|
||||
pub unsafe fn into_initialized(self) -> T {
|
||||
pub unsafe fn assume_init(self) -> T {
|
||||
intrinsics::panic_if_uninhabited::<T>();
|
||||
ManuallyDrop::into_inner(self.value)
|
||||
}
|
||||
|
||||
/// Deprecated before stabilization.
|
||||
#[unstable(feature = "maybe_uninit", issue = "53491")]
|
||||
#[inline(always)]
|
||||
// FIXME: still used by stdsimd
|
||||
// #[rustc_deprecated(since = "1.35.0", reason = "use `assume_init` instead")]
|
||||
pub unsafe fn into_initialized(self) -> T {
|
||||
self.assume_init()
|
||||
}
|
||||
|
||||
/// Reads the value from the `MaybeUninit<T>` container. The resulting `T` is subject
|
||||
/// to the usual drop handling.
|
||||
///
|
||||
/// Whenever possible, it is preferrable to use [`into_initialized`] instead, which
|
||||
/// Whenever possible, it is preferrable to use [`assume_init`] instead, which
|
||||
/// prevents duplicating the content of the `MaybeUninit<T>`.
|
||||
///
|
||||
/// # Safety
|
||||
|
|
@ -1342,11 +1368,11 @@ impl<T> MaybeUninit<T> {
|
|||
/// behavior.
|
||||
///
|
||||
/// Moreover, this leaves a copy of the same data behind in the `MaybeUninit<T>`. When using
|
||||
/// multiple copies of the data (by calling `read_initialized` multiple times, or first
|
||||
/// calling `read_initialized` and then [`into_initialized`]), it is your responsibility
|
||||
/// multiple copies of the data (by calling `read` multiple times, or first
|
||||
/// calling `read` and then [`assume_init`]), it is your responsibility
|
||||
/// to ensure that that data may indeed be duplicated.
|
||||
///
|
||||
/// [`into_initialized`]: #method.into_initialized
|
||||
/// [`assume_init`]: #method.assume_init
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
|
@ -1356,18 +1382,18 @@ impl<T> MaybeUninit<T> {
|
|||
/// #![feature(maybe_uninit)]
|
||||
/// use std::mem::MaybeUninit;
|
||||
///
|
||||
/// let mut x = MaybeUninit::<u32>::uninitialized();
|
||||
/// x.set(13);
|
||||
/// let x1 = unsafe { x.read_initialized() };
|
||||
/// let mut x = MaybeUninit::<u32>::uninit();
|
||||
/// x.write(13);
|
||||
/// let x1 = unsafe { x.read() };
|
||||
/// // `u32` is `Copy`, so we may read multiple times.
|
||||
/// let x2 = unsafe { x.read_initialized() };
|
||||
/// let x2 = unsafe { x.read() };
|
||||
/// assert_eq!(x1, x2);
|
||||
///
|
||||
/// let mut x = MaybeUninit::<Option<Vec<u32>>>::uninitialized();
|
||||
/// x.set(None);
|
||||
/// let x1 = unsafe { x.read_initialized() };
|
||||
/// let mut x = MaybeUninit::<Option<Vec<u32>>>::uninit();
|
||||
/// x.write(None);
|
||||
/// let x1 = unsafe { x.read() };
|
||||
/// // Duplicating a `None` value is okay, so we may read multiple times.
|
||||
/// let x2 = unsafe { x.read_initialized() };
|
||||
/// let x2 = unsafe { x.read() };
|
||||
/// assert_eq!(x1, x2);
|
||||
/// ```
|
||||
///
|
||||
|
|
@ -1377,20 +1403,28 @@ impl<T> MaybeUninit<T> {
|
|||
/// #![feature(maybe_uninit)]
|
||||
/// use std::mem::MaybeUninit;
|
||||
///
|
||||
/// let mut x = MaybeUninit::<Option<Vec<u32>>>::uninitialized();
|
||||
/// x.set(Some(vec![0,1,2]));
|
||||
/// let x1 = unsafe { x.read_initialized() };
|
||||
/// let x2 = unsafe { x.read_initialized() };
|
||||
/// let mut x = MaybeUninit::<Option<Vec<u32>>>::uninit();
|
||||
/// x.write(Some(vec![0,1,2]));
|
||||
/// let x1 = unsafe { x.read() };
|
||||
/// let x2 = unsafe { x.read() };
|
||||
/// // We now created two copies of the same vector, leading to a double-free when
|
||||
/// // they both get dropped!
|
||||
/// ```
|
||||
#[unstable(feature = "maybe_uninit", issue = "53491")]
|
||||
#[inline(always)]
|
||||
pub unsafe fn read_initialized(&self) -> T {
|
||||
pub unsafe fn read(&self) -> T {
|
||||
intrinsics::panic_if_uninhabited::<T>();
|
||||
self.as_ptr().read()
|
||||
}
|
||||
|
||||
/// Deprecated before stabilization.
|
||||
#[unstable(feature = "maybe_uninit", issue = "53491")]
|
||||
#[inline(always)]
|
||||
#[rustc_deprecated(since = "1.35.0", reason = "use `read` instead")]
|
||||
pub unsafe fn read_initialized(&self) -> T {
|
||||
self.read()
|
||||
}
|
||||
|
||||
/// Gets a reference to the contained value.
|
||||
///
|
||||
/// # Safety
|
||||
|
|
|
|||
|
|
@ -3794,7 +3794,8 @@ impl u8 {
|
|||
#[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
|
||||
#[inline]
|
||||
pub fn to_ascii_uppercase(&self) -> u8 {
|
||||
ASCII_UPPERCASE_MAP[*self as usize]
|
||||
// Unset the fith 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.
|
||||
|
|
@ -3816,7 +3817,8 @@ impl u8 {
|
|||
#[stable(feature = "ascii_methods_on_intrinsics", since = "1.23.0")]
|
||||
#[inline]
|
||||
pub fn to_ascii_lowercase(&self) -> u8 {
|
||||
ASCII_LOWERCASE_MAP[*self as usize]
|
||||
// Set the fith 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.
|
||||
|
|
@ -3918,9 +3920,8 @@ impl u8 {
|
|||
#[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")]
|
||||
#[inline]
|
||||
pub fn is_ascii_alphabetic(&self) -> bool {
|
||||
if *self >= 0x80 { return false; }
|
||||
match ASCII_CHARACTER_CLASS[*self as usize] {
|
||||
L | Lx | U | Ux => true,
|
||||
match *self {
|
||||
b'A'...b'Z' | b'a'...b'z' => true,
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
|
|
@ -3954,9 +3955,8 @@ impl u8 {
|
|||
#[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")]
|
||||
#[inline]
|
||||
pub fn is_ascii_uppercase(&self) -> bool {
|
||||
if *self >= 0x80 { return false }
|
||||
match ASCII_CHARACTER_CLASS[*self as usize] {
|
||||
U | Ux => true,
|
||||
match *self {
|
||||
b'A'...b'Z' => true,
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
|
|
@ -3990,9 +3990,8 @@ impl u8 {
|
|||
#[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")]
|
||||
#[inline]
|
||||
pub fn is_ascii_lowercase(&self) -> bool {
|
||||
if *self >= 0x80 { return false }
|
||||
match ASCII_CHARACTER_CLASS[*self as usize] {
|
||||
L | Lx => true,
|
||||
match *self {
|
||||
b'a'...b'z' => true,
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
|
|
@ -4029,9 +4028,8 @@ impl u8 {
|
|||
#[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")]
|
||||
#[inline]
|
||||
pub fn is_ascii_alphanumeric(&self) -> bool {
|
||||
if *self >= 0x80 { return false }
|
||||
match ASCII_CHARACTER_CLASS[*self as usize] {
|
||||
D | L | Lx | U | Ux => true,
|
||||
match *self {
|
||||
b'0'...b'9' | b'A'...b'Z' | b'a'...b'z' => true,
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
|
|
@ -4065,9 +4063,8 @@ impl u8 {
|
|||
#[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")]
|
||||
#[inline]
|
||||
pub fn is_ascii_digit(&self) -> bool {
|
||||
if *self >= 0x80 { return false }
|
||||
match ASCII_CHARACTER_CLASS[*self as usize] {
|
||||
D => true,
|
||||
match *self {
|
||||
b'0'...b'9' => true,
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
|
|
@ -4104,9 +4101,8 @@ impl u8 {
|
|||
#[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")]
|
||||
#[inline]
|
||||
pub fn is_ascii_hexdigit(&self) -> bool {
|
||||
if *self >= 0x80 { return false }
|
||||
match ASCII_CHARACTER_CLASS[*self as usize] {
|
||||
D | Lx | Ux => true,
|
||||
match *self {
|
||||
b'0'...b'9' | b'A'...b'F' | b'a'...b'f' => true,
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
|
|
@ -4144,9 +4140,8 @@ impl u8 {
|
|||
#[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")]
|
||||
#[inline]
|
||||
pub fn is_ascii_punctuation(&self) -> bool {
|
||||
if *self >= 0x80 { return false }
|
||||
match ASCII_CHARACTER_CLASS[*self as usize] {
|
||||
P => true,
|
||||
match *self {
|
||||
b'!'...b'/' | b':'...b'@' | b'['...b'`' | b'{'...b'~' => true,
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
|
|
@ -4180,9 +4175,8 @@ impl u8 {
|
|||
#[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")]
|
||||
#[inline]
|
||||
pub fn is_ascii_graphic(&self) -> bool {
|
||||
if *self >= 0x80 { return false; }
|
||||
match ASCII_CHARACTER_CLASS[*self as usize] {
|
||||
Ux | U | Lx | L | D | P => true,
|
||||
match *self {
|
||||
b'!'...b'~' => true,
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
|
|
@ -4233,9 +4227,8 @@ impl u8 {
|
|||
#[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")]
|
||||
#[inline]
|
||||
pub fn is_ascii_whitespace(&self) -> bool {
|
||||
if *self >= 0x80 { return false; }
|
||||
match ASCII_CHARACTER_CLASS[*self as usize] {
|
||||
Cw | W => true,
|
||||
match *self {
|
||||
b'\t' | b'\n' | b'\x0C' | b'\r' | b' ' => true,
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
|
|
@ -4271,9 +4264,8 @@ impl u8 {
|
|||
#[stable(feature = "ascii_ctype_on_intrinsics", since = "1.24.0")]
|
||||
#[inline]
|
||||
pub fn is_ascii_control(&self) -> bool {
|
||||
if *self >= 0x80 { return false; }
|
||||
match ASCII_CHARACTER_CLASS[*self as usize] {
|
||||
C | Cw => true,
|
||||
match *self {
|
||||
b'\0'...b'\x1F' | b'\x7F' => true,
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
|
|
@ -4939,106 +4931,3 @@ 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")] }
|
||||
|
||||
static ASCII_LOWERCASE_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,
|
||||
];
|
||||
|
||||
static 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
|
||||
}
|
||||
use self::AsciiCharacterClass::*;
|
||||
|
||||
static ASCII_CHARACTER_CLASS: [AsciiCharacterClass; 128] = [
|
||||
// _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_
|
||||
];
|
||||
|
|
|
|||
|
|
@ -296,7 +296,7 @@ pub const fn null_mut<T>() -> *mut T { 0 as *mut T }
|
|||
pub unsafe fn swap<T>(x: *mut T, y: *mut T) {
|
||||
// Give ourselves some scratch space to work with.
|
||||
// We do not have to worry about drops: `MaybeUninit` does nothing when dropped.
|
||||
let mut tmp = MaybeUninit::<T>::uninitialized();
|
||||
let mut tmp = MaybeUninit::<T>::uninit();
|
||||
|
||||
// Perform the swap
|
||||
copy_nonoverlapping(x, tmp.as_mut_ptr(), 1);
|
||||
|
|
@ -388,7 +388,7 @@ unsafe fn swap_nonoverlapping_bytes(x: *mut u8, y: *mut u8, len: usize) {
|
|||
while i + block_size <= len {
|
||||
// Create some uninitialized memory as scratch space
|
||||
// Declaring `t` here avoids aligning the stack when this loop is unused
|
||||
let mut t = mem::MaybeUninit::<Block>::uninitialized();
|
||||
let mut t = mem::MaybeUninit::<Block>::uninit();
|
||||
let t = t.as_mut_ptr() as *mut u8;
|
||||
let x = x.add(i);
|
||||
let y = y.add(i);
|
||||
|
|
@ -403,7 +403,7 @@ unsafe fn swap_nonoverlapping_bytes(x: *mut u8, y: *mut u8, len: usize) {
|
|||
|
||||
if i < len {
|
||||
// Swap any remaining bytes
|
||||
let mut t = mem::MaybeUninit::<UnalignedBlock>::uninitialized();
|
||||
let mut t = mem::MaybeUninit::<UnalignedBlock>::uninit();
|
||||
let rem = len - i;
|
||||
|
||||
let t = t.as_mut_ptr() as *mut u8;
|
||||
|
|
@ -571,9 +571,9 @@ pub unsafe fn replace<T>(dst: *mut T, mut src: T) -> T {
|
|||
#[inline]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub unsafe fn read<T>(src: *const T) -> T {
|
||||
let mut tmp = MaybeUninit::<T>::uninitialized();
|
||||
let mut tmp = MaybeUninit::<T>::uninit();
|
||||
copy_nonoverlapping(src, tmp.as_mut_ptr(), 1);
|
||||
tmp.into_initialized()
|
||||
tmp.assume_init()
|
||||
}
|
||||
|
||||
/// Reads the value from `src` without moving it. This leaves the
|
||||
|
|
@ -638,11 +638,11 @@ pub unsafe fn read<T>(src: *const T) -> T {
|
|||
#[inline]
|
||||
#[stable(feature = "ptr_unaligned", since = "1.17.0")]
|
||||
pub unsafe fn read_unaligned<T>(src: *const T) -> T {
|
||||
let mut tmp = MaybeUninit::<T>::uninitialized();
|
||||
let mut tmp = MaybeUninit::<T>::uninit();
|
||||
copy_nonoverlapping(src as *const u8,
|
||||
tmp.as_mut_ptr() as *mut u8,
|
||||
mem::size_of::<T>());
|
||||
tmp.into_initialized()
|
||||
tmp.assume_init()
|
||||
}
|
||||
|
||||
/// Overwrites a memory location with the given value without reading or
|
||||
|
|
@ -2495,11 +2495,57 @@ impl<T: ?Sized> Eq for *mut T {}
|
|||
/// let other_five_ref = &other_five;
|
||||
///
|
||||
/// assert!(five_ref == same_five_ref);
|
||||
/// assert!(five_ref == other_five_ref);
|
||||
///
|
||||
/// assert!(ptr::eq(five_ref, same_five_ref));
|
||||
///
|
||||
/// assert!(five_ref == other_five_ref);
|
||||
/// assert!(!ptr::eq(five_ref, other_five_ref));
|
||||
/// ```
|
||||
///
|
||||
/// Slices are also compared by their length (fat pointers):
|
||||
///
|
||||
/// ```
|
||||
/// let a = [1, 2, 3];
|
||||
/// assert!(std::ptr::eq(&a[..3], &a[..3]));
|
||||
/// assert!(!std::ptr::eq(&a[..2], &a[..3]));
|
||||
/// assert!(!std::ptr::eq(&a[0..2], &a[1..3]));
|
||||
/// ```
|
||||
///
|
||||
/// Traits are also compared by their implementation:
|
||||
///
|
||||
/// ```
|
||||
/// #[repr(transparent)]
|
||||
/// struct Wrapper { member: i32 }
|
||||
///
|
||||
/// trait Trait {}
|
||||
/// impl Trait for Wrapper {}
|
||||
/// impl Trait for i32 {}
|
||||
///
|
||||
/// fn main() {
|
||||
/// let wrapper = Wrapper { member: 10 };
|
||||
///
|
||||
/// // Pointers have equal addresses.
|
||||
/// assert!(std::ptr::eq(
|
||||
/// &wrapper as *const Wrapper as *const u8,
|
||||
/// &wrapper.member as *const i32 as *const u8
|
||||
/// ));
|
||||
///
|
||||
/// // Objects have equal addresses, but `Trait` has different implementations.
|
||||
/// assert!(!std::ptr::eq(
|
||||
/// &wrapper as &dyn Trait,
|
||||
/// &wrapper.member as &dyn Trait,
|
||||
/// ));
|
||||
/// assert!(!std::ptr::eq(
|
||||
/// &wrapper as &dyn Trait as *const dyn Trait,
|
||||
/// &wrapper.member as &dyn Trait as *const dyn Trait,
|
||||
/// ));
|
||||
///
|
||||
/// // Converting the reference to a `*const u8` compares by address.
|
||||
/// assert!(std::ptr::eq(
|
||||
/// &wrapper as &dyn Trait as *const dyn Trait as *const u8,
|
||||
/// &wrapper.member as &dyn Trait as *const dyn Trait as *const u8,
|
||||
/// ));
|
||||
/// }
|
||||
/// ```
|
||||
#[stable(feature = "ptr_eq", since = "1.17.0")]
|
||||
#[inline]
|
||||
pub fn eq<T: ?Sized>(a: *const T, b: *const T) -> bool {
|
||||
|
|
|
|||
|
|
@ -72,7 +72,7 @@ pub unsafe fn ptr_rotate<T>(mut left: usize, mid: *mut T, mut right: usize) {
|
|||
}
|
||||
}
|
||||
|
||||
let mut rawarray = MaybeUninit::<RawArray<T>>::uninitialized();
|
||||
let mut rawarray = MaybeUninit::<RawArray<T>>::uninit();
|
||||
let buf = &mut (*rawarray.as_mut_ptr()).typed as *mut [T; 2] as *mut T;
|
||||
|
||||
let dim = mid.sub(left).add(right);
|
||||
|
|
|
|||
|
|
@ -3601,7 +3601,11 @@ impl str {
|
|||
/// assert!(Some('ע') == s.trim_left().chars().next());
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_deprecated(reason = "superseded by `trim_start`", since = "1.33.0")]
|
||||
#[rustc_deprecated(
|
||||
since = "1.33.0",
|
||||
reason = "superseded by `trim_start`",
|
||||
suggestion = "trim_start",
|
||||
)]
|
||||
pub fn trim_left(&self) -> &str {
|
||||
self.trim_start()
|
||||
}
|
||||
|
|
@ -3638,7 +3642,11 @@ impl str {
|
|||
/// assert!(Some('ת') == s.trim_right().chars().rev().next());
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_deprecated(reason = "superseded by `trim_end`", since = "1.33.0")]
|
||||
#[rustc_deprecated(
|
||||
since = "1.33.0",
|
||||
reason = "superseded by `trim_end`",
|
||||
suggestion = "trim_end",
|
||||
)]
|
||||
pub fn trim_right(&self) -> &str {
|
||||
self.trim_end()
|
||||
}
|
||||
|
|
@ -3802,7 +3810,11 @@ impl str {
|
|||
/// assert_eq!("12foo1bar12".trim_left_matches(x), "foo1bar12");
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_deprecated(reason = "superseded by `trim_start_matches`", since = "1.33.0")]
|
||||
#[rustc_deprecated(
|
||||
since = "1.33.0",
|
||||
reason = "superseded by `trim_start_matches`",
|
||||
suggestion = "trim_start_matches",
|
||||
)]
|
||||
pub fn trim_left_matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> &'a str {
|
||||
self.trim_start_matches(pat)
|
||||
}
|
||||
|
|
@ -3840,7 +3852,11 @@ impl str {
|
|||
/// assert_eq!("1fooX".trim_right_matches(|c| c == '1' || c == 'X'), "1foo");
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_deprecated(reason = "superseded by `trim_end_matches`", since = "1.33.0")]
|
||||
#[rustc_deprecated(
|
||||
since = "1.33.0",
|
||||
reason = "superseded by `trim_end_matches`",
|
||||
suggestion = "trim_end_matches",
|
||||
)]
|
||||
pub fn trim_right_matches<'a, P: Pattern<'a>>(&'a self, pat: P) -> &'a str
|
||||
where P::Searcher: ReverseSearcher<'a>
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
use std::cmp::Ordering::{Equal, Less, Greater};
|
||||
use std::f64::NAN;
|
||||
|
||||
#[test]
|
||||
fn test_clone() {
|
||||
|
|
@ -8,18 +9,18 @@ fn test_clone() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_tuple_cmp() {
|
||||
fn test_partial_eq() {
|
||||
let (small, big) = ((1, 2, 3), (3, 2, 1));
|
||||
|
||||
let nan = 0.0f64/0.0;
|
||||
|
||||
// PartialEq
|
||||
assert_eq!(small, small);
|
||||
assert_eq!(big, big);
|
||||
assert!(small != big);
|
||||
assert!(big != small);
|
||||
assert_ne!(small, big);
|
||||
assert_ne!(big, small);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_partial_ord() {
|
||||
let (small, big) = ((1, 2, 3), (3, 2, 1));
|
||||
|
||||
// PartialOrd
|
||||
assert!(small < big);
|
||||
assert!(!(small < small));
|
||||
assert!(!(big < small));
|
||||
|
|
@ -33,18 +34,21 @@ fn test_tuple_cmp() {
|
|||
assert!(big >= small);
|
||||
assert!(big >= big);
|
||||
|
||||
assert!(!((1.0f64, 2.0f64) < (nan, 3.0)));
|
||||
assert!(!((1.0f64, 2.0f64) <= (nan, 3.0)));
|
||||
assert!(!((1.0f64, 2.0f64) > (nan, 3.0)));
|
||||
assert!(!((1.0f64, 2.0f64) >= (nan, 3.0)));
|
||||
assert!(((1.0f64, 2.0f64) < (2.0, nan)));
|
||||
assert!(!((2.0f64, 2.0f64) < (2.0, nan)));
|
||||
assert!(!((1.0f64, 2.0f64) < (NAN, 3.0)));
|
||||
assert!(!((1.0f64, 2.0f64) <= (NAN, 3.0)));
|
||||
assert!(!((1.0f64, 2.0f64) > (NAN, 3.0)));
|
||||
assert!(!((1.0f64, 2.0f64) >= (NAN, 3.0)));
|
||||
assert!(((1.0f64, 2.0f64) < (2.0, NAN)));
|
||||
assert!(!((2.0f64, 2.0f64) < (2.0, NAN)));
|
||||
}
|
||||
|
||||
// Ord
|
||||
assert!(small.cmp(&small) == Equal);
|
||||
assert!(big.cmp(&big) == Equal);
|
||||
assert!(small.cmp(&big) == Less);
|
||||
assert!(big.cmp(&small) == Greater);
|
||||
#[test]
|
||||
fn test_ord() {
|
||||
let (small, big) = ((1, 2, 3), (3, 2, 1));
|
||||
assert_eq!(small.cmp(&small), Equal);
|
||||
assert_eq!(big.cmp(&big), Equal);
|
||||
assert_eq!(small.cmp(&big), Less);
|
||||
assert_eq!(big.cmp(&small), Greater);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
|||
|
|
@ -469,6 +469,7 @@ rustc_dep_node_append!([define_dep_nodes!][ <'tcx>
|
|||
[] UnsafetyCheckResult(DefId),
|
||||
[] UnsafeDeriveOnReprPacked(DefId),
|
||||
|
||||
[] LintMod(DefId),
|
||||
[] CheckModAttrs(DefId),
|
||||
[] CheckModLoops(DefId),
|
||||
[] CheckModUnstableApiUsage(DefId),
|
||||
|
|
|
|||
|
|
@ -580,17 +580,17 @@ impl<'hir> Map<'hir> {
|
|||
&self.forest.krate.attrs
|
||||
}
|
||||
|
||||
pub fn get_module(&self, module: DefId) -> (&'hir Mod, Span, NodeId)
|
||||
{
|
||||
pub fn get_module(&self, module: DefId) -> (&'hir Mod, Span, HirId) {
|
||||
let node_id = self.as_local_node_id(module).unwrap();
|
||||
let hir_id = self.node_to_hir_id(node_id);
|
||||
self.read(node_id);
|
||||
match self.find_entry(node_id).unwrap().node {
|
||||
Node::Item(&Item {
|
||||
span,
|
||||
node: ItemKind::Mod(ref m),
|
||||
..
|
||||
}) => (m, span, node_id),
|
||||
Node::Crate => (&self.forest.krate.module, self.forest.krate.span, node_id),
|
||||
}) => (m, span, hir_id),
|
||||
Node::Crate => (&self.forest.krate.module, self.forest.krate.span, hir_id),
|
||||
_ => panic!("not a module")
|
||||
}
|
||||
}
|
||||
|
|
@ -1013,7 +1013,7 @@ impl<'hir> Map<'hir> {
|
|||
/// corresponding to the Node ID
|
||||
pub fn attrs(&self, id: NodeId) -> &'hir [ast::Attribute] {
|
||||
self.read(id); // reveals attributes on the node
|
||||
let attrs = match self.find(id) {
|
||||
let attrs = match self.find_entry(id).map(|entry| entry.node) {
|
||||
Some(Node::Local(l)) => Some(&l.attrs[..]),
|
||||
Some(Node::Item(i)) => Some(&i.attrs[..]),
|
||||
Some(Node::ForeignItem(fi)) => Some(&fi.attrs[..]),
|
||||
|
|
@ -1027,6 +1027,7 @@ impl<'hir> Map<'hir> {
|
|||
// Unit/tuple structs/variants take the attributes straight from
|
||||
// the struct/variant definition.
|
||||
Some(Node::Ctor(..)) => return self.attrs(self.get_parent(id)),
|
||||
Some(Node::Crate) => Some(&self.forest.krate.attrs[..]),
|
||||
_ => None
|
||||
};
|
||||
attrs.unwrap_or(&[])
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ use crate::rustc_serialize::{Decoder, Decodable, Encoder, Encodable};
|
|||
use crate::session::{config, early_error, Session};
|
||||
use crate::ty::{self, TyCtxt, Ty};
|
||||
use crate::ty::layout::{LayoutError, LayoutOf, TyLayout};
|
||||
use crate::ty::query::Providers;
|
||||
use crate::util::nodemap::FxHashMap;
|
||||
use crate::util::common::time;
|
||||
|
||||
|
|
@ -36,8 +37,9 @@ use syntax::edition;
|
|||
use syntax_pos::{MultiSpan, Span, symbol::{LocalInternedString, Symbol}};
|
||||
use errors::DiagnosticBuilder;
|
||||
use crate::hir;
|
||||
use crate::hir::def_id::LOCAL_CRATE;
|
||||
use crate::hir::def_id::{DefId, LOCAL_CRATE};
|
||||
use crate::hir::intravisit as hir_visit;
|
||||
use crate::hir::intravisit::Visitor;
|
||||
use syntax::util::lev_distance::find_best_match_for_name;
|
||||
use syntax::visit as ast_visit;
|
||||
|
||||
|
|
@ -55,6 +57,7 @@ pub struct LintStore {
|
|||
pre_expansion_passes: Option<Vec<EarlyLintPassObject>>,
|
||||
early_passes: Option<Vec<EarlyLintPassObject>>,
|
||||
late_passes: Option<Vec<LateLintPassObject>>,
|
||||
late_module_passes: Option<Vec<LateLintPassObject>>,
|
||||
|
||||
/// Lints indexed by name.
|
||||
by_name: FxHashMap<String, TargetLint>,
|
||||
|
|
@ -150,6 +153,7 @@ impl LintStore {
|
|||
pre_expansion_passes: Some(vec![]),
|
||||
early_passes: Some(vec![]),
|
||||
late_passes: Some(vec![]),
|
||||
late_module_passes: Some(vec![]),
|
||||
by_name: Default::default(),
|
||||
future_incompatible: Default::default(),
|
||||
lint_groups: Default::default(),
|
||||
|
|
@ -199,9 +203,14 @@ impl LintStore {
|
|||
pub fn register_late_pass(&mut self,
|
||||
sess: Option<&Session>,
|
||||
from_plugin: bool,
|
||||
per_module: bool,
|
||||
pass: LateLintPassObject) {
|
||||
self.push_pass(sess, from_plugin, &pass);
|
||||
self.late_passes.as_mut().unwrap().push(pass);
|
||||
if per_module {
|
||||
self.late_module_passes.as_mut().unwrap().push(pass);
|
||||
} else {
|
||||
self.late_passes.as_mut().unwrap().push(pass);
|
||||
}
|
||||
}
|
||||
|
||||
// Helper method for register_early/late_pass
|
||||
|
|
@ -508,6 +517,7 @@ pub struct LateContext<'a, 'tcx: 'a> {
|
|||
pub tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
|
||||
/// Side-tables for the body we are in.
|
||||
// FIXME: Make this lazy to avoid running the TypeckTables query?
|
||||
pub tables: &'a ty::TypeckTables<'tcx>,
|
||||
|
||||
/// Parameter environment for the item we are in.
|
||||
|
|
@ -523,6 +533,9 @@ pub struct LateContext<'a, 'tcx: 'a> {
|
|||
|
||||
/// Generic type parameters in scope for the item we are in.
|
||||
pub generics: Option<&'tcx hir::Generics>,
|
||||
|
||||
/// We are only looking at one module
|
||||
only_module: bool,
|
||||
}
|
||||
|
||||
/// Context for lint checking of the AST, after expansion, before lowering to
|
||||
|
|
@ -803,6 +816,12 @@ impl<'a, 'tcx> LateContext<'a, 'tcx> {
|
|||
pub fn current_lint_root(&self) -> hir::HirId {
|
||||
self.last_node_with_lint_attrs
|
||||
}
|
||||
|
||||
fn process_mod(&mut self, m: &'tcx hir::Mod, s: Span, n: hir::HirId) {
|
||||
run_lints!(self, check_mod, m, s, n);
|
||||
hir_visit::walk_mod(self, m, n);
|
||||
run_lints!(self, check_mod_post, m, s, n);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> LayoutOf for LateContext<'a, 'tcx> {
|
||||
|
|
@ -934,9 +953,9 @@ impl<'a, 'tcx> hir_visit::Visitor<'tcx> for LateContext<'a, 'tcx> {
|
|||
}
|
||||
|
||||
fn visit_mod(&mut self, m: &'tcx hir::Mod, s: Span, n: hir::HirId) {
|
||||
run_lints!(self, check_mod, m, s, n);
|
||||
hir_visit::walk_mod(self, m, n);
|
||||
run_lints!(self, check_mod_post, m, s, n);
|
||||
if !self.only_module {
|
||||
self.process_mod(m, s, n);
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_local(&mut self, l: &'tcx hir::Local) {
|
||||
|
|
@ -1203,11 +1222,48 @@ impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T>
|
|||
}
|
||||
}
|
||||
|
||||
pub fn lint_mod<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>, module_def_id: DefId) {
|
||||
let access_levels = &tcx.privacy_access_levels(LOCAL_CRATE);
|
||||
|
||||
/// Performs lint checking on a crate.
|
||||
///
|
||||
/// Consumes the `lint_store` field of the `Session`.
|
||||
pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
|
||||
let store = &tcx.sess.lint_store;
|
||||
let passes = store.borrow_mut().late_module_passes.take();
|
||||
|
||||
let mut cx = LateContext {
|
||||
tcx,
|
||||
tables: &ty::TypeckTables::empty(None),
|
||||
param_env: ty::ParamEnv::empty(),
|
||||
access_levels,
|
||||
lint_sess: LintSession {
|
||||
lints: store.borrow(),
|
||||
passes,
|
||||
},
|
||||
last_node_with_lint_attrs: tcx.hir().as_local_hir_id(module_def_id).unwrap(),
|
||||
generics: None,
|
||||
only_module: true,
|
||||
};
|
||||
|
||||
let (module, span, hir_id) = tcx.hir().get_module(module_def_id);
|
||||
cx.process_mod(module, span, hir_id);
|
||||
|
||||
// Visit the crate attributes
|
||||
if hir_id == hir::CRATE_HIR_ID {
|
||||
walk_list!(cx, visit_attribute, cx.tcx.hir().attrs_by_hir_id(hir::CRATE_HIR_ID));
|
||||
}
|
||||
|
||||
// Put the lint store levels and passes back in the session.
|
||||
let passes = cx.lint_sess.passes;
|
||||
drop(cx.lint_sess.lints);
|
||||
store.borrow_mut().late_module_passes = passes;
|
||||
}
|
||||
|
||||
pub(crate) fn provide(providers: &mut Providers<'_>) {
|
||||
*providers = Providers {
|
||||
lint_mod,
|
||||
..*providers
|
||||
};
|
||||
}
|
||||
|
||||
fn lint_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
|
||||
let access_levels = &tcx.privacy_access_levels(LOCAL_CRATE);
|
||||
|
||||
let krate = tcx.hir().krate();
|
||||
|
|
@ -1225,6 +1281,7 @@ pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
|
|||
},
|
||||
last_node_with_lint_attrs: hir::CRATE_HIR_ID,
|
||||
generics: None,
|
||||
only_module: false,
|
||||
};
|
||||
|
||||
// Visit the whole crate.
|
||||
|
|
@ -1244,6 +1301,17 @@ pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
|
|||
tcx.sess.lint_store.borrow_mut().late_passes = passes;
|
||||
}
|
||||
|
||||
/// Performs lint checking on a crate.
|
||||
pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
|
||||
// Run per-module lints
|
||||
for &module in tcx.hir().krate().modules.keys() {
|
||||
tcx.ensure().lint_mod(tcx.hir().local_def_id(module));
|
||||
}
|
||||
|
||||
// Run whole crate non-incremental lints
|
||||
lint_crate(tcx);
|
||||
}
|
||||
|
||||
struct EarlyLintPassObjects<'a> {
|
||||
lints: &'a mut [EarlyLintPassObject],
|
||||
}
|
||||
|
|
|
|||
|
|
@ -824,6 +824,7 @@ impl<'a, 'tcx> intravisit::Visitor<'tcx> for LintLevelMapBuilder<'a, 'tcx> {
|
|||
|
||||
pub fn provide(providers: &mut Providers<'_>) {
|
||||
providers.lint_levels = lint_levels;
|
||||
context::provide(providers);
|
||||
}
|
||||
|
||||
/// Returns whether `span` originates in a foreign crate's external macro.
|
||||
|
|
|
|||
|
|
@ -344,7 +344,7 @@ impl<'tcx> AllocMap<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Returns `None` in case the `AllocId` is dangling. An `EvalContext` can still have a
|
||||
/// Returns `None` in case the `AllocId` is dangling. An `InterpretCx` can still have a
|
||||
/// local `Allocation` for that `AllocId`, but having such an `AllocId` in a constant is
|
||||
/// illegal and will likely ICE.
|
||||
/// This function exists to allow const eval to detect the difference between evaluation-
|
||||
|
|
|
|||
|
|
@ -217,6 +217,8 @@ rustc_query_append! { [define_queries!][ <'tcx>
|
|||
},
|
||||
|
||||
Other {
|
||||
[] fn lint_mod: LintMod(DefId) -> (),
|
||||
|
||||
/// Checks the attributes in the module
|
||||
[] fn check_mod_attrs: CheckModAttrs(DefId) -> (),
|
||||
|
||||
|
|
|
|||
|
|
@ -1262,6 +1262,7 @@ pub fn force_from_dep_node<'tcx>(
|
|||
DepKind::MirBorrowCheck => { force!(mir_borrowck, def_id!()); }
|
||||
DepKind::UnsafetyCheckResult => { force!(unsafety_check_result, def_id!()); }
|
||||
DepKind::UnsafeDeriveOnReprPacked => { force!(unsafe_derive_on_repr_packed, def_id!()); }
|
||||
DepKind::LintMod => { force!(lint_mod, def_id!()); }
|
||||
DepKind::CheckModAttrs => { force!(check_mod_attrs, def_id!()); }
|
||||
DepKind::CheckModLoops => { force!(check_mod_loops, def_id!()); }
|
||||
DepKind::CheckModUnstableApiUsage => { force!(check_mod_unstable_api_usage, def_id!()); }
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
authors = ["The Rust Project Developers"]
|
||||
name = "rustc_driver"
|
||||
version = "0.0.0"
|
||||
edition = "2018"
|
||||
|
||||
[lib]
|
||||
name = "rustc_driver"
|
||||
|
|
@ -13,14 +14,14 @@ arena = { path = "../libarena" }
|
|||
graphviz = { path = "../libgraphviz" }
|
||||
log = "0.4"
|
||||
env_logger = { version = "0.5", default-features = false }
|
||||
rustc-rayon = "0.1.2"
|
||||
rayon = { version = "0.1.2", package = "rustc-rayon" }
|
||||
scoped-tls = "1.0"
|
||||
rustc = { path = "../librustc" }
|
||||
rustc_allocator = { path = "../librustc_allocator" }
|
||||
rustc_target = { path = "../librustc_target" }
|
||||
rustc_borrowck = { path = "../librustc_borrowck" }
|
||||
rustc_data_structures = { path = "../librustc_data_structures" }
|
||||
rustc_errors = { path = "../librustc_errors" }
|
||||
errors = { path = "../librustc_errors", package = "rustc_errors" }
|
||||
rustc_incremental = { path = "../librustc_incremental" }
|
||||
rustc_lint = { path = "../librustc_lint" }
|
||||
rustc_metadata = { path = "../librustc_metadata" }
|
||||
|
|
|
|||
|
|
@ -16,40 +16,13 @@
|
|||
|
||||
#![recursion_limit="256"]
|
||||
|
||||
extern crate arena;
|
||||
#![deny(rust_2018_idioms)]
|
||||
|
||||
pub extern crate getopts;
|
||||
extern crate graphviz;
|
||||
extern crate env_logger;
|
||||
#[cfg(unix)]
|
||||
extern crate libc;
|
||||
extern crate rustc_rayon as rayon;
|
||||
extern crate rustc;
|
||||
extern crate rustc_allocator;
|
||||
extern crate rustc_target;
|
||||
extern crate rustc_borrowck;
|
||||
extern crate rustc_data_structures;
|
||||
extern crate rustc_errors as errors;
|
||||
extern crate rustc_passes;
|
||||
extern crate rustc_lint;
|
||||
extern crate rustc_plugin;
|
||||
extern crate rustc_privacy;
|
||||
extern crate rustc_incremental;
|
||||
extern crate rustc_metadata;
|
||||
extern crate rustc_mir;
|
||||
extern crate rustc_resolve;
|
||||
extern crate rustc_save_analysis;
|
||||
extern crate rustc_traits;
|
||||
extern crate rustc_codegen_utils;
|
||||
extern crate rustc_typeck;
|
||||
extern crate rustc_interface;
|
||||
extern crate scoped_tls;
|
||||
extern crate serialize;
|
||||
extern crate smallvec;
|
||||
#[macro_use]
|
||||
extern crate log;
|
||||
extern crate syntax;
|
||||
extern crate syntax_ext;
|
||||
extern crate syntax_pos;
|
||||
|
||||
use pretty::{PpMode, UserIdentifiedItem};
|
||||
|
||||
|
|
|
|||
|
|
@ -35,9 +35,9 @@ pub use self::UserIdentifiedItem::*;
|
|||
pub use self::PpSourceMode::*;
|
||||
pub use self::PpMode::*;
|
||||
use self::NodesMatchingUII::*;
|
||||
use abort_on_err;
|
||||
use crate::abort_on_err;
|
||||
|
||||
use source_name;
|
||||
use crate::source_name;
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Debug)]
|
||||
pub enum PpSourceMode {
|
||||
|
|
@ -191,7 +191,7 @@ impl PpSourceMode {
|
|||
tcx: TyCtxt<'tcx, 'tcx, 'tcx>,
|
||||
f: F
|
||||
) -> A
|
||||
where F: FnOnce(&dyn HirPrinterSupport, &hir::Crate) -> A
|
||||
where F: FnOnce(&dyn HirPrinterSupport<'_>, &hir::Crate) -> A
|
||||
{
|
||||
match *self {
|
||||
PpmNormal => {
|
||||
|
|
@ -296,7 +296,7 @@ impl<'hir> HirPrinterSupport<'hir> for NoAnn<'hir> {
|
|||
|
||||
impl<'hir> pprust::PpAnn for NoAnn<'hir> {}
|
||||
impl<'hir> pprust_hir::PpAnn for NoAnn<'hir> {
|
||||
fn nested(&self, state: &mut pprust_hir::State, nested: pprust_hir::Nested)
|
||||
fn nested(&self, state: &mut pprust_hir::State<'_>, nested: pprust_hir::Nested)
|
||||
-> io::Result<()> {
|
||||
if let Some(tcx) = self.tcx {
|
||||
pprust_hir::PpAnn::nested(tcx.hir(), state, nested)
|
||||
|
|
@ -322,13 +322,13 @@ impl<'hir> PrinterSupport for IdentifiedAnnotation<'hir> {
|
|||
}
|
||||
|
||||
impl<'hir> pprust::PpAnn for IdentifiedAnnotation<'hir> {
|
||||
fn pre(&self, s: &mut pprust::State, node: pprust::AnnNode) -> io::Result<()> {
|
||||
fn pre(&self, s: &mut pprust::State<'_>, node: pprust::AnnNode<'_>) -> io::Result<()> {
|
||||
match node {
|
||||
pprust::AnnNode::Expr(_) => s.popen(),
|
||||
_ => Ok(()),
|
||||
}
|
||||
}
|
||||
fn post(&self, s: &mut pprust::State, node: pprust::AnnNode) -> io::Result<()> {
|
||||
fn post(&self, s: &mut pprust::State<'_>, node: pprust::AnnNode<'_>) -> io::Result<()> {
|
||||
match node {
|
||||
pprust::AnnNode::Ident(_) |
|
||||
pprust::AnnNode::Name(_) => Ok(()),
|
||||
|
|
@ -373,7 +373,7 @@ impl<'hir> HirPrinterSupport<'hir> for IdentifiedAnnotation<'hir> {
|
|||
}
|
||||
|
||||
impl<'hir> pprust_hir::PpAnn for IdentifiedAnnotation<'hir> {
|
||||
fn nested(&self, state: &mut pprust_hir::State, nested: pprust_hir::Nested)
|
||||
fn nested(&self, state: &mut pprust_hir::State<'_>, nested: pprust_hir::Nested)
|
||||
-> io::Result<()> {
|
||||
if let Some(ref tcx) = self.tcx {
|
||||
pprust_hir::PpAnn::nested(tcx.hir(), state, nested)
|
||||
|
|
@ -381,13 +381,13 @@ impl<'hir> pprust_hir::PpAnn for IdentifiedAnnotation<'hir> {
|
|||
Ok(())
|
||||
}
|
||||
}
|
||||
fn pre(&self, s: &mut pprust_hir::State, node: pprust_hir::AnnNode) -> io::Result<()> {
|
||||
fn pre(&self, s: &mut pprust_hir::State<'_>, node: pprust_hir::AnnNode<'_>) -> io::Result<()> {
|
||||
match node {
|
||||
pprust_hir::AnnNode::Expr(_) => s.popen(),
|
||||
_ => Ok(()),
|
||||
}
|
||||
}
|
||||
fn post(&self, s: &mut pprust_hir::State, node: pprust_hir::AnnNode) -> io::Result<()> {
|
||||
fn post(&self, s: &mut pprust_hir::State<'_>, node: pprust_hir::AnnNode<'_>) -> io::Result<()> {
|
||||
match node {
|
||||
pprust_hir::AnnNode::Name(_) => Ok(()),
|
||||
pprust_hir::AnnNode::Item(item) => {
|
||||
|
|
@ -434,7 +434,7 @@ impl<'a> PrinterSupport for HygieneAnnotation<'a> {
|
|||
}
|
||||
|
||||
impl<'a> pprust::PpAnn for HygieneAnnotation<'a> {
|
||||
fn post(&self, s: &mut pprust::State, node: pprust::AnnNode) -> io::Result<()> {
|
||||
fn post(&self, s: &mut pprust::State<'_>, node: pprust::AnnNode<'_>) -> io::Result<()> {
|
||||
match node {
|
||||
pprust::AnnNode::Ident(&ast::Ident { name, span }) => {
|
||||
s.s.space()?;
|
||||
|
|
@ -476,7 +476,7 @@ impl<'b, 'tcx> HirPrinterSupport<'tcx> for TypedAnnotation<'b, 'tcx> {
|
|||
}
|
||||
|
||||
impl<'a, 'tcx> pprust_hir::PpAnn for TypedAnnotation<'a, 'tcx> {
|
||||
fn nested(&self, state: &mut pprust_hir::State, nested: pprust_hir::Nested)
|
||||
fn nested(&self, state: &mut pprust_hir::State<'_>, nested: pprust_hir::Nested)
|
||||
-> io::Result<()> {
|
||||
let old_tables = self.tables.get();
|
||||
if let pprust_hir::Nested::Body(id) = nested {
|
||||
|
|
@ -486,13 +486,13 @@ impl<'a, 'tcx> pprust_hir::PpAnn for TypedAnnotation<'a, 'tcx> {
|
|||
self.tables.set(old_tables);
|
||||
Ok(())
|
||||
}
|
||||
fn pre(&self, s: &mut pprust_hir::State, node: pprust_hir::AnnNode) -> io::Result<()> {
|
||||
fn pre(&self, s: &mut pprust_hir::State<'_>, node: pprust_hir::AnnNode<'_>) -> io::Result<()> {
|
||||
match node {
|
||||
pprust_hir::AnnNode::Expr(_) => s.popen(),
|
||||
_ => Ok(()),
|
||||
}
|
||||
}
|
||||
fn post(&self, s: &mut pprust_hir::State, node: pprust_hir::AnnNode) -> io::Result<()> {
|
||||
fn post(&self, s: &mut pprust_hir::State<'_>, node: pprust_hir::AnnNode<'_>) -> io::Result<()> {
|
||||
match node {
|
||||
pprust_hir::AnnNode::Expr(expr) => {
|
||||
s.s.space()?;
|
||||
|
|
@ -580,7 +580,11 @@ impl UserIdentifiedItem {
|
|||
}
|
||||
}
|
||||
|
||||
fn to_one_node_id(self, user_option: &str, sess: &Session, map: &hir_map::Map) -> ast::NodeId {
|
||||
fn to_one_node_id(self,
|
||||
user_option: &str,
|
||||
sess: &Session,
|
||||
map: &hir_map::Map<'_>)
|
||||
-> ast::NodeId {
|
||||
let fail_because = |is_wrong_because| -> ast::NodeId {
|
||||
let message = format!("{} needs NodeId (int) or unique path suffix (b::c::d); got \
|
||||
{}, which {}",
|
||||
|
|
|
|||
|
|
@ -886,7 +886,10 @@ fn safe_remove_dir_all(p: &Path) -> io::Result<()> {
|
|||
fn safe_remove_file(p: &Path) -> io::Result<()> {
|
||||
if p.exists() {
|
||||
let canonicalized = p.canonicalize()?;
|
||||
std_fs::remove_file(canonicalized)
|
||||
match std_fs::remove_file(canonicalized) {
|
||||
Err(ref err) if err.kind() == io::ErrorKind::NotFound => Ok(()),
|
||||
result => result,
|
||||
}
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
authors = ["The Rust Project Developers"]
|
||||
name = "rustc_interface"
|
||||
version = "0.0.0"
|
||||
edition = "2018"
|
||||
|
||||
[lib]
|
||||
name = "rustc_interface"
|
||||
|
|
@ -10,7 +11,7 @@ crate-type = ["dylib"]
|
|||
|
||||
[dependencies]
|
||||
log = "0.4"
|
||||
rustc-rayon = "0.1.1"
|
||||
rayon = { version = "0.1.1", package = "rustc-rayon" }
|
||||
smallvec = { version = "0.6.7", features = ["union", "may_dangle"] }
|
||||
scoped-tls = "1.0"
|
||||
syntax = { path = "../libsyntax" }
|
||||
|
|
|
|||
|
|
@ -1,4 +1,8 @@
|
|||
use queries::Queries;
|
||||
use crate::queries::Queries;
|
||||
use crate::util;
|
||||
use crate::profile;
|
||||
pub use crate::passes::BoxedResolver;
|
||||
|
||||
use rustc::lint;
|
||||
use rustc::session::config::{self, Input};
|
||||
use rustc::session::{DiagnosticOutput, Session};
|
||||
|
|
@ -15,10 +19,6 @@ use std::result;
|
|||
use std::sync::{Arc, Mutex};
|
||||
use syntax;
|
||||
use syntax::source_map::{FileLoader, SourceMap};
|
||||
use util;
|
||||
use profile;
|
||||
|
||||
pub use passes::BoxedResolver;
|
||||
|
||||
pub type Result<T> = result::Result<T, ErrorReported>;
|
||||
|
||||
|
|
|
|||
|
|
@ -6,37 +6,14 @@
|
|||
#![feature(generators)]
|
||||
#![cfg_attr(unix, feature(libc))]
|
||||
|
||||
#![deny(rust_2018_idioms)]
|
||||
|
||||
#![allow(unused_imports)]
|
||||
|
||||
#![recursion_limit="256"]
|
||||
|
||||
#[cfg(unix)]
|
||||
extern crate libc;
|
||||
#[macro_use]
|
||||
extern crate log;
|
||||
extern crate rustc;
|
||||
extern crate rustc_codegen_utils;
|
||||
extern crate rustc_allocator;
|
||||
extern crate rustc_borrowck;
|
||||
extern crate rustc_incremental;
|
||||
extern crate rustc_traits;
|
||||
#[macro_use]
|
||||
extern crate rustc_data_structures;
|
||||
extern crate rustc_errors;
|
||||
extern crate rustc_lint;
|
||||
extern crate rustc_metadata;
|
||||
extern crate rustc_mir;
|
||||
extern crate rustc_passes;
|
||||
extern crate rustc_plugin;
|
||||
extern crate rustc_privacy;
|
||||
extern crate rustc_rayon as rayon;
|
||||
extern crate rustc_resolve;
|
||||
extern crate rustc_typeck;
|
||||
extern crate smallvec;
|
||||
extern crate serialize;
|
||||
extern crate syntax;
|
||||
extern crate syntax_pos;
|
||||
extern crate syntax_ext;
|
||||
|
||||
pub mod interface;
|
||||
mod passes;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
use interface::{Compiler, Result};
|
||||
use util;
|
||||
use proc_macro_decls;
|
||||
use crate::interface::{Compiler, Result};
|
||||
use crate::util;
|
||||
use crate::proc_macro_decls;
|
||||
|
||||
use log::{debug, info, warn, log_enabled};
|
||||
use rustc::dep_graph::DepGraph;
|
||||
use rustc::hir;
|
||||
use rustc::hir::lowering::lower_crate;
|
||||
|
|
@ -20,6 +21,7 @@ use rustc::session::search_paths::PathKind;
|
|||
use rustc_allocator as allocator;
|
||||
use rustc_borrowck as borrowck;
|
||||
use rustc_codegen_utils::codegen_backend::CodegenBackend;
|
||||
use rustc_data_structures::{box_region_allow_access, declare_box_region_type, parallel};
|
||||
use rustc_data_structures::fingerprint::Fingerprint;
|
||||
use rustc_data_structures::stable_hasher::StableHasher;
|
||||
use rustc_data_structures::sync::{Lrc, ParallelIterator, par_iter};
|
||||
|
|
@ -328,7 +330,7 @@ pub fn register_plugins<'a>(
|
|||
ls.register_early_pass(Some(sess), true, false, pass);
|
||||
}
|
||||
for pass in late_lint_passes {
|
||||
ls.register_late_pass(Some(sess), true, pass);
|
||||
ls.register_late_pass(Some(sess), true, false, pass);
|
||||
}
|
||||
|
||||
for (name, (to, deprecated_name)) in lint_groups {
|
||||
|
|
@ -758,7 +760,7 @@ pub fn prepare_outputs(
|
|||
Ok(outputs)
|
||||
}
|
||||
|
||||
pub fn default_provide(providers: &mut ty::query::Providers) {
|
||||
pub fn default_provide(providers: &mut ty::query::Providers<'_>) {
|
||||
providers.analysis = analysis;
|
||||
proc_macro_decls::provide(providers);
|
||||
plugin::build::provide(providers);
|
||||
|
|
@ -783,7 +785,7 @@ pub fn default_provide(providers: &mut ty::query::Providers) {
|
|||
lint::provide(providers);
|
||||
}
|
||||
|
||||
pub fn default_provide_extern(providers: &mut ty::query::Providers) {
|
||||
pub fn default_provide_extern(providers: &mut ty::query::Providers<'_>) {
|
||||
cstore::provide_extern(providers);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
use log::debug;
|
||||
use rustc::dep_graph::DepNode;
|
||||
use rustc::session::Session;
|
||||
use rustc::util::common::{ProfQDumpParams, ProfileQueriesMsg, profq_msg, profq_set_chan};
|
||||
use std::sync::mpsc::{Receiver};
|
||||
use std::io::{Write};
|
||||
use rustc::dep_graph::{DepNode};
|
||||
use std::time::{Duration, Instant};
|
||||
|
||||
pub mod trace;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
use interface::{Compiler, Result};
|
||||
use passes::{self, BoxedResolver, ExpansionResult, BoxedGlobalCtxt, PluginInfo};
|
||||
use crate::interface::{Compiler, Result};
|
||||
use crate::passes::{self, BoxedResolver, ExpansionResult, BoxedGlobalCtxt, PluginInfo};
|
||||
|
||||
use rustc_incremental::DepGraphFuture;
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
use rustc::session::config::{Input, OutputFilenames, OutputType};
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
use log::info;
|
||||
use rustc::session::config::{Input, OutputFilenames, ErrorOutputType};
|
||||
use rustc::session::{self, config, early_error, filesearch, Session, DiagnosticOutput};
|
||||
use rustc::session::CrateDisambiguator;
|
||||
|
|
|
|||
|
|
@ -1360,6 +1360,7 @@ fn check_const(cx: &LateContext<'_, '_>, body_id: hir::BodyId) {
|
|||
promoted: None
|
||||
};
|
||||
// trigger the query once for all constants since that will already report the errors
|
||||
// FIXME: Use ensure here
|
||||
let _ = cx.tcx.const_eval(param_env.and(cid));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -125,37 +125,72 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) {
|
|||
store.register_early_pass(sess, false, true, box BuiltinCombinedEarlyLintPass::new());
|
||||
}
|
||||
|
||||
late_lint_methods!(declare_combined_late_lint_pass, [BuiltinCombinedLateLintPass, [
|
||||
late_lint_methods!(declare_combined_late_lint_pass, [BuiltinCombinedModuleLateLintPass, [
|
||||
HardwiredLints: HardwiredLints,
|
||||
WhileTrue: WhileTrue,
|
||||
ImproperCTypes: ImproperCTypes,
|
||||
VariantSizeDifferences: VariantSizeDifferences,
|
||||
BoxPointers: BoxPointers,
|
||||
UnusedAttributes: UnusedAttributes,
|
||||
PathStatements: PathStatements,
|
||||
|
||||
// Depends on referenced function signatures in expressions
|
||||
UnusedResults: UnusedResults,
|
||||
NonSnakeCase: NonSnakeCase,
|
||||
|
||||
NonUpperCaseGlobals: NonUpperCaseGlobals,
|
||||
NonShorthandFieldPatterns: NonShorthandFieldPatterns,
|
||||
UnusedAllocation: UnusedAllocation,
|
||||
|
||||
// Depends on types used in type definitions
|
||||
MissingCopyImplementations: MissingCopyImplementations,
|
||||
UnstableFeatures: UnstableFeatures,
|
||||
InvalidNoMangleItems: InvalidNoMangleItems,
|
||||
|
||||
PluginAsLibrary: PluginAsLibrary,
|
||||
|
||||
// Depends on referenced function signatures in expressions
|
||||
MutableTransmutes: MutableTransmutes,
|
||||
|
||||
// Depends on types of fields, checks if they implement Drop
|
||||
UnionsWithDropFields: UnionsWithDropFields,
|
||||
UnreachablePub: UnreachablePub,
|
||||
UnnameableTestItems: UnnameableTestItems::new(),
|
||||
|
||||
TypeAliasBounds: TypeAliasBounds,
|
||||
UnusedBrokenConst: UnusedBrokenConst,
|
||||
|
||||
TrivialConstraints: TrivialConstraints,
|
||||
TypeLimits: TypeLimits::new(),
|
||||
MissingDoc: MissingDoc::new(),
|
||||
MissingDebugImplementations: MissingDebugImplementations::new(),
|
||||
|
||||
NonSnakeCase: NonSnakeCase,
|
||||
InvalidNoMangleItems: InvalidNoMangleItems,
|
||||
|
||||
// Depends on access levels
|
||||
UnreachablePub: UnreachablePub,
|
||||
|
||||
ExplicitOutlivesRequirements: ExplicitOutlivesRequirements,
|
||||
]], ['tcx]);
|
||||
|
||||
store.register_late_pass(sess, false, box BuiltinCombinedLateLintPass::new());
|
||||
store.register_late_pass(sess, false, true, box BuiltinCombinedModuleLateLintPass::new());
|
||||
|
||||
late_lint_methods!(declare_combined_late_lint_pass, [BuiltinCombinedLateLintPass, [
|
||||
// FIXME: Look into regression when this is used as a module lint
|
||||
// May Depend on constants elsewhere
|
||||
UnusedBrokenConst: UnusedBrokenConst,
|
||||
|
||||
// Uses attr::is_used which is untracked, can't be an incremental module pass.
|
||||
UnusedAttributes: UnusedAttributes,
|
||||
|
||||
// Needs to run after UnusedAttributes as it marks all `feature` attributes as used.
|
||||
UnstableFeatures: UnstableFeatures,
|
||||
|
||||
// Tracks state across modules
|
||||
UnnameableTestItems: UnnameableTestItems::new(),
|
||||
|
||||
// Tracks attributes of parents
|
||||
MissingDoc: MissingDoc::new(),
|
||||
|
||||
// Depends on access levels
|
||||
// FIXME: Turn the computation of types which implement Debug into a query
|
||||
// and change this to a module lint pass
|
||||
MissingDebugImplementations: MissingDebugImplementations::new(),
|
||||
]], ['tcx]);
|
||||
|
||||
store.register_late_pass(sess, false, false, box BuiltinCombinedLateLintPass::new());
|
||||
|
||||
add_lint_group!(sess,
|
||||
"nonstandard_style",
|
||||
|
|
|
|||
|
|
@ -267,11 +267,15 @@ impl LintPass for NonSnakeCase {
|
|||
}
|
||||
|
||||
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonSnakeCase {
|
||||
fn check_crate(&mut self, cx: &LateContext<'_, '_>, cr: &hir::Crate) {
|
||||
fn check_mod(&mut self, cx: &LateContext<'_, '_>, _: &'tcx hir::Mod, _: Span, id: hir::HirId) {
|
||||
if id != hir::CRATE_HIR_ID {
|
||||
return;
|
||||
}
|
||||
|
||||
let crate_ident = if let Some(name) = &cx.tcx.sess.opts.crate_name {
|
||||
Some(Ident::from_str(name))
|
||||
} else {
|
||||
attr::find_by_name(&cr.attrs, "crate_name")
|
||||
attr::find_by_name(&cx.tcx.hir().attrs_by_hir_id(hir::CRATE_HIR_ID), "crate_name")
|
||||
.and_then(|attr| attr.meta())
|
||||
.and_then(|meta| {
|
||||
meta.name_value_literal().and_then(|lit| {
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ use syntax::source_map::{Span, DUMMY_SP};
|
|||
use crate::interpret::{self,
|
||||
PlaceTy, MPlaceTy, MemPlace, OpTy, ImmTy, Immediate, Scalar, Pointer,
|
||||
RawConst, ConstValue,
|
||||
EvalResult, EvalError, EvalErrorKind, GlobalId, EvalContext, StackPopCleanup,
|
||||
EvalResult, EvalError, EvalErrorKind, GlobalId, InterpretCx, StackPopCleanup,
|
||||
Allocation, AllocId, MemoryKind,
|
||||
snapshot, RefTracking,
|
||||
};
|
||||
|
|
@ -34,7 +34,7 @@ const STEPS_UNTIL_DETECTOR_ENABLED: isize = 1_000_000;
|
|||
/// Should be a power of two for performance reasons.
|
||||
const DETECTOR_SNAPSHOT_PERIOD: isize = 256;
|
||||
|
||||
/// The `EvalContext` is only meant to be used to do field and index projections into constants for
|
||||
/// The `InterpretCx` is only meant to be used to do field and index projections into constants for
|
||||
/// `simd_shuffle` and const patterns in match arms.
|
||||
///
|
||||
/// The function containing the `match` that is currently being analyzed may have generic bounds
|
||||
|
|
@ -47,7 +47,7 @@ pub(crate) fn mk_eval_cx<'a, 'mir, 'tcx>(
|
|||
param_env: ty::ParamEnv<'tcx>,
|
||||
) -> CompileTimeEvalContext<'a, 'mir, 'tcx> {
|
||||
debug!("mk_eval_cx: {:?}", param_env);
|
||||
EvalContext::new(tcx.at(span), param_env, CompileTimeInterpreter::new())
|
||||
InterpretCx::new(tcx.at(span), param_env, CompileTimeInterpreter::new())
|
||||
}
|
||||
|
||||
pub(crate) fn eval_promoted<'a, 'mir, 'tcx>(
|
||||
|
|
@ -116,7 +116,7 @@ fn eval_body_and_ecx<'a, 'mir, 'tcx>(
|
|||
// and try improving it down the road when more information is available
|
||||
let span = tcx.def_span(cid.instance.def_id());
|
||||
let span = mir.map(|mir| mir.span).unwrap_or(span);
|
||||
let mut ecx = EvalContext::new(tcx.at(span), param_env, CompileTimeInterpreter::new());
|
||||
let mut ecx = InterpretCx::new(tcx.at(span), param_env, CompileTimeInterpreter::new());
|
||||
let r = eval_body_using_ecx(&mut ecx, cid, mir, param_env);
|
||||
(r, ecx)
|
||||
}
|
||||
|
|
@ -292,7 +292,7 @@ impl<K: Hash + Eq, V> interpret::AllocMap<K, V> for FxHashMap<K, V> {
|
|||
}
|
||||
|
||||
type CompileTimeEvalContext<'a, 'mir, 'tcx> =
|
||||
EvalContext<'a, 'mir, 'tcx, CompileTimeInterpreter<'a, 'mir, 'tcx>>;
|
||||
InterpretCx<'a, 'mir, 'tcx, CompileTimeInterpreter<'a, 'mir, 'tcx>>;
|
||||
|
||||
impl interpret::MayLeak for ! {
|
||||
#[inline(always)]
|
||||
|
|
@ -317,12 +317,12 @@ impl<'a, 'mir, 'tcx> interpret::Machine<'a, 'mir, 'tcx>
|
|||
const STATIC_KIND: Option<!> = None; // no copying of statics allowed
|
||||
|
||||
#[inline(always)]
|
||||
fn enforce_validity(_ecx: &EvalContext<'a, 'mir, 'tcx, Self>) -> bool {
|
||||
fn enforce_validity(_ecx: &InterpretCx<'a, 'mir, 'tcx, Self>) -> bool {
|
||||
false // for now, we don't enforce validity
|
||||
}
|
||||
|
||||
fn find_fn(
|
||||
ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>,
|
||||
ecx: &mut InterpretCx<'a, 'mir, 'tcx, Self>,
|
||||
instance: ty::Instance<'tcx>,
|
||||
args: &[OpTy<'tcx>],
|
||||
dest: Option<PlaceTy<'tcx>>,
|
||||
|
|
@ -362,7 +362,7 @@ impl<'a, 'mir, 'tcx> interpret::Machine<'a, 'mir, 'tcx>
|
|||
}
|
||||
|
||||
fn call_intrinsic(
|
||||
ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>,
|
||||
ecx: &mut InterpretCx<'a, 'mir, 'tcx, Self>,
|
||||
instance: ty::Instance<'tcx>,
|
||||
args: &[OpTy<'tcx>],
|
||||
dest: PlaceTy<'tcx>,
|
||||
|
|
@ -378,7 +378,7 @@ impl<'a, 'mir, 'tcx> interpret::Machine<'a, 'mir, 'tcx>
|
|||
}
|
||||
|
||||
fn ptr_op(
|
||||
_ecx: &EvalContext<'a, 'mir, 'tcx, Self>,
|
||||
_ecx: &InterpretCx<'a, 'mir, 'tcx, Self>,
|
||||
_bin_op: mir::BinOp,
|
||||
_left: ImmTy<'tcx>,
|
||||
_right: ImmTy<'tcx>,
|
||||
|
|
@ -406,7 +406,7 @@ impl<'a, 'mir, 'tcx> interpret::Machine<'a, 'mir, 'tcx>
|
|||
}
|
||||
|
||||
fn box_alloc(
|
||||
_ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>,
|
||||
_ecx: &mut InterpretCx<'a, 'mir, 'tcx, Self>,
|
||||
_dest: PlaceTy<'tcx>,
|
||||
) -> EvalResult<'tcx> {
|
||||
Err(
|
||||
|
|
@ -414,7 +414,7 @@ impl<'a, 'mir, 'tcx> interpret::Machine<'a, 'mir, 'tcx>
|
|||
)
|
||||
}
|
||||
|
||||
fn before_terminator(ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>) -> EvalResult<'tcx> {
|
||||
fn before_terminator(ecx: &mut InterpretCx<'a, 'mir, 'tcx, Self>) -> EvalResult<'tcx> {
|
||||
{
|
||||
let steps = &mut ecx.machine.steps_since_detector_enabled;
|
||||
|
||||
|
|
@ -440,7 +440,7 @@ impl<'a, 'mir, 'tcx> interpret::Machine<'a, 'mir, 'tcx>
|
|||
|
||||
#[inline(always)]
|
||||
fn tag_new_allocation(
|
||||
_ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>,
|
||||
_ecx: &mut InterpretCx<'a, 'mir, 'tcx, Self>,
|
||||
ptr: Pointer,
|
||||
_kind: MemoryKind<Self::MemoryKinds>,
|
||||
) -> Pointer {
|
||||
|
|
@ -449,7 +449,7 @@ impl<'a, 'mir, 'tcx> interpret::Machine<'a, 'mir, 'tcx>
|
|||
|
||||
#[inline(always)]
|
||||
fn stack_push(
|
||||
_ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>,
|
||||
_ecx: &mut InterpretCx<'a, 'mir, 'tcx, Self>,
|
||||
) -> EvalResult<'tcx> {
|
||||
Ok(())
|
||||
}
|
||||
|
|
@ -457,7 +457,7 @@ impl<'a, 'mir, 'tcx> interpret::Machine<'a, 'mir, 'tcx>
|
|||
/// Called immediately before a stack frame gets popped.
|
||||
#[inline(always)]
|
||||
fn stack_pop(
|
||||
_ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>,
|
||||
_ecx: &mut InterpretCx<'a, 'mir, 'tcx, Self>,
|
||||
_extra: (),
|
||||
) -> EvalResult<'tcx> {
|
||||
Ok(())
|
||||
|
|
@ -504,7 +504,7 @@ pub fn const_variant_index<'a, 'tcx>(
|
|||
}
|
||||
|
||||
pub fn error_to_const_error<'a, 'mir, 'tcx>(
|
||||
ecx: &EvalContext<'a, 'mir, 'tcx, CompileTimeInterpreter<'a, 'mir, 'tcx>>,
|
||||
ecx: &InterpretCx<'a, 'mir, 'tcx, CompileTimeInterpreter<'a, 'mir, 'tcx>>,
|
||||
mut error: EvalError<'tcx>
|
||||
) -> ConstEvalErr<'tcx> {
|
||||
error.print_backtrace();
|
||||
|
|
|
|||
|
|
@ -9,9 +9,9 @@ use rustc::mir::interpret::{
|
|||
use rustc::mir::CastKind;
|
||||
use rustc_apfloat::Float;
|
||||
|
||||
use super::{EvalContext, Machine, PlaceTy, OpTy, ImmTy, Immediate};
|
||||
use super::{InterpretCx, Machine, PlaceTy, OpTy, ImmTy, Immediate};
|
||||
|
||||
impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
|
||||
impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tcx, M> {
|
||||
fn type_is_fat_ptr(&self, ty: Ty<'tcx>) -> bool {
|
||||
match ty.sty {
|
||||
ty::RawPtr(ty::TypeAndMut { ty, .. }) |
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ use super::{
|
|||
Memory, Machine
|
||||
};
|
||||
|
||||
pub struct EvalContext<'a, 'mir, 'tcx: 'a + 'mir, M: Machine<'a, 'mir, 'tcx>> {
|
||||
pub struct InterpretCx<'a, 'mir, 'tcx: 'a + 'mir, M: Machine<'a, 'mir, 'tcx>> {
|
||||
/// Stores the `Machine` instance.
|
||||
pub machine: M,
|
||||
|
||||
|
|
@ -141,7 +141,7 @@ impl<'tcx, Tag> LocalState<'tcx, Tag> {
|
|||
}
|
||||
|
||||
impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> HasDataLayout
|
||||
for EvalContext<'a, 'mir, 'tcx, M>
|
||||
for InterpretCx<'a, 'mir, 'tcx, M>
|
||||
{
|
||||
#[inline]
|
||||
fn data_layout(&self) -> &layout::TargetDataLayout {
|
||||
|
|
@ -149,7 +149,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> HasDataLayout
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, 'mir, 'tcx, M> layout::HasTyCtxt<'tcx> for EvalContext<'a, 'mir, 'tcx, M>
|
||||
impl<'a, 'mir, 'tcx, M> layout::HasTyCtxt<'tcx> for InterpretCx<'a, 'mir, 'tcx, M>
|
||||
where M: Machine<'a, 'mir, 'tcx>
|
||||
{
|
||||
#[inline]
|
||||
|
|
@ -159,7 +159,7 @@ impl<'a, 'mir, 'tcx, M> layout::HasTyCtxt<'tcx> for EvalContext<'a, 'mir, 'tcx,
|
|||
}
|
||||
|
||||
impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> LayoutOf
|
||||
for EvalContext<'a, 'mir, 'tcx, M>
|
||||
for InterpretCx<'a, 'mir, 'tcx, M>
|
||||
{
|
||||
type Ty = Ty<'tcx>;
|
||||
type TyLayout = EvalResult<'tcx, TyLayout<'tcx>>;
|
||||
|
|
@ -171,13 +171,13 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> LayoutOf
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
|
||||
impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tcx, M> {
|
||||
pub fn new(
|
||||
tcx: TyCtxtAt<'a, 'tcx, 'tcx>,
|
||||
param_env: ty::ParamEnv<'tcx>,
|
||||
machine: M,
|
||||
) -> Self {
|
||||
EvalContext {
|
||||
InterpretCx {
|
||||
machine,
|
||||
tcx,
|
||||
param_env,
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ use rustc::mir::interpret::{
|
|||
};
|
||||
|
||||
use super::{
|
||||
Machine, PlaceTy, OpTy, EvalContext,
|
||||
Machine, PlaceTy, OpTy, InterpretCx,
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -36,7 +36,7 @@ fn numeric_intrinsic<'tcx, Tag>(
|
|||
Ok(Scalar::from_uint(bits_out, size))
|
||||
}
|
||||
|
||||
impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
|
||||
impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tcx, M> {
|
||||
/// Returns `true` if emulation happened.
|
||||
pub fn emulate_intrinsic(
|
||||
&mut self,
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ use rustc::ty::{self, query::TyCtxtAt};
|
|||
|
||||
use super::{
|
||||
Allocation, AllocId, EvalResult, Scalar, AllocationExtra,
|
||||
EvalContext, PlaceTy, MPlaceTy, OpTy, ImmTy, Pointer, MemoryKind,
|
||||
InterpretCx, PlaceTy, MPlaceTy, OpTy, ImmTy, Pointer, MemoryKind,
|
||||
};
|
||||
|
||||
/// Whether this kind of memory is allowed to leak
|
||||
|
|
@ -95,11 +95,11 @@ pub trait Machine<'a, 'mir, 'tcx>: Sized {
|
|||
const STATIC_KIND: Option<Self::MemoryKinds>;
|
||||
|
||||
/// Whether to enforce the validity invariant
|
||||
fn enforce_validity(ecx: &EvalContext<'a, 'mir, 'tcx, Self>) -> bool;
|
||||
fn enforce_validity(ecx: &InterpretCx<'a, 'mir, 'tcx, Self>) -> bool;
|
||||
|
||||
/// Called before a basic block terminator is executed.
|
||||
/// You can use this to detect endlessly running programs.
|
||||
fn before_terminator(ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>) -> EvalResult<'tcx>;
|
||||
fn before_terminator(ecx: &mut InterpretCx<'a, 'mir, 'tcx, Self>) -> EvalResult<'tcx>;
|
||||
|
||||
/// Entry point to all function calls.
|
||||
///
|
||||
|
|
@ -112,7 +112,7 @@ pub trait Machine<'a, 'mir, 'tcx>: Sized {
|
|||
/// Passing `dest`and `ret` in the same `Option` proved very annoying when only one of them
|
||||
/// was used.
|
||||
fn find_fn(
|
||||
ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>,
|
||||
ecx: &mut InterpretCx<'a, 'mir, 'tcx, Self>,
|
||||
instance: ty::Instance<'tcx>,
|
||||
args: &[OpTy<'tcx, Self::PointerTag>],
|
||||
dest: Option<PlaceTy<'tcx, Self::PointerTag>>,
|
||||
|
|
@ -122,7 +122,7 @@ pub trait Machine<'a, 'mir, 'tcx>: Sized {
|
|||
/// Directly process an intrinsic without pushing a stack frame.
|
||||
/// If this returns successfully, the engine will take care of jumping to the next block.
|
||||
fn call_intrinsic(
|
||||
ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>,
|
||||
ecx: &mut InterpretCx<'a, 'mir, 'tcx, Self>,
|
||||
instance: ty::Instance<'tcx>,
|
||||
args: &[OpTy<'tcx, Self::PointerTag>],
|
||||
dest: PlaceTy<'tcx, Self::PointerTag>,
|
||||
|
|
@ -156,7 +156,7 @@ pub trait Machine<'a, 'mir, 'tcx>: Sized {
|
|||
///
|
||||
/// Returns a (value, overflowed) pair if the operation succeeded
|
||||
fn ptr_op(
|
||||
ecx: &EvalContext<'a, 'mir, 'tcx, Self>,
|
||||
ecx: &InterpretCx<'a, 'mir, 'tcx, Self>,
|
||||
bin_op: mir::BinOp,
|
||||
left: ImmTy<'tcx, Self::PointerTag>,
|
||||
right: ImmTy<'tcx, Self::PointerTag>,
|
||||
|
|
@ -164,13 +164,13 @@ pub trait Machine<'a, 'mir, 'tcx>: Sized {
|
|||
|
||||
/// Heap allocations via the `box` keyword.
|
||||
fn box_alloc(
|
||||
ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>,
|
||||
ecx: &mut InterpretCx<'a, 'mir, 'tcx, Self>,
|
||||
dest: PlaceTy<'tcx, Self::PointerTag>,
|
||||
) -> EvalResult<'tcx>;
|
||||
|
||||
/// Adds the tag for a newly allocated pointer.
|
||||
fn tag_new_allocation(
|
||||
ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>,
|
||||
ecx: &mut InterpretCx<'a, 'mir, 'tcx, Self>,
|
||||
ptr: Pointer,
|
||||
kind: MemoryKind<Self::MemoryKinds>,
|
||||
) -> Pointer<Self::PointerTag>;
|
||||
|
|
@ -180,7 +180,7 @@ pub trait Machine<'a, 'mir, 'tcx>: Sized {
|
|||
/// `mutability` can be `None` in case a raw ptr is being dereferenced.
|
||||
#[inline]
|
||||
fn tag_dereference(
|
||||
_ecx: &EvalContext<'a, 'mir, 'tcx, Self>,
|
||||
_ecx: &InterpretCx<'a, 'mir, 'tcx, Self>,
|
||||
place: MPlaceTy<'tcx, Self::PointerTag>,
|
||||
_mutability: Option<hir::Mutability>,
|
||||
) -> EvalResult<'tcx, Scalar<Self::PointerTag>> {
|
||||
|
|
@ -190,7 +190,7 @@ pub trait Machine<'a, 'mir, 'tcx>: Sized {
|
|||
/// Executes a retagging operation
|
||||
#[inline]
|
||||
fn retag(
|
||||
_ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>,
|
||||
_ecx: &mut InterpretCx<'a, 'mir, 'tcx, Self>,
|
||||
_kind: mir::RetagKind,
|
||||
_place: PlaceTy<'tcx, Self::PointerTag>,
|
||||
) -> EvalResult<'tcx> {
|
||||
|
|
@ -199,12 +199,12 @@ pub trait Machine<'a, 'mir, 'tcx>: Sized {
|
|||
|
||||
/// Called immediately before a new stack frame got pushed
|
||||
fn stack_push(
|
||||
ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>,
|
||||
ecx: &mut InterpretCx<'a, 'mir, 'tcx, Self>,
|
||||
) -> EvalResult<'tcx, Self::FrameExtra>;
|
||||
|
||||
/// Called immediately after a stack frame gets popped
|
||||
fn stack_pop(
|
||||
ecx: &mut EvalContext<'a, 'mir, 'tcx, Self>,
|
||||
ecx: &mut InterpretCx<'a, 'mir, 'tcx, Self>,
|
||||
extra: Self::FrameExtra,
|
||||
) -> EvalResult<'tcx>;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ mod visitor;
|
|||
pub use rustc::mir::interpret::*; // have all the `interpret` symbols in one place: here
|
||||
|
||||
pub use self::eval_context::{
|
||||
EvalContext, Frame, StackPopCleanup, LocalState, LocalValue,
|
||||
InterpretCx, Frame, StackPopCleanup, LocalState, LocalValue,
|
||||
};
|
||||
|
||||
pub use self::place::{Place, PlaceTy, MemPlace, MPlaceTy};
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ use rustc::mir::interpret::{
|
|||
sign_extend, truncate,
|
||||
};
|
||||
use super::{
|
||||
EvalContext, Machine,
|
||||
InterpretCx, Machine,
|
||||
MemPlace, MPlaceTy, PlaceTy, Place, MemoryKind,
|
||||
};
|
||||
pub use rustc::mir::interpret::ScalarMaybeUndef;
|
||||
|
|
@ -267,7 +267,7 @@ pub(super) fn from_known_layout<'tcx>(
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
|
||||
impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tcx, M> {
|
||||
/// Try reading an immediate in memory; this is interesting particularly for ScalarPair.
|
||||
/// Returns `None` if the layout does not permit loading this as a value.
|
||||
fn try_read_immediate_from_mplace(
|
||||
|
|
|
|||
|
|
@ -5,10 +5,10 @@ use rustc_apfloat::ieee::{Double, Single};
|
|||
use rustc_apfloat::Float;
|
||||
use rustc::mir::interpret::{EvalResult, Scalar};
|
||||
|
||||
use super::{EvalContext, PlaceTy, Immediate, Machine, ImmTy};
|
||||
use super::{InterpretCx, PlaceTy, Immediate, Machine, ImmTy};
|
||||
|
||||
|
||||
impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
|
||||
impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tcx, M> {
|
||||
/// Applies the binary operation `op` to the two operands and writes a tuple of the result
|
||||
/// and a boolean signifying the potential overflow to the destination.
|
||||
pub fn binop_with_overflow(
|
||||
|
|
@ -37,7 +37,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
|
||||
impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tcx, M> {
|
||||
fn binary_char_op(
|
||||
&self,
|
||||
bin_op: mir::BinOp,
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ use rustc::ty::TypeFoldable;
|
|||
|
||||
use super::{
|
||||
GlobalId, AllocId, Allocation, Scalar, EvalResult, Pointer, PointerArithmetic,
|
||||
EvalContext, Machine, AllocMap, AllocationExtra,
|
||||
InterpretCx, Machine, AllocMap, AllocationExtra,
|
||||
RawConst, Immediate, ImmTy, ScalarMaybeUndef, Operand, OpTy, MemoryKind
|
||||
};
|
||||
|
||||
|
|
@ -305,7 +305,7 @@ impl<'tcx, Tag: ::std::fmt::Debug> PlaceTy<'tcx, Tag> {
|
|||
}
|
||||
|
||||
// separating the pointer tag for `impl Trait`, see https://github.com/rust-lang/rust/issues/54385
|
||||
impl<'a, 'mir, 'tcx, Tag, M> EvalContext<'a, 'mir, 'tcx, M>
|
||||
impl<'a, 'mir, 'tcx, Tag, M> InterpretCx<'a, 'mir, 'tcx, M>
|
||||
where
|
||||
// FIXME: Working around https://github.com/rust-lang/rust/issues/54385
|
||||
Tag: ::std::fmt::Debug+Default+Copy+Eq+Hash+'static,
|
||||
|
|
@ -607,7 +607,7 @@ where
|
|||
// global table but not in its local memory: It calls back into tcx through
|
||||
// a query, triggering the CTFE machinery to actually turn this lazy reference
|
||||
// into a bunch of bytes. IOW, statics are evaluated with CTFE even when
|
||||
// this EvalContext uses another Machine (e.g., in miri). This is what we
|
||||
// this InterpretCx uses another Machine (e.g., in miri). This is what we
|
||||
// want! This way, computing statics works concistently between codegen
|
||||
// and miri: They use the same query to eventually obtain a `ty::Const`
|
||||
// and use that for further computation.
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
//! This module contains the `EvalContext` methods for executing a single step of the interpreter.
|
||||
//! This module contains the `InterpretCx` methods for executing a single step of the interpreter.
|
||||
//!
|
||||
//! The main entry point is the `step` method.
|
||||
|
||||
|
|
@ -6,7 +6,7 @@ use rustc::mir;
|
|||
use rustc::ty::layout::LayoutOf;
|
||||
use rustc::mir::interpret::{EvalResult, Scalar, PointerArithmetic};
|
||||
|
||||
use super::{EvalContext, Machine};
|
||||
use super::{InterpretCx, Machine};
|
||||
|
||||
/// Classify whether an operator is "left-homogeneous", i.e., the LHS has the
|
||||
/// same type as the result.
|
||||
|
|
@ -35,7 +35,7 @@ fn binop_right_homogeneous(op: mir::BinOp) -> bool {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
|
||||
impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tcx, M> {
|
||||
pub fn run(&mut self) -> EvalResult<'tcx> {
|
||||
while self.step()? {}
|
||||
Ok(())
|
||||
|
|
|
|||
|
|
@ -7,10 +7,10 @@ use rustc_target::spec::abi::Abi;
|
|||
|
||||
use rustc::mir::interpret::{EvalResult, PointerArithmetic, EvalErrorKind, Scalar};
|
||||
use super::{
|
||||
EvalContext, Machine, Immediate, OpTy, ImmTy, PlaceTy, MPlaceTy, StackPopCleanup
|
||||
InterpretCx, Machine, Immediate, OpTy, ImmTy, PlaceTy, MPlaceTy, StackPopCleanup
|
||||
};
|
||||
|
||||
impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
|
||||
impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tcx, M> {
|
||||
#[inline]
|
||||
pub fn goto_block(&mut self, target: Option<mir::BasicBlock>) -> EvalResult<'tcx> {
|
||||
if let Some(target) = target {
|
||||
|
|
|
|||
|
|
@ -3,9 +3,9 @@ use rustc::ty::{self, Ty};
|
|||
use rustc::ty::layout::{Size, Align, LayoutOf};
|
||||
use rustc::mir::interpret::{Scalar, Pointer, EvalResult, PointerArithmetic};
|
||||
|
||||
use super::{EvalContext, Machine, MemoryKind};
|
||||
use super::{InterpretCx, Machine, MemoryKind};
|
||||
|
||||
impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
|
||||
impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tcx, M> {
|
||||
/// Creates a dynamic vtable for the given type and vtable origin. This is used only for
|
||||
/// objects.
|
||||
///
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ use rustc::mir::interpret::{
|
|||
};
|
||||
|
||||
use super::{
|
||||
OpTy, Machine, EvalContext, ValueVisitor, MPlaceTy,
|
||||
OpTy, Machine, InterpretCx, ValueVisitor, MPlaceTy,
|
||||
};
|
||||
|
||||
macro_rules! validation_failure {
|
||||
|
|
@ -153,7 +153,7 @@ struct ValidityVisitor<'rt, 'a: 'rt, 'mir: 'rt, 'tcx: 'a+'rt+'mir, M: Machine<'a
|
|||
path: Vec<PathElem>,
|
||||
ref_tracking: Option<&'rt mut RefTracking<MPlaceTy<'tcx, M::PointerTag>>>,
|
||||
const_mode: bool,
|
||||
ecx: &'rt EvalContext<'a, 'mir, 'tcx, M>,
|
||||
ecx: &'rt InterpretCx<'a, 'mir, 'tcx, M>,
|
||||
}
|
||||
|
||||
impl<'rt, 'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> ValidityVisitor<'rt, 'a, 'mir, 'tcx, M> {
|
||||
|
|
@ -224,7 +224,7 @@ impl<'rt, 'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>>
|
|||
type V = OpTy<'tcx, M::PointerTag>;
|
||||
|
||||
#[inline(always)]
|
||||
fn ecx(&self) -> &EvalContext<'a, 'mir, 'tcx, M> {
|
||||
fn ecx(&self) -> &InterpretCx<'a, 'mir, 'tcx, M> {
|
||||
&self.ecx
|
||||
}
|
||||
|
||||
|
|
@ -587,7 +587,7 @@ impl<'rt, 'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>>
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
|
||||
impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tcx, M> {
|
||||
/// This function checks the data at `op`. `op` is assumed to cover valid memory if it
|
||||
/// is an indirect operand.
|
||||
/// It will error if the bits at the destination do not match the ones described by the layout.
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ use rustc::mir::interpret::{
|
|||
};
|
||||
|
||||
use super::{
|
||||
Machine, EvalContext, MPlaceTy, OpTy,
|
||||
Machine, InterpretCx, MPlaceTy, OpTy,
|
||||
};
|
||||
|
||||
// A thing that we can project into, and that has a layout.
|
||||
|
|
@ -22,7 +22,7 @@ pub trait Value<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>>: Copy
|
|||
/// Makes this into an `OpTy`.
|
||||
fn to_op(
|
||||
self,
|
||||
ecx: &EvalContext<'a, 'mir, 'tcx, M>,
|
||||
ecx: &InterpretCx<'a, 'mir, 'tcx, M>,
|
||||
) -> EvalResult<'tcx, OpTy<'tcx, M::PointerTag>>;
|
||||
|
||||
/// Creates this from an `MPlaceTy`.
|
||||
|
|
@ -31,14 +31,14 @@ pub trait Value<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>>: Copy
|
|||
/// Projects to the given enum variant.
|
||||
fn project_downcast(
|
||||
self,
|
||||
ecx: &EvalContext<'a, 'mir, 'tcx, M>,
|
||||
ecx: &InterpretCx<'a, 'mir, 'tcx, M>,
|
||||
variant: VariantIdx,
|
||||
) -> EvalResult<'tcx, Self>;
|
||||
|
||||
/// Projects to the n-th field.
|
||||
fn project_field(
|
||||
self,
|
||||
ecx: &EvalContext<'a, 'mir, 'tcx, M>,
|
||||
ecx: &InterpretCx<'a, 'mir, 'tcx, M>,
|
||||
field: u64,
|
||||
) -> EvalResult<'tcx, Self>;
|
||||
}
|
||||
|
|
@ -56,7 +56,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Value<'a, 'mir, 'tcx, M>
|
|||
#[inline(always)]
|
||||
fn to_op(
|
||||
self,
|
||||
_ecx: &EvalContext<'a, 'mir, 'tcx, M>,
|
||||
_ecx: &InterpretCx<'a, 'mir, 'tcx, M>,
|
||||
) -> EvalResult<'tcx, OpTy<'tcx, M::PointerTag>> {
|
||||
Ok(self)
|
||||
}
|
||||
|
|
@ -69,7 +69,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Value<'a, 'mir, 'tcx, M>
|
|||
#[inline(always)]
|
||||
fn project_downcast(
|
||||
self,
|
||||
ecx: &EvalContext<'a, 'mir, 'tcx, M>,
|
||||
ecx: &InterpretCx<'a, 'mir, 'tcx, M>,
|
||||
variant: VariantIdx,
|
||||
) -> EvalResult<'tcx, Self> {
|
||||
ecx.operand_downcast(self, variant)
|
||||
|
|
@ -78,7 +78,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Value<'a, 'mir, 'tcx, M>
|
|||
#[inline(always)]
|
||||
fn project_field(
|
||||
self,
|
||||
ecx: &EvalContext<'a, 'mir, 'tcx, M>,
|
||||
ecx: &InterpretCx<'a, 'mir, 'tcx, M>,
|
||||
field: u64,
|
||||
) -> EvalResult<'tcx, Self> {
|
||||
ecx.operand_field(self, field)
|
||||
|
|
@ -95,7 +95,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Value<'a, 'mir, 'tcx, M>
|
|||
#[inline(always)]
|
||||
fn to_op(
|
||||
self,
|
||||
_ecx: &EvalContext<'a, 'mir, 'tcx, M>,
|
||||
_ecx: &InterpretCx<'a, 'mir, 'tcx, M>,
|
||||
) -> EvalResult<'tcx, OpTy<'tcx, M::PointerTag>> {
|
||||
Ok(self.into())
|
||||
}
|
||||
|
|
@ -108,7 +108,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Value<'a, 'mir, 'tcx, M>
|
|||
#[inline(always)]
|
||||
fn project_downcast(
|
||||
self,
|
||||
ecx: &EvalContext<'a, 'mir, 'tcx, M>,
|
||||
ecx: &InterpretCx<'a, 'mir, 'tcx, M>,
|
||||
variant: VariantIdx,
|
||||
) -> EvalResult<'tcx, Self> {
|
||||
ecx.mplace_downcast(self, variant)
|
||||
|
|
@ -117,7 +117,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Value<'a, 'mir, 'tcx, M>
|
|||
#[inline(always)]
|
||||
fn project_field(
|
||||
self,
|
||||
ecx: &EvalContext<'a, 'mir, 'tcx, M>,
|
||||
ecx: &InterpretCx<'a, 'mir, 'tcx, M>,
|
||||
field: u64,
|
||||
) -> EvalResult<'tcx, Self> {
|
||||
ecx.mplace_field(self, field)
|
||||
|
|
@ -130,9 +130,9 @@ macro_rules! make_value_visitor {
|
|||
pub trait $visitor_trait_name<'a, 'mir, 'tcx: 'mir+'a, M: Machine<'a, 'mir, 'tcx>>: Sized {
|
||||
type V: Value<'a, 'mir, 'tcx, M>;
|
||||
|
||||
/// The visitor must have an `EvalContext` in it.
|
||||
/// The visitor must have an `InterpretCx` in it.
|
||||
fn ecx(&$($mutability)? self)
|
||||
-> &$($mutability)? EvalContext<'a, 'mir, 'tcx, M>;
|
||||
-> &$($mutability)? InterpretCx<'a, 'mir, 'tcx, M>;
|
||||
|
||||
// Recursive actions, ready to be overloaded.
|
||||
/// Visits the given value, dispatching as appropriate to more specialized visitors.
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ use rustc::ty::layout::{
|
|||
HasTyCtxt, TargetDataLayout, HasDataLayout,
|
||||
};
|
||||
|
||||
use crate::interpret::{EvalContext, ScalarMaybeUndef, Immediate, OpTy, ImmTy, MemoryKind};
|
||||
use crate::interpret::{InterpretCx, ScalarMaybeUndef, Immediate, OpTy, ImmTy, MemoryKind};
|
||||
use crate::const_eval::{
|
||||
CompileTimeInterpreter, error_to_const_error, eval_promoted, mk_eval_cx,
|
||||
};
|
||||
|
|
@ -70,7 +70,7 @@ type Const<'tcx> = (OpTy<'tcx>, Span);
|
|||
|
||||
/// Finds optimization opportunities on the MIR.
|
||||
struct ConstPropagator<'a, 'mir, 'tcx:'a+'mir> {
|
||||
ecx: EvalContext<'a, 'mir, 'tcx, CompileTimeInterpreter<'a, 'mir, 'tcx>>,
|
||||
ecx: InterpretCx<'a, 'mir, 'tcx, CompileTimeInterpreter<'a, 'mir, 'tcx>>,
|
||||
mir: &'mir Mir<'tcx>,
|
||||
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
source: MirSource<'tcx>,
|
||||
|
|
|
|||
|
|
@ -1790,8 +1790,7 @@ fn check_mod_privacy<'tcx>(tcx: TyCtxt<'_, 'tcx, 'tcx>, module_def_id: DefId) {
|
|||
current_item: hir::DUMMY_HIR_ID,
|
||||
empty_tables: &empty_tables,
|
||||
};
|
||||
let (module, span, node_id) = tcx.hir().get_module(module_def_id);
|
||||
let hir_id = tcx.hir().node_to_hir_id(node_id);
|
||||
let (module, span, hir_id) = tcx.hir().get_module(module_def_id);
|
||||
intravisit::walk_mod(&mut visitor, module, hir_id);
|
||||
|
||||
// Check privacy of explicitly written types and traits as well as
|
||||
|
|
|
|||
|
|
@ -1233,7 +1233,12 @@ impl<'gcx, 'tcx, 'exprs, E> CoerceMany<'gcx, 'tcx, 'exprs, E>
|
|||
augment_error(&mut db);
|
||||
}
|
||||
|
||||
db.emit();
|
||||
if expression.filter(|e| fcx.is_assign_to_bool(e, expected)).is_some() {
|
||||
// Error reported in `check_assign` so avoid emitting error again.
|
||||
db.delay_as_bug();
|
||||
} else {
|
||||
db.emit();
|
||||
}
|
||||
|
||||
self.final_ty = Some(fcx.tcx.types.err);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -119,44 +119,65 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
let expr_ty = self.resolve_type_vars_with_obligations(checked_ty);
|
||||
let mut err = self.report_mismatched_types(&cause, expected, expr_ty, e);
|
||||
|
||||
// If the expected type is an enum (Issue #55250) with any variants whose
|
||||
// sole field is of the found type, suggest such variants. (Issue #42764)
|
||||
if let ty::Adt(expected_adt, substs) = expected.sty {
|
||||
if expected_adt.is_enum() {
|
||||
let mut compatible_variants = expected_adt.variants
|
||||
.iter()
|
||||
.filter(|variant| variant.fields.len() == 1)
|
||||
.filter_map(|variant| {
|
||||
let sole_field = &variant.fields[0];
|
||||
let sole_field_ty = sole_field.ty(self.tcx, substs);
|
||||
if self.can_coerce(expr_ty, sole_field_ty) {
|
||||
let variant_path = self.tcx.def_path_str(variant.def_id);
|
||||
// FIXME #56861: DRYer prelude filtering
|
||||
Some(variant_path.trim_start_matches("std::prelude::v1::").to_string())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}).peekable();
|
||||
|
||||
if compatible_variants.peek().is_some() {
|
||||
let expr_text = print::to_string(print::NO_ANN, |s| s.print_expr(expr));
|
||||
let suggestions = compatible_variants
|
||||
.map(|v| format!("{}({})", v, expr_text));
|
||||
err.span_suggestions(
|
||||
expr.span,
|
||||
"try using a variant of the expected type",
|
||||
suggestions,
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
}
|
||||
}
|
||||
if self.is_assign_to_bool(expr, expected) {
|
||||
// Error reported in `check_assign` so avoid emitting error again.
|
||||
err.delay_as_bug();
|
||||
return (expected, None)
|
||||
}
|
||||
|
||||
self.suggest_compatible_variants(&mut err, expr, expected, expr_ty);
|
||||
self.suggest_ref_or_into(&mut err, expr, expected, expr_ty);
|
||||
|
||||
(expected, Some(err))
|
||||
}
|
||||
|
||||
/// Returns whether the expected type is `bool` and the expression is `x = y`.
|
||||
pub fn is_assign_to_bool(&self, expr: &hir::Expr, expected: Ty<'tcx>) -> bool {
|
||||
if let hir::ExprKind::Assign(..) = expr.node {
|
||||
return expected == self.tcx.types.bool;
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
/// If the expected type is an enum (Issue #55250) with any variants whose
|
||||
/// sole field is of the found type, suggest such variants. (Issue #42764)
|
||||
fn suggest_compatible_variants(
|
||||
&self,
|
||||
err: &mut DiagnosticBuilder<'_>,
|
||||
expr: &hir::Expr,
|
||||
expected: Ty<'tcx>,
|
||||
expr_ty: Ty<'tcx>,
|
||||
) {
|
||||
if let ty::Adt(expected_adt, substs) = expected.sty {
|
||||
if !expected_adt.is_enum() {
|
||||
return;
|
||||
}
|
||||
|
||||
let mut compatible_variants = expected_adt.variants
|
||||
.iter()
|
||||
.filter(|variant| variant.fields.len() == 1)
|
||||
.filter_map(|variant| {
|
||||
let sole_field = &variant.fields[0];
|
||||
let sole_field_ty = sole_field.ty(self.tcx, substs);
|
||||
if self.can_coerce(expr_ty, sole_field_ty) {
|
||||
let variant_path = self.tcx.def_path_str(variant.def_id);
|
||||
// FIXME #56861: DRYer prelude filtering
|
||||
Some(variant_path.trim_start_matches("std::prelude::v1::").to_string())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}).peekable();
|
||||
|
||||
if compatible_variants.peek().is_some() {
|
||||
let expr_text = print::to_string(print::NO_ANN, |s| s.print_expr(expr));
|
||||
let suggestions = compatible_variants
|
||||
.map(|v| format!("{}({})", v, expr_text));
|
||||
let msg = "try using a variant of the expected type";
|
||||
err.span_suggestions(expr.span, msg, suggestions, Applicability::MaybeIncorrect);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_conversion_methods(&self, span: Span, expected: Ty<'tcx>, checked_ty: Ty<'tcx>)
|
||||
-> Vec<AssociatedItem> {
|
||||
let mut methods = self.probe_for_return_type(span,
|
||||
|
|
|
|||
|
|
@ -246,9 +246,6 @@ pub enum Expectation<'tcx> {
|
|||
/// We know nothing about what type this expression should have.
|
||||
NoExpectation,
|
||||
|
||||
/// This expression is an `if` condition, it must resolve to `bool`.
|
||||
ExpectIfCondition,
|
||||
|
||||
/// This expression should have the type given (or some subtype).
|
||||
ExpectHasType(Ty<'tcx>),
|
||||
|
||||
|
|
@ -328,7 +325,6 @@ impl<'a, 'gcx, 'tcx> Expectation<'tcx> {
|
|||
fn resolve(self, fcx: &FnCtxt<'a, 'gcx, 'tcx>) -> Expectation<'tcx> {
|
||||
match self {
|
||||
NoExpectation => NoExpectation,
|
||||
ExpectIfCondition => ExpectIfCondition,
|
||||
ExpectCastableToType(t) => {
|
||||
ExpectCastableToType(fcx.resolve_type_vars_if_possible(&t))
|
||||
}
|
||||
|
|
@ -344,7 +340,6 @@ impl<'a, 'gcx, 'tcx> Expectation<'tcx> {
|
|||
fn to_option(self, fcx: &FnCtxt<'a, 'gcx, 'tcx>) -> Option<Ty<'tcx>> {
|
||||
match self.resolve(fcx) {
|
||||
NoExpectation => None,
|
||||
ExpectIfCondition => Some(fcx.tcx.types.bool),
|
||||
ExpectCastableToType(ty) |
|
||||
ExpectHasType(ty) |
|
||||
ExpectRvalueLikeUnsized(ty) => Some(ty),
|
||||
|
|
@ -358,7 +353,6 @@ impl<'a, 'gcx, 'tcx> Expectation<'tcx> {
|
|||
fn only_has_type(self, fcx: &FnCtxt<'a, 'gcx, 'tcx>) -> Option<Ty<'tcx>> {
|
||||
match self.resolve(fcx) {
|
||||
ExpectHasType(ty) => Some(ty),
|
||||
ExpectIfCondition => Some(fcx.tcx.types.bool),
|
||||
NoExpectation | ExpectCastableToType(_) | ExpectRvalueLikeUnsized(_) => None,
|
||||
}
|
||||
}
|
||||
|
|
@ -3148,25 +3142,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
}
|
||||
|
||||
if let Some(mut err) = self.demand_suptype_diag(expr.span, expected_ty, ty) {
|
||||
// Add help to type error if this is an `if` condition with an assignment.
|
||||
if let (ExpectIfCondition, &ExprKind::Assign(ref lhs, ref rhs))
|
||||
= (expected, &expr.node)
|
||||
{
|
||||
let msg = "try comparing for equality";
|
||||
if let (Ok(left), Ok(right)) = (
|
||||
self.tcx.sess.source_map().span_to_snippet(lhs.span),
|
||||
self.tcx.sess.source_map().span_to_snippet(rhs.span))
|
||||
{
|
||||
err.span_suggestion(
|
||||
expr.span,
|
||||
msg,
|
||||
format!("{} == {}", left, right),
|
||||
Applicability::MaybeIncorrect);
|
||||
} else {
|
||||
err.help(msg);
|
||||
}
|
||||
if self.is_assign_to_bool(expr, expected_ty) {
|
||||
// Error reported in `check_assign` so avoid emitting error again.
|
||||
// FIXME(centril): Consider removing if/when `if` desugars to `match`.
|
||||
err.delay_as_bug();
|
||||
} else {
|
||||
err.emit();
|
||||
}
|
||||
err.emit();
|
||||
}
|
||||
ty
|
||||
}
|
||||
|
|
@ -3337,7 +3319,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
opt_else_expr: Option<&'gcx hir::Expr>,
|
||||
sp: Span,
|
||||
expected: Expectation<'tcx>) -> Ty<'tcx> {
|
||||
let cond_ty = self.check_expr_meets_expectation_or_error(cond_expr, ExpectIfCondition);
|
||||
let cond_ty = self.check_expr_has_type_or_error(cond_expr, self.tcx.types.bool);
|
||||
let cond_diverges = self.diverges.get();
|
||||
self.diverges.set(Diverges::Maybe);
|
||||
|
||||
|
|
@ -4422,34 +4404,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
tcx.types.never
|
||||
}
|
||||
ExprKind::Assign(ref lhs, ref rhs) => {
|
||||
let lhs_ty = self.check_expr_with_needs(&lhs, Needs::MutPlace);
|
||||
|
||||
let rhs_ty = self.check_expr_coercable_to_type(&rhs, lhs_ty);
|
||||
|
||||
match expected {
|
||||
ExpectIfCondition => {
|
||||
self.tcx.sess.delay_span_bug(lhs.span, "invalid lhs expression in if;\
|
||||
expected error elsehwere");
|
||||
}
|
||||
_ => {
|
||||
// Only check this if not in an `if` condition, as the
|
||||
// mistyped comparison help is more appropriate.
|
||||
if !lhs.is_place_expr() {
|
||||
struct_span_err!(self.tcx.sess, expr.span, E0070,
|
||||
"invalid left-hand side expression")
|
||||
.span_label(expr.span, "left-hand of expression not valid")
|
||||
.emit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self.require_type_is_sized(lhs_ty, lhs.span, traits::AssignmentLhsSized);
|
||||
|
||||
if lhs_ty.references_error() || rhs_ty.references_error() {
|
||||
tcx.types.err
|
||||
} else {
|
||||
tcx.mk_unit()
|
||||
}
|
||||
self.check_assign(expr, expected, lhs, rhs)
|
||||
}
|
||||
ExprKind::If(ref cond, ref then_expr, ref opt_else_expr) => {
|
||||
self.check_then_else(&cond, then_expr, opt_else_expr.as_ref().map(|e| &**e),
|
||||
|
|
@ -4750,6 +4705,51 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Type check assignment expression `expr` of form `lhs = rhs`.
|
||||
/// The expected type is `()` and is passsed to the function for the purposes of diagnostics.
|
||||
fn check_assign(
|
||||
&self,
|
||||
expr: &'gcx hir::Expr,
|
||||
expected: Expectation<'tcx>,
|
||||
lhs: &'gcx hir::Expr,
|
||||
rhs: &'gcx hir::Expr,
|
||||
) -> Ty<'tcx> {
|
||||
let lhs_ty = self.check_expr_with_needs(&lhs, Needs::MutPlace);
|
||||
let rhs_ty = self.check_expr_coercable_to_type(&rhs, lhs_ty);
|
||||
|
||||
let expected_ty = expected.coercion_target_type(self, expr.span);
|
||||
if expected_ty == self.tcx.types.bool {
|
||||
// The expected type is `bool` but this will result in `()` so we can reasonably
|
||||
// say that the user intended to write `lhs == rhs` instead of `lhs = rhs`.
|
||||
// The likely cause of this is `if foo = bar { .. }`.
|
||||
let actual_ty = self.tcx.mk_unit();
|
||||
let mut err = self.demand_suptype_diag(expr.span, expected_ty, actual_ty).unwrap();
|
||||
let msg = "try comparing for equality";
|
||||
let left = self.tcx.sess.source_map().span_to_snippet(lhs.span);
|
||||
let right = self.tcx.sess.source_map().span_to_snippet(rhs.span);
|
||||
if let (Ok(left), Ok(right)) = (left, right) {
|
||||
let help = format!("{} == {}", left, right);
|
||||
err.span_suggestion(expr.span, msg, help, Applicability::MaybeIncorrect);
|
||||
} else {
|
||||
err.help(msg);
|
||||
}
|
||||
err.emit();
|
||||
} else if !lhs.is_place_expr() {
|
||||
struct_span_err!(self.tcx.sess, expr.span, E0070,
|
||||
"invalid left-hand side expression")
|
||||
.span_label(expr.span, "left-hand of expression not valid")
|
||||
.emit();
|
||||
}
|
||||
|
||||
self.require_type_is_sized(lhs_ty, lhs.span, traits::AssignmentLhsSized);
|
||||
|
||||
if lhs_ty.references_error() || rhs_ty.references_error() {
|
||||
self.tcx.types.err
|
||||
} else {
|
||||
self.tcx.mk_unit()
|
||||
}
|
||||
}
|
||||
|
||||
// Finish resolving a path in a struct expression or pattern `S::A { .. }` if necessary.
|
||||
// The newly resolved definition is written into `type_dependent_defs`.
|
||||
fn finish_resolving_struct_path(&self,
|
||||
|
|
|
|||
|
|
@ -130,7 +130,7 @@ pub use alloc_crate::alloc::*;
|
|||
/// program opts in to using jemalloc as the global allocator, `System` will
|
||||
/// still allocate memory using `malloc` and `HeapAlloc`.
|
||||
#[stable(feature = "alloc_system_type", since = "1.28.0")]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
#[derive(Debug, Default, Copy, Clone)]
|
||||
pub struct System;
|
||||
|
||||
// The Alloc impl just forwards to the GlobalAlloc impl, which is in `std::sys::*::alloc`.
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ const ENCLU_EGETKEY: u32 = 1;
|
|||
#[unstable(feature = "sgx_platform", issue = "56975")]
|
||||
pub fn egetkey(request: &Align512<[u8; 512]>) -> Result<Align16<[u8; 16]>, u32> {
|
||||
unsafe {
|
||||
let mut out = MaybeUninit::uninitialized();
|
||||
let mut out = MaybeUninit::uninit();
|
||||
let error;
|
||||
|
||||
asm!(
|
||||
|
|
@ -41,7 +41,7 @@ pub fn egetkey(request: &Align512<[u8; 512]>) -> Result<Align16<[u8; 16]>, u32>
|
|||
);
|
||||
|
||||
match error {
|
||||
0 => Ok(out.into_initialized()),
|
||||
0 => Ok(out.assume_init()),
|
||||
err => Err(err),
|
||||
}
|
||||
}
|
||||
|
|
@ -58,7 +58,7 @@ pub fn ereport(
|
|||
reportdata: &Align128<[u8; 64]>,
|
||||
) -> Align512<[u8; 432]> {
|
||||
unsafe {
|
||||
let mut report = MaybeUninit::uninitialized();
|
||||
let mut report = MaybeUninit::uninit();
|
||||
|
||||
asm!(
|
||||
"enclu"
|
||||
|
|
@ -69,6 +69,6 @@ pub fn ereport(
|
|||
"{rdx}"(report.as_mut_ptr())
|
||||
);
|
||||
|
||||
report.into_initialized()
|
||||
report.assume_init()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -280,7 +280,7 @@ mod tests {
|
|||
let mut init = MaybeUninit::<RWLock>::zeroed();
|
||||
rwlock_new(&mut init);
|
||||
assert_eq!(
|
||||
mem::transmute::<_, [u8; 128]>(init.into_initialized()).as_slice(),
|
||||
mem::transmute::<_, [u8; 128]>(init.assume_init()).as_slice(),
|
||||
RWLOCK_INIT
|
||||
)
|
||||
};
|
||||
|
|
|
|||
|
|
@ -154,7 +154,7 @@ unsafe impl Sync for ReentrantMutex {}
|
|||
|
||||
impl ReentrantMutex {
|
||||
pub fn uninitialized() -> ReentrantMutex {
|
||||
ReentrantMutex { inner: UnsafeCell::new(MaybeUninit::uninitialized()) }
|
||||
ReentrantMutex { inner: UnsafeCell::new(MaybeUninit::uninit()) }
|
||||
}
|
||||
|
||||
pub unsafe fn init(&mut self) {
|
||||
|
|
|
|||
|
|
@ -1257,7 +1257,10 @@ impl Thread {
|
|||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl fmt::Debug for Thread {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
fmt::Debug::fmt(&self.name(), f)
|
||||
f.debug_struct("Thread")
|
||||
.field("id", &self.id())
|
||||
.field("name", &self.name())
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -929,7 +929,7 @@ fn parse_nt<'a>(p: &mut Parser<'a>, sp: Span, name: &str) -> Nonterminal {
|
|||
p.fatal(&format!("expected ident, found {}", &token_str)).emit();
|
||||
FatalError.raise()
|
||||
}
|
||||
"path" => token::NtPath(panictry!(p.parse_path_common(PathStyle::Type, false))),
|
||||
"path" => token::NtPath(panictry!(p.parse_path(PathStyle::Type))),
|
||||
"meta" => token::NtMeta(panictry!(p.parse_meta_item())),
|
||||
"vis" => token::NtVis(panictry!(p.parse_visibility(true))),
|
||||
"lifetime" => if p.check_lifetime() {
|
||||
|
|
|
|||
|
|
@ -1119,9 +1119,8 @@ impl<'a> Parser<'a> {
|
|||
if text.is_empty() {
|
||||
self.span_bug(sp, "found empty literal suffix in Some")
|
||||
}
|
||||
let msg = format!("{} with a suffix is invalid", kind);
|
||||
self.struct_span_err(sp, &msg)
|
||||
.span_label(sp, msg)
|
||||
self.struct_span_err(sp, &format!("suffixes on {} are invalid", kind))
|
||||
.span_label(sp, format!("invalid suffix `{}`", text))
|
||||
.emit();
|
||||
}
|
||||
}
|
||||
|
|
@ -1903,7 +1902,7 @@ impl<'a> Parser<'a> {
|
|||
self.expect(&token::ModSep)?;
|
||||
|
||||
let mut path = ast::Path { segments: Vec::new(), span: syntax_pos::DUMMY_SP };
|
||||
self.parse_path_segments(&mut path.segments, T::PATH_STYLE, true)?;
|
||||
self.parse_path_segments(&mut path.segments, T::PATH_STYLE)?;
|
||||
path.span = ty_span.to(self.prev_span);
|
||||
|
||||
let ty_str = self.sess.source_map().span_to_snippet(ty_span)
|
||||
|
|
@ -2150,7 +2149,7 @@ impl<'a> Parser<'a> {
|
|||
|
||||
if suffix_illegal {
|
||||
let sp = self.span;
|
||||
self.expect_no_suffix(sp, lit.literal_name(), suf)
|
||||
self.expect_no_suffix(sp, &format!("a {}", lit.literal_name()), suf)
|
||||
}
|
||||
|
||||
result.unwrap()
|
||||
|
|
@ -2294,7 +2293,7 @@ impl<'a> Parser<'a> {
|
|||
self.expect(&token::ModSep)?;
|
||||
|
||||
let qself = QSelf { ty, path_span, position: path.segments.len() };
|
||||
self.parse_path_segments(&mut path.segments, style, true)?;
|
||||
self.parse_path_segments(&mut path.segments, style)?;
|
||||
|
||||
Ok((qself, ast::Path { segments: path.segments, span: lo.to(self.prev_span) }))
|
||||
}
|
||||
|
|
@ -2310,11 +2309,6 @@ impl<'a> Parser<'a> {
|
|||
/// `Fn(Args)` (without disambiguator)
|
||||
/// `Fn::(Args)` (with disambiguator)
|
||||
pub fn parse_path(&mut self, style: PathStyle) -> PResult<'a, ast::Path> {
|
||||
self.parse_path_common(style, true)
|
||||
}
|
||||
|
||||
crate fn parse_path_common(&mut self, style: PathStyle, enable_warning: bool)
|
||||
-> PResult<'a, ast::Path> {
|
||||
maybe_whole!(self, NtPath, |path| {
|
||||
if style == PathStyle::Mod &&
|
||||
path.segments.iter().any(|segment| segment.args.is_some()) {
|
||||
|
|
@ -2329,7 +2323,7 @@ impl<'a> Parser<'a> {
|
|||
if self.eat(&token::ModSep) {
|
||||
segments.push(PathSegment::path_root(lo.shrink_to_lo().with_ctxt(mod_sep_ctxt)));
|
||||
}
|
||||
self.parse_path_segments(&mut segments, style, enable_warning)?;
|
||||
self.parse_path_segments(&mut segments, style)?;
|
||||
|
||||
Ok(ast::Path { segments, span: lo.to(self.prev_span) })
|
||||
}
|
||||
|
|
@ -2357,11 +2351,10 @@ impl<'a> Parser<'a> {
|
|||
|
||||
fn parse_path_segments(&mut self,
|
||||
segments: &mut Vec<PathSegment>,
|
||||
style: PathStyle,
|
||||
enable_warning: bool)
|
||||
style: PathStyle)
|
||||
-> PResult<'a, ()> {
|
||||
loop {
|
||||
let segment = self.parse_path_segment(style, enable_warning)?;
|
||||
let segment = self.parse_path_segment(style)?;
|
||||
if style == PathStyle::Expr {
|
||||
// In order to check for trailing angle brackets, we must have finished
|
||||
// recursing (`parse_path_segment` can indirectly call this function),
|
||||
|
|
@ -2389,8 +2382,7 @@ impl<'a> Parser<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
fn parse_path_segment(&mut self, style: PathStyle, enable_warning: bool)
|
||||
-> PResult<'a, PathSegment> {
|
||||
fn parse_path_segment(&mut self, style: PathStyle) -> PResult<'a, PathSegment> {
|
||||
let ident = self.parse_path_segment_ident()?;
|
||||
|
||||
let is_args_start = |token: &token::Token| match *token {
|
||||
|
|
@ -2407,13 +2399,6 @@ impl<'a> Parser<'a> {
|
|||
Ok(if style == PathStyle::Type && check_args_start(self) ||
|
||||
style != PathStyle::Mod && self.check(&token::ModSep)
|
||||
&& self.look_ahead(1, |t| is_args_start(t)) {
|
||||
// Generic arguments are found - `<`, `(`, `::<` or `::(`.
|
||||
if self.eat(&token::ModSep) && style == PathStyle::Type && enable_warning {
|
||||
self.diagnostic().struct_span_warn(self.prev_span, "unnecessary path disambiguator")
|
||||
.span_label(self.prev_span, "try removing `::`").emit();
|
||||
}
|
||||
let lo = self.span;
|
||||
|
||||
// We use `style == PathStyle::Expr` to check if this is in a recursion or not. If
|
||||
// it isn't, then we reset the unmatched angle bracket count as we're about to start
|
||||
// parsing a new path.
|
||||
|
|
@ -2422,6 +2407,9 @@ impl<'a> Parser<'a> {
|
|||
self.max_angle_bracket_count = 0;
|
||||
}
|
||||
|
||||
// Generic arguments are found - `<`, `(`, `::<` or `::(`.
|
||||
self.eat(&token::ModSep);
|
||||
let lo = self.span;
|
||||
let args = if self.eat_lt() {
|
||||
// `<'a, T, A = U>`
|
||||
let (args, bindings) =
|
||||
|
|
@ -2492,7 +2480,8 @@ impl<'a> Parser<'a> {
|
|||
}
|
||||
|
||||
fn parse_field_name(&mut self) -> PResult<'a, Ident> {
|
||||
if let token::Literal(token::Integer(name), None) = self.token {
|
||||
if let token::Literal(token::Integer(name), suffix) = self.token {
|
||||
self.expect_no_suffix(self.span, "a tuple index", suffix);
|
||||
self.bump();
|
||||
Ok(Ident::new(name, self.prev_span))
|
||||
} else {
|
||||
|
|
@ -3043,7 +3032,7 @@ impl<'a> Parser<'a> {
|
|||
|
||||
// Assuming we have just parsed `.`, continue parsing into an expression.
|
||||
fn parse_dot_suffix(&mut self, self_arg: P<Expr>, lo: Span) -> PResult<'a, P<Expr>> {
|
||||
let segment = self.parse_path_segment(PathStyle::Expr, true)?;
|
||||
let segment = self.parse_path_segment(PathStyle::Expr)?;
|
||||
self.check_trailing_angle_brackets(&segment, token::OpenDelim(token::Paren));
|
||||
|
||||
Ok(match self.token {
|
||||
|
|
@ -3196,51 +3185,53 @@ impl<'a> Parser<'a> {
|
|||
// expr.f
|
||||
if self.eat(&token::Dot) {
|
||||
match self.token {
|
||||
token::Ident(..) => {
|
||||
e = self.parse_dot_suffix(e, lo)?;
|
||||
}
|
||||
token::Literal(token::Integer(name), _) => {
|
||||
let span = self.span;
|
||||
self.bump();
|
||||
let field = ExprKind::Field(e, Ident::new(name, span));
|
||||
e = self.mk_expr(lo.to(span), field, ThinVec::new());
|
||||
}
|
||||
token::Literal(token::Float(n), _suf) => {
|
||||
self.bump();
|
||||
let fstr = n.as_str();
|
||||
let mut err = self.diagnostic()
|
||||
.struct_span_err(self.prev_span, &format!("unexpected token: `{}`", n));
|
||||
err.span_label(self.prev_span, "unexpected token");
|
||||
if fstr.chars().all(|x| "0123456789.".contains(x)) {
|
||||
let float = match fstr.parse::<f64>().ok() {
|
||||
Some(f) => f,
|
||||
None => continue,
|
||||
};
|
||||
let sugg = pprust::to_string(|s| {
|
||||
use crate::print::pprust::PrintState;
|
||||
s.popen()?;
|
||||
s.print_expr(&e)?;
|
||||
s.s.word( ".")?;
|
||||
s.print_usize(float.trunc() as usize)?;
|
||||
s.pclose()?;
|
||||
s.s.word(".")?;
|
||||
s.s.word(fstr.splitn(2, ".").last().unwrap().to_string())
|
||||
});
|
||||
err.span_suggestion(
|
||||
lo.to(self.prev_span),
|
||||
"try parenthesizing the first index",
|
||||
sugg,
|
||||
Applicability::MachineApplicable
|
||||
);
|
||||
token::Ident(..) => {
|
||||
e = self.parse_dot_suffix(e, lo)?;
|
||||
}
|
||||
return Err(err);
|
||||
token::Literal(token::Integer(name), suffix) => {
|
||||
let span = self.span;
|
||||
self.bump();
|
||||
let field = ExprKind::Field(e, Ident::new(name, span));
|
||||
e = self.mk_expr(lo.to(span), field, ThinVec::new());
|
||||
|
||||
}
|
||||
_ => {
|
||||
// FIXME Could factor this out into non_fatal_unexpected or something.
|
||||
let actual = self.this_token_to_string();
|
||||
self.span_err(self.span, &format!("unexpected token: `{}`", actual));
|
||||
}
|
||||
self.expect_no_suffix(span, "a tuple index", suffix);
|
||||
}
|
||||
token::Literal(token::Float(n), _suf) => {
|
||||
self.bump();
|
||||
let fstr = n.as_str();
|
||||
let mut err = self.diagnostic()
|
||||
.struct_span_err(self.prev_span, &format!("unexpected token: `{}`", n));
|
||||
err.span_label(self.prev_span, "unexpected token");
|
||||
if fstr.chars().all(|x| "0123456789.".contains(x)) {
|
||||
let float = match fstr.parse::<f64>().ok() {
|
||||
Some(f) => f,
|
||||
None => continue,
|
||||
};
|
||||
let sugg = pprust::to_string(|s| {
|
||||
use crate::print::pprust::PrintState;
|
||||
s.popen()?;
|
||||
s.print_expr(&e)?;
|
||||
s.s.word( ".")?;
|
||||
s.print_usize(float.trunc() as usize)?;
|
||||
s.pclose()?;
|
||||
s.s.word(".")?;
|
||||
s.s.word(fstr.splitn(2, ".").last().unwrap().to_string())
|
||||
});
|
||||
err.span_suggestion(
|
||||
lo.to(self.prev_span),
|
||||
"try parenthesizing the first index",
|
||||
sugg,
|
||||
Applicability::MachineApplicable
|
||||
);
|
||||
}
|
||||
return Err(err);
|
||||
|
||||
}
|
||||
_ => {
|
||||
// FIXME Could factor this out into non_fatal_unexpected or something.
|
||||
let actual = self.this_token_to_string();
|
||||
self.span_err(self.span, &format!("unexpected token: `{}`", actual));
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
|
@ -7838,7 +7829,7 @@ impl<'a> Parser<'a> {
|
|||
match self.token {
|
||||
token::Literal(token::Str_(s), suf) | token::Literal(token::StrRaw(s, _), suf) => {
|
||||
let sp = self.span;
|
||||
self.expect_no_suffix(sp, "ABI spec", suf);
|
||||
self.expect_no_suffix(sp, "an ABI spec", suf);
|
||||
self.bump();
|
||||
match abi::lookup(&s.as_str()) {
|
||||
Some(abi) => Ok(Some(abi)),
|
||||
|
|
@ -8659,7 +8650,7 @@ impl<'a> Parser<'a> {
|
|||
match self.parse_optional_str() {
|
||||
Some((s, style, suf)) => {
|
||||
let sp = self.prev_span;
|
||||
self.expect_no_suffix(sp, "string literal", suf);
|
||||
self.expect_no_suffix(sp, "a string literal", suf);
|
||||
Ok((s, style))
|
||||
}
|
||||
_ => {
|
||||
|
|
|
|||
|
|
@ -12,5 +12,8 @@ pub fn box_uninitialized() -> Box<MaybeUninit<usize>> {
|
|||
// CHECK-NOT: alloca
|
||||
// CHECK-NOT: memcpy
|
||||
// CHECK-NOT: memset
|
||||
Box::new(MaybeUninit::uninitialized())
|
||||
Box::new(MaybeUninit::uninit())
|
||||
}
|
||||
|
||||
// FIXME: add a test for a bigger box. Currently broken, see
|
||||
// https://github.com/rust-lang/rust/issues/58201.
|
||||
|
|
|
|||
|
|
@ -33,12 +33,12 @@ macro_rules! check {
|
|||
}
|
||||
|
||||
pub fn main() {
|
||||
check!(P1::<u8, u8>, 1, 3);
|
||||
check!(P1::<u64, u16>, 1, 11);
|
||||
check!(P1<u8, u8>, 1, 3);
|
||||
check!(P1<u64, u16>, 1, 11);
|
||||
|
||||
check!(P2::<u8, u8>, 1, 3);
|
||||
check!(P2::<u64, u16>, 2, 12);
|
||||
check!(P2<u8, u8>, 1, 3);
|
||||
check!(P2<u64, u16>, 2, 12);
|
||||
|
||||
check!(P4C::<u8, u8>, 1, 3);
|
||||
check!(P4C::<u16, u64>, 4, 12);
|
||||
check!(P4C<u8, u8>, 1, 3);
|
||||
check!(P4C<u16, u64>, 4, 12);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,36 +0,0 @@
|
|||
warning: unnecessary path disambiguator
|
||||
--> $DIR/packed-struct-generic-size.rs:36:14
|
||||
|
|
||||
LL | check!(P1::<u8, u8>, 1, 3);
|
||||
| ^^ try removing `::`
|
||||
|
||||
warning: unnecessary path disambiguator
|
||||
--> $DIR/packed-struct-generic-size.rs:37:14
|
||||
|
|
||||
LL | check!(P1::<u64, u16>, 1, 11);
|
||||
| ^^ try removing `::`
|
||||
|
||||
warning: unnecessary path disambiguator
|
||||
--> $DIR/packed-struct-generic-size.rs:39:14
|
||||
|
|
||||
LL | check!(P2::<u8, u8>, 1, 3);
|
||||
| ^^ try removing `::`
|
||||
|
||||
warning: unnecessary path disambiguator
|
||||
--> $DIR/packed-struct-generic-size.rs:40:14
|
||||
|
|
||||
LL | check!(P2::<u64, u16>, 2, 12);
|
||||
| ^^ try removing `::`
|
||||
|
||||
warning: unnecessary path disambiguator
|
||||
--> $DIR/packed-struct-generic-size.rs:42:15
|
||||
|
|
||||
LL | check!(P4C::<u8, u8>, 1, 3);
|
||||
| ^^ try removing `::`
|
||||
|
||||
warning: unnecessary path disambiguator
|
||||
--> $DIR/packed-struct-generic-size.rs:43:15
|
||||
|
|
||||
LL | check!(P4C::<u16, u64>, 4, 12);
|
||||
| ^^ try removing `::`
|
||||
|
||||
|
|
@ -36,7 +36,7 @@ fn main() {
|
|||
|
||||
assert_eq!(
|
||||
panic::catch_unwind(|| {
|
||||
mem::MaybeUninit::<!>::uninitialized().into_initialized()
|
||||
mem::MaybeUninit::<!>::uninit().assume_init()
|
||||
}).err().and_then(|a| a.downcast_ref::<String>().map(|s| {
|
||||
s == "Attempted to instantiate uninhabited type !"
|
||||
})),
|
||||
|
|
@ -63,7 +63,7 @@ fn main() {
|
|||
|
||||
assert_eq!(
|
||||
panic::catch_unwind(|| {
|
||||
mem::MaybeUninit::<Foo>::uninitialized().into_initialized()
|
||||
mem::MaybeUninit::<Foo>::uninit().assume_init()
|
||||
}).err().and_then(|a| a.downcast_ref::<String>().map(|s| {
|
||||
s == "Attempted to instantiate uninhabited type Foo"
|
||||
})),
|
||||
|
|
@ -90,7 +90,7 @@ fn main() {
|
|||
|
||||
assert_eq!(
|
||||
panic::catch_unwind(|| {
|
||||
mem::MaybeUninit::<Bar>::uninitialized().into_initialized()
|
||||
mem::MaybeUninit::<Bar>::uninit().assume_init()
|
||||
}).err().and_then(|a| a.downcast_ref::<String>().map(|s| {
|
||||
s == "Attempted to instantiate uninhabited type Bar"
|
||||
})),
|
||||
|
|
|
|||
|
|
@ -0,0 +1,12 @@
|
|||
#![feature(existential_type)]
|
||||
|
||||
existential type Foo: Fn() -> Foo;
|
||||
//~^ ERROR: cycle detected when processing `Foo`
|
||||
|
||||
fn crash(x: Foo) -> Foo {
|
||||
x
|
||||
}
|
||||
|
||||
fn main() {
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
error[E0391]: cycle detected when processing `Foo`
|
||||
--> $DIR/existential-types-with-cycle-error.rs:3:1
|
||||
|
|
||||
LL | existential type Foo: Fn() -> Foo;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: ...which requires processing `crash`...
|
||||
--> $DIR/existential-types-with-cycle-error.rs:6:25
|
||||
|
|
||||
LL | fn crash(x: Foo) -> Foo {
|
||||
| _________________________^
|
||||
LL | | x
|
||||
LL | | }
|
||||
| |_^
|
||||
= note: ...which again requires processing `Foo`, completing the cycle
|
||||
note: cycle used when collecting item types in top-level module
|
||||
--> $DIR/existential-types-with-cycle-error.rs:1:1
|
||||
|
|
||||
LL | / #![feature(existential_type)]
|
||||
LL | |
|
||||
LL | | existential type Foo: Fn() -> Foo;
|
||||
LL | |
|
||||
... |
|
||||
LL | |
|
||||
LL | | }
|
||||
| |_^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0391`.
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
#![feature(existential_type)]
|
||||
|
||||
pub trait Bar<T> {
|
||||
type Item;
|
||||
}
|
||||
|
||||
existential type Foo: Bar<Foo, Item = Foo>;
|
||||
//~^ ERROR: cycle detected when processing `Foo`
|
||||
|
||||
fn crash(x: Foo) -> Foo {
|
||||
x
|
||||
}
|
||||
|
||||
fn main() {
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
error[E0391]: cycle detected when processing `Foo`
|
||||
--> $DIR/existential-types-with-cycle-error2.rs:7:1
|
||||
|
|
||||
LL | existential type Foo: Bar<Foo, Item = Foo>;
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: ...which requires processing `crash`...
|
||||
--> $DIR/existential-types-with-cycle-error2.rs:10:25
|
||||
|
|
||||
LL | fn crash(x: Foo) -> Foo {
|
||||
| _________________________^
|
||||
LL | | x
|
||||
LL | | }
|
||||
| |_^
|
||||
= note: ...which again requires processing `Foo`, completing the cycle
|
||||
note: cycle used when collecting item types in top-level module
|
||||
--> $DIR/existential-types-with-cycle-error2.rs:1:1
|
||||
|
|
||||
LL | / #![feature(existential_type)]
|
||||
LL | |
|
||||
LL | | pub trait Bar<T> {
|
||||
LL | | type Item;
|
||||
... |
|
||||
LL | |
|
||||
LL | | }
|
||||
| |_^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0391`.
|
||||
|
|
@ -17,10 +17,10 @@ struct Foo<T> {
|
|||
struct S<T>(T);
|
||||
|
||||
fn f() {
|
||||
let f = Some(Foo { _a: 42 }).map(|a| a as Foo::<i32>); //~ WARN unnecessary path disambiguator
|
||||
let g: Foo::<i32> = Foo { _a: 42 }; //~ WARN unnecessary path disambiguator
|
||||
let f = Some(Foo { _a: 42 }).map(|a| a as Foo::<i32>);
|
||||
let g: Foo::<i32> = Foo { _a: 42 };
|
||||
|
||||
m!(S::<u8>); // OK, no warning
|
||||
m!(S::<u8>);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,12 +0,0 @@
|
|||
warning: unnecessary path disambiguator
|
||||
--> $DIR/issue-36116.rs:20:50
|
||||
|
|
||||
LL | let f = Some(Foo { _a: 42 }).map(|a| a as Foo::<i32>);
|
||||
| ^^ try removing `::`
|
||||
|
||||
warning: unnecessary path disambiguator
|
||||
--> $DIR/issue-36116.rs:21:15
|
||||
|
|
||||
LL | let g: Foo::<i32> = Foo { _a: 42 };
|
||||
| ^^ try removing `::`
|
||||
|
||||
|
|
@ -10,18 +10,6 @@ note: lint level defined here
|
|||
LL | #[deny(while_true)]
|
||||
| ^^^^^^^^^^
|
||||
|
||||
error: denote infinite loops with `loop { ... }`
|
||||
--> $DIR/lint-impl-fn.rs:18:25
|
||||
|
|
||||
LL | fn foo(&self) { while true {} }
|
||||
| ^^^^^^^^^^ help: use `loop`
|
||||
|
|
||||
note: lint level defined here
|
||||
--> $DIR/lint-impl-fn.rs:13:8
|
||||
|
|
||||
LL | #[deny(while_true)]
|
||||
| ^^^^^^^^^^
|
||||
|
||||
error: denote infinite loops with `loop { ... }`
|
||||
--> $DIR/lint-impl-fn.rs:27:5
|
||||
|
|
||||
|
|
@ -34,5 +22,17 @@ note: lint level defined here
|
|||
LL | #[deny(while_true)]
|
||||
| ^^^^^^^^^^
|
||||
|
||||
error: denote infinite loops with `loop { ... }`
|
||||
--> $DIR/lint-impl-fn.rs:18:25
|
||||
|
|
||||
LL | fn foo(&self) { while true {} }
|
||||
| ^^^^^^^^^^ help: use `loop`
|
||||
|
|
||||
note: lint level defined here
|
||||
--> $DIR/lint-impl-fn.rs:13:8
|
||||
|
|
||||
LL | #[deny(while_true)]
|
||||
| ^^^^^^^^^^
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
|
|
|
|||
|
|
@ -65,6 +65,24 @@ LL | pub fn defiant<T>(_t: T) {}
|
|||
|
|
||||
= note: #[warn(no_mangle_generic_items)] on by default
|
||||
|
||||
warning: denote infinite loops with `loop { ... }`
|
||||
--> $DIR/suggestions.rs:46:5
|
||||
|
|
||||
LL | while true {
|
||||
| ^^^^^^^^^^ help: use `loop`
|
||||
|
|
||||
= note: #[warn(while_true)] on by default
|
||||
|
||||
warning: the `warp_factor:` in this pattern is redundant
|
||||
--> $DIR/suggestions.rs:61:23
|
||||
|
|
||||
LL | Equinox { warp_factor: warp_factor } => {}
|
||||
| ------------^^^^^^^^^^^^
|
||||
| |
|
||||
| help: remove this
|
||||
|
|
||||
= note: #[warn(non_shorthand_field_patterns)] on by default
|
||||
|
||||
error: const items should never be #[no_mangle]
|
||||
--> $DIR/suggestions.rs:22:18
|
||||
|
|
||||
|
|
@ -97,23 +115,5 @@ LL | #[no_mangle] pub(crate) fn crossfield<T>() {}
|
|||
| |
|
||||
| help: remove this attribute
|
||||
|
||||
warning: denote infinite loops with `loop { ... }`
|
||||
--> $DIR/suggestions.rs:46:5
|
||||
|
|
||||
LL | while true {
|
||||
| ^^^^^^^^^^ help: use `loop`
|
||||
|
|
||||
= note: #[warn(while_true)] on by default
|
||||
|
||||
warning: the `warp_factor:` in this pattern is redundant
|
||||
--> $DIR/suggestions.rs:61:23
|
||||
|
|
||||
LL | Equinox { warp_factor: warp_factor } => {}
|
||||
| ------------^^^^^^^^^^^^
|
||||
| |
|
||||
| help: remove this
|
||||
|
|
||||
= note: #[warn(non_shorthand_field_patterns)] on by default
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
|
|
|
|||
|
|
@ -2,20 +2,20 @@
|
|||
|
||||
|
||||
extern
|
||||
"C"suffix //~ ERROR ABI spec with a suffix is invalid
|
||||
"C"suffix //~ ERROR suffixes on an ABI spec are invalid
|
||||
fn foo() {}
|
||||
|
||||
extern
|
||||
"C"suffix //~ ERROR ABI spec with a suffix is invalid
|
||||
"C"suffix //~ ERROR suffixes on an ABI spec are invalid
|
||||
{}
|
||||
|
||||
fn main() {
|
||||
""suffix; //~ ERROR string literal with a suffix is invalid
|
||||
b""suffix; //~ ERROR byte string literal with a suffix is invalid
|
||||
r#""#suffix; //~ ERROR string literal with a suffix is invalid
|
||||
br#""#suffix; //~ ERROR byte string literal with a suffix is invalid
|
||||
'a'suffix; //~ ERROR char literal with a suffix is invalid
|
||||
b'a'suffix; //~ ERROR byte literal with a suffix is invalid
|
||||
""suffix; //~ ERROR suffixes on a string literal are invalid
|
||||
b""suffix; //~ ERROR suffixes on a byte string literal are invalid
|
||||
r#""#suffix; //~ ERROR suffixes on a string literal are invalid
|
||||
br#""#suffix; //~ ERROR suffixes on a byte string literal are invalid
|
||||
'a'suffix; //~ ERROR suffixes on a char literal are invalid
|
||||
b'a'suffix; //~ ERROR suffixes on a byte literal are invalid
|
||||
|
||||
1234u1024; //~ ERROR invalid width `1024` for integer literal
|
||||
1234i1024; //~ ERROR invalid width `1024` for integer literal
|
||||
|
|
|
|||
|
|
@ -1,50 +1,50 @@
|
|||
error: ABI spec with a suffix is invalid
|
||||
error: suffixes on an ABI spec are invalid
|
||||
--> $DIR/bad-lit-suffixes.rs:5:5
|
||||
|
|
||||
LL | "C"suffix
|
||||
| ^^^^^^^^^ ABI spec with a suffix is invalid
|
||||
| ^^^^^^^^^ invalid suffix `suffix`
|
||||
|
||||
error: ABI spec with a suffix is invalid
|
||||
error: suffixes on an ABI spec are invalid
|
||||
--> $DIR/bad-lit-suffixes.rs:9:5
|
||||
|
|
||||
LL | "C"suffix
|
||||
| ^^^^^^^^^ ABI spec with a suffix is invalid
|
||||
| ^^^^^^^^^ invalid suffix `suffix`
|
||||
|
||||
error: string literal with a suffix is invalid
|
||||
error: suffixes on a string literal are invalid
|
||||
--> $DIR/bad-lit-suffixes.rs:13:5
|
||||
|
|
||||
LL | ""suffix;
|
||||
| ^^^^^^^^ string literal with a suffix is invalid
|
||||
| ^^^^^^^^ invalid suffix `suffix`
|
||||
|
||||
error: byte string literal with a suffix is invalid
|
||||
error: suffixes on a byte string literal are invalid
|
||||
--> $DIR/bad-lit-suffixes.rs:14:5
|
||||
|
|
||||
LL | b""suffix;
|
||||
| ^^^^^^^^^ byte string literal with a suffix is invalid
|
||||
| ^^^^^^^^^ invalid suffix `suffix`
|
||||
|
||||
error: string literal with a suffix is invalid
|
||||
error: suffixes on a string literal are invalid
|
||||
--> $DIR/bad-lit-suffixes.rs:15:5
|
||||
|
|
||||
LL | r#""#suffix;
|
||||
| ^^^^^^^^^^^ string literal with a suffix is invalid
|
||||
| ^^^^^^^^^^^ invalid suffix `suffix`
|
||||
|
||||
error: byte string literal with a suffix is invalid
|
||||
error: suffixes on a byte string literal are invalid
|
||||
--> $DIR/bad-lit-suffixes.rs:16:5
|
||||
|
|
||||
LL | br#""#suffix;
|
||||
| ^^^^^^^^^^^^ byte string literal with a suffix is invalid
|
||||
| ^^^^^^^^^^^^ invalid suffix `suffix`
|
||||
|
||||
error: char literal with a suffix is invalid
|
||||
error: suffixes on a char literal are invalid
|
||||
--> $DIR/bad-lit-suffixes.rs:17:5
|
||||
|
|
||||
LL | 'a'suffix;
|
||||
| ^^^^^^^^^ char literal with a suffix is invalid
|
||||
| ^^^^^^^^^ invalid suffix `suffix`
|
||||
|
||||
error: byte literal with a suffix is invalid
|
||||
error: suffixes on a byte literal are invalid
|
||||
--> $DIR/bad-lit-suffixes.rs:18:5
|
||||
|
|
||||
LL | b'a'suffix;
|
||||
| ^^^^^^^^^^ byte literal with a suffix is invalid
|
||||
| ^^^^^^^^^^ invalid suffix `suffix`
|
||||
|
||||
error: invalid width `1024` for integer literal
|
||||
--> $DIR/bad-lit-suffixes.rs:20:5
|
||||
|
|
|
|||
18
src/test/ui/parser/issue-59418.rs
Normal file
18
src/test/ui/parser/issue-59418.rs
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
struct X(i32,i32,i32);
|
||||
|
||||
fn main() {
|
||||
let a = X(1, 2, 3);
|
||||
let b = a.1suffix;
|
||||
//~^ ERROR suffixes on a tuple index are invalid
|
||||
println!("{}", b);
|
||||
let c = (1, 2, 3);
|
||||
let d = c.1suffix;
|
||||
//~^ ERROR suffixes on a tuple index are invalid
|
||||
println!("{}", d);
|
||||
let s = X { 0suffix: 0, 1: 1, 2: 2 };
|
||||
//~^ ERROR suffixes on a tuple index are invalid
|
||||
match s {
|
||||
X { 0suffix: _, .. } => {}
|
||||
//~^ ERROR suffixes on a tuple index are invalid
|
||||
}
|
||||
}
|
||||
26
src/test/ui/parser/issue-59418.stderr
Normal file
26
src/test/ui/parser/issue-59418.stderr
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
error: suffixes on a tuple index are invalid
|
||||
--> $DIR/issue-59418.rs:5:15
|
||||
|
|
||||
LL | let b = a.1suffix;
|
||||
| ^^^^^^^ invalid suffix `suffix`
|
||||
|
||||
error: suffixes on a tuple index are invalid
|
||||
--> $DIR/issue-59418.rs:9:15
|
||||
|
|
||||
LL | let d = c.1suffix;
|
||||
| ^^^^^^^ invalid suffix `suffix`
|
||||
|
||||
error: suffixes on a tuple index are invalid
|
||||
--> $DIR/issue-59418.rs:12:17
|
||||
|
|
||||
LL | let s = X { 0suffix: 0, 1: 1, 2: 2 };
|
||||
| ^^^^^^^ invalid suffix `suffix`
|
||||
|
||||
error: suffixes on a tuple index are invalid
|
||||
--> $DIR/issue-59418.rs:15:13
|
||||
|
|
||||
LL | X { 0suffix: _, .. } => {}
|
||||
| ^^^^^^^ invalid suffix `suffix`
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
6
src/test/ui/suggestions/into-str.rs
Normal file
6
src/test/ui/suggestions/into-str.rs
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
fn foo<'a, T>(_t: T) where T: Into<&'a str> {}
|
||||
|
||||
fn main() {
|
||||
foo(String::new());
|
||||
//~^ ERROR the trait bound `&str: std::convert::From<std::string::String>` is not satisfied
|
||||
}
|
||||
17
src/test/ui/suggestions/into-str.stderr
Normal file
17
src/test/ui/suggestions/into-str.stderr
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
error[E0277]: the trait bound `&str: std::convert::From<std::string::String>` is not satisfied
|
||||
--> $DIR/into-str.rs:4:5
|
||||
|
|
||||
LL | foo(String::new());
|
||||
| ^^^ the trait `std::convert::From<std::string::String>` is not implemented for `&str`
|
||||
|
|
||||
= note: to coerce a `std::string::String` into a `&str`, use `&*` as a prefix
|
||||
= note: required because of the requirements on the impl of `std::convert::Into<&str>` for `std::string::String`
|
||||
note: required by `foo`
|
||||
--> $DIR/into-str.rs:1:1
|
||||
|
|
||||
LL | fn foo<'a, T>(_t: T) where T: Into<&'a str> {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
||||
34
src/test/ui/type/type-check/assignment-expected-bool.rs
Normal file
34
src/test/ui/type/type-check/assignment-expected-bool.rs
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
// The purpose of this text is to ensure that we get good
|
||||
// diagnostics when a `bool` is expected but that due to
|
||||
// an assignment expression `x = y` the type is `()`.
|
||||
|
||||
fn main() {
|
||||
let _: bool = 0 = 0; //~ ERROR mismatched types [E0308]
|
||||
|
||||
let _: bool = match 0 {
|
||||
0 => 0 = 0, //~ ERROR mismatched types [E0308]
|
||||
_ => 0 = 0, //~ ERROR mismatched types [E0308]
|
||||
};
|
||||
|
||||
let _: bool = match true {
|
||||
true => 0 = 0, //~ ERROR mismatched types [E0308]
|
||||
_ => (),
|
||||
};
|
||||
|
||||
if 0 = 0 {} //~ ERROR mismatched types [E0308]
|
||||
|
||||
let _: bool = if { 0 = 0 } { //~ ERROR mismatched types [E0308]
|
||||
0 = 0 //~ ERROR mismatched types [E0308]
|
||||
} else {
|
||||
0 = 0 //~ ERROR mismatched types [E0308]
|
||||
};
|
||||
|
||||
let _ = (0 = 0) //~ ERROR mismatched types [E0308]
|
||||
&& { 0 = 0 } //~ ERROR mismatched types [E0308]
|
||||
|| (0 = 0); //~ ERROR mismatched types [E0308]
|
||||
|
||||
// A test to check that not expecting `bool` behaves well:
|
||||
let _: usize = 0 = 0;
|
||||
//~^ ERROR mismatched types [E0308]
|
||||
//~| ERROR invalid left-hand side expression [E0070]
|
||||
}
|
||||
151
src/test/ui/type/type-check/assignment-expected-bool.stderr
Normal file
151
src/test/ui/type/type-check/assignment-expected-bool.stderr
Normal file
|
|
@ -0,0 +1,151 @@
|
|||
error[E0308]: mismatched types
|
||||
--> $DIR/assignment-expected-bool.rs:6:19
|
||||
|
|
||||
LL | let _: bool = 0 = 0;
|
||||
| ^^^^^
|
||||
| |
|
||||
| expected bool, found ()
|
||||
| help: try comparing for equality: `0 == 0`
|
||||
|
|
||||
= note: expected type `bool`
|
||||
found type `()`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/assignment-expected-bool.rs:9:14
|
||||
|
|
||||
LL | 0 => 0 = 0,
|
||||
| ^^^^^
|
||||
| |
|
||||
| expected bool, found ()
|
||||
| help: try comparing for equality: `0 == 0`
|
||||
|
|
||||
= note: expected type `bool`
|
||||
found type `()`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/assignment-expected-bool.rs:10:14
|
||||
|
|
||||
LL | _ => 0 = 0,
|
||||
| ^^^^^
|
||||
| |
|
||||
| expected bool, found ()
|
||||
| help: try comparing for equality: `0 == 0`
|
||||
|
|
||||
= note: expected type `bool`
|
||||
found type `()`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/assignment-expected-bool.rs:14:17
|
||||
|
|
||||
LL | true => 0 = 0,
|
||||
| ^^^^^
|
||||
| |
|
||||
| expected bool, found ()
|
||||
| help: try comparing for equality: `0 == 0`
|
||||
|
|
||||
= note: expected type `bool`
|
||||
found type `()`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/assignment-expected-bool.rs:18:8
|
||||
|
|
||||
LL | if 0 = 0 {}
|
||||
| ^^^^^
|
||||
| |
|
||||
| expected bool, found ()
|
||||
| help: try comparing for equality: `0 == 0`
|
||||
|
|
||||
= note: expected type `bool`
|
||||
found type `()`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/assignment-expected-bool.rs:20:24
|
||||
|
|
||||
LL | let _: bool = if { 0 = 0 } {
|
||||
| ^^^^^
|
||||
| |
|
||||
| expected bool, found ()
|
||||
| help: try comparing for equality: `0 == 0`
|
||||
|
|
||||
= note: expected type `bool`
|
||||
found type `()`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/assignment-expected-bool.rs:21:9
|
||||
|
|
||||
LL | 0 = 0
|
||||
| ^^^^^
|
||||
| |
|
||||
| expected bool, found ()
|
||||
| help: try comparing for equality: `0 == 0`
|
||||
|
|
||||
= note: expected type `bool`
|
||||
found type `()`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/assignment-expected-bool.rs:23:9
|
||||
|
|
||||
LL | 0 = 0
|
||||
| ^^^^^
|
||||
| |
|
||||
| expected bool, found ()
|
||||
| help: try comparing for equality: `0 == 0`
|
||||
|
|
||||
= note: expected type `bool`
|
||||
found type `()`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/assignment-expected-bool.rs:26:13
|
||||
|
|
||||
LL | let _ = (0 = 0)
|
||||
| ^^^^^^^
|
||||
| |
|
||||
| expected bool, found ()
|
||||
| help: try comparing for equality: `0 == 0`
|
||||
|
|
||||
= note: expected type `bool`
|
||||
found type `()`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/assignment-expected-bool.rs:27:14
|
||||
|
|
||||
LL | && { 0 = 0 }
|
||||
| ^^^^^
|
||||
| |
|
||||
| expected bool, found ()
|
||||
| help: try comparing for equality: `0 == 0`
|
||||
|
|
||||
= note: expected type `bool`
|
||||
found type `()`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/assignment-expected-bool.rs:28:12
|
||||
|
|
||||
LL | || (0 = 0);
|
||||
| ^^^^^^^
|
||||
| |
|
||||
| expected bool, found ()
|
||||
| help: try comparing for equality: `0 == 0`
|
||||
|
|
||||
= note: expected type `bool`
|
||||
found type `()`
|
||||
|
||||
error[E0070]: invalid left-hand side expression
|
||||
--> $DIR/assignment-expected-bool.rs:31:20
|
||||
|
|
||||
LL | let _: usize = 0 = 0;
|
||||
| ^^^^^ left-hand of expression not valid
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/assignment-expected-bool.rs:31:20
|
||||
|
|
||||
LL | let _: usize = 0 = 0;
|
||||
| ^^^^^ expected usize, found ()
|
||||
|
|
||||
= note: expected type `usize`
|
||||
found type `()`
|
||||
|
||||
error: aborting due to 13 previous errors
|
||||
|
||||
Some errors occurred: E0070, E0308.
|
||||
For more information about an error, try `rustc --explain E0070`.
|
||||
|
|
@ -31,8 +31,13 @@ fn main() {
|
|||
//~^ ERROR mismatched types
|
||||
println!("{}", x);
|
||||
}
|
||||
if (if true { x = 4 } else { x = 5 }) {
|
||||
//~^ ERROR mismatched types
|
||||
if (
|
||||
if true {
|
||||
x = 4 //~ ERROR mismatched types
|
||||
} else {
|
||||
x = 5 //~ ERROR mismatched types
|
||||
}
|
||||
) {
|
||||
println!("{}", x);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -47,14 +47,29 @@ LL | if 3 = x {
|
|||
found type `()`
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/assignment-in-if.rs:34:8
|
||||
--> $DIR/assignment-in-if.rs:36:13
|
||||
|
|
||||
LL | if (if true { x = 4 } else { x = 5 }) {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected bool, found ()
|
||||
LL | x = 4
|
||||
| ^^^^^
|
||||
| |
|
||||
| expected bool, found ()
|
||||
| help: try comparing for equality: `x == 4`
|
||||
|
|
||||
= note: expected type `bool`
|
||||
found type `()`
|
||||
|
||||
error: aborting due to 5 previous errors
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/assignment-in-if.rs:38:13
|
||||
|
|
||||
LL | x = 5
|
||||
| ^^^^^
|
||||
| |
|
||||
| expected bool, found ()
|
||||
| help: try comparing for equality: `x == 5`
|
||||
|
|
||||
= note: expected type `bool`
|
||||
found type `()`
|
||||
|
||||
error: aborting due to 6 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue