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:
bors 2019-03-28 02:00:57 +00:00
commit d20e000272
84 changed files with 1474 additions and 698 deletions

View file

@ -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

View file

@ -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 { /* ... */ }
```

View file

@ -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);
}
}

View 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,
];

View file

@ -5,6 +5,7 @@ extern crate core;
extern crate test;
mod any;
mod ascii;
mod char;
mod hash;
mod iter;

View file

@ -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")]

View file

@ -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,

View file

@ -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.

View file

@ -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()
});
}

View file

@ -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

View file

@ -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_
];

View file

@ -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 {

View file

@ -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);

View file

@ -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>
{

View file

@ -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]

View file

@ -469,6 +469,7 @@ rustc_dep_node_append!([define_dep_nodes!][ <'tcx>
[] UnsafetyCheckResult(DefId),
[] UnsafeDeriveOnReprPacked(DefId),
[] LintMod(DefId),
[] CheckModAttrs(DefId),
[] CheckModLoops(DefId),
[] CheckModUnstableApiUsage(DefId),

View file

@ -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(&[])

View file

@ -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],
}

View file

@ -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.

View file

@ -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-

View file

@ -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) -> (),

View file

@ -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!()); }

View file

@ -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" }

View file

@ -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};

View file

@ -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 {}",

View file

@ -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(())
}

View file

@ -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" }

View file

@ -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>;

View file

@ -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;

View file

@ -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);
}

View file

@ -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;

View file

@ -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};

View file

@ -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;

View file

@ -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));
}

View file

@ -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",

View file

@ -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| {

View file

@ -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();

View file

@ -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, .. }) |

View file

@ -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,

View file

@ -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,

View file

@ -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>;
}

View file

@ -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};

View file

@ -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(

View file

@ -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,

View file

@ -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.

View file

@ -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(())

View file

@ -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 {

View file

@ -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.
///

View file

@ -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.

View file

@ -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.

View file

@ -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>,

View file

@ -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

View file

@ -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);
}

View file

@ -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,

View file

@ -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,

View file

@ -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`.

View file

@ -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()
}
}

View file

@ -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
)
};

View file

@ -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) {

View file

@ -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()
}
}

View file

@ -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() {

View file

@ -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))
}
_ => {

View file

@ -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.

View file

@ -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);
}

View file

@ -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 `::`

View file

@ -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"
})),

View file

@ -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() {
}

View file

@ -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`.

View file

@ -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() {
}

View file

@ -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`.

View file

@ -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>);
}

View file

@ -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 `::`

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View 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
}
}

View 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

View 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
}

View 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`.

View 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]
}

View 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`.

View file

@ -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);
}
}

View file

@ -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`.