From b70e7fd0db5d23a2e045e89b8bc7e5564acce9b7 Mon Sep 17 00:00:00 2001 From: CAD97 Date: Mon, 3 Feb 2020 14:54:02 -0500 Subject: [PATCH 001/203] Add inherent impls for unchecked math intrinsics --- src/libcore/num/mod.rs | 102 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 102 insertions(+) diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index 7ba4004d8609..db533d154c99 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -697,6 +697,23 @@ $EndFeature, " } } + doc_comment! { + concat!("Unchecked integer addition. Computes `self + rhs, assuming overflow +cannot occur. This results in undefined behavior when `self + rhs > ", stringify!($SelfT), +"::max_value()` or `self + rhs < ", stringify!($SelfT), "::min_value()`."), + #[unstable( + feature = "unchecked_math", + reason = "niche optimization path", + issue = "none", + )] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub unsafe fn unchecked_add(self, rhs: Self) -> Self { + intrinsics::unchecked_add(self, rhs) + } + } + doc_comment! { concat!("Checked integer subtraction. Computes `self - rhs`, returning `None` if overflow occurred. @@ -722,6 +739,23 @@ $EndFeature, " } } + doc_comment! { + concat!("Unchecked integer subtraction. Computes `self - rhs, assuming overflow +cannot occur. This results in undefined behavior when `self - rhs > ", stringify!($SelfT), +"::max_value()` or `self - rhs < ", stringify!($SelfT), "::min_value()`."), + #[unstable( + feature = "unchecked_math", + reason = "niche optimization path", + issue = "none", + )] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub unsafe fn unchecked_sub(self, rhs: Self) -> Self { + intrinsics::unchecked_sub(self, rhs) + } + } + doc_comment! { concat!("Checked integer multiplication. Computes `self * rhs`, returning `None` if overflow occurred. @@ -747,6 +781,23 @@ $EndFeature, " } } + doc_comment! { + concat!("Unchecked integer multiplication. Computes `self * rhs, assuming overflow +cannot occur. This results in undefined behavior when `self * rhs > ", stringify!($SelfT), +"::max_value()` or `self * rhs < ", stringify!($SelfT), "::min_value()`."), + #[unstable( + feature = "unchecked_math", + reason = "niche optimization path", + issue = "none", + )] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub unsafe fn unchecked_mul(self, rhs: Self) -> Self { + intrinsics::unchecked_mul(self, rhs) + } + } + doc_comment! { concat!("Checked integer division. Computes `self / rhs`, returning `None` if `rhs == 0` or the division results in overflow. @@ -2884,6 +2935,23 @@ assert_eq!((", stringify!($SelfT), "::MAX - 2).checked_add(3), None);", $EndFeat } } + doc_comment! { + concat!("Unchecked integer addition. Computes `self + rhs, assuming overflow +cannot occur. This results in undefined behavior when `self + rhs > ", stringify!($SelfT), +"::max_value()` or `self + rhs < ", stringify!($SelfT), "::min_value()`."), + #[unstable( + feature = "unchecked_math", + reason = "niche optimization path", + issue = "none", + )] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub unsafe fn unchecked_add(self, rhs: Self) -> Self { + intrinsics::unchecked_add(self, rhs) + } + } + doc_comment! { concat!("Checked integer subtraction. Computes `self - rhs`, returning `None` if overflow occurred. @@ -2907,6 +2975,23 @@ assert_eq!(0", stringify!($SelfT), ".checked_sub(1), None);", $EndFeature, " } } + doc_comment! { + concat!("Unchecked integer subtraction. Computes `self - rhs, assuming overflow +cannot occur. This results in undefined behavior when `self - rhs > ", stringify!($SelfT), +"::max_value()` or `self - rhs < ", stringify!($SelfT), "::min_value()`."), + #[unstable( + feature = "unchecked_math", + reason = "niche optimization path", + issue = "none", + )] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub unsafe fn unchecked_sub(self, rhs: Self) -> Self { + intrinsics::unchecked_sub(self, rhs) + } + } + doc_comment! { concat!("Checked integer multiplication. Computes `self * rhs`, returning `None` if overflow occurred. @@ -2930,6 +3015,23 @@ assert_eq!(", stringify!($SelfT), "::MAX.checked_mul(2), None);", $EndFeature, " } } + doc_comment! { + concat!("Unchecked integer multiplication. Computes `self * rhs, assuming overflow +cannot occur. This results in undefined behavior when `self * rhs > ", stringify!($SelfT), +"::max_value()` or `self * rhs < ", stringify!($SelfT), "::min_value()`."), + #[unstable( + feature = "unchecked_math", + reason = "niche optimization path", + issue = "none", + )] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub unsafe fn unchecked_mul(self, rhs: Self) -> Self { + intrinsics::unchecked_mul(self, rhs) + } + } + doc_comment! { concat!("Checked integer division. Computes `self / rhs`, returning `None` if `rhs == 0`. From 2fcfd233f755c548ddc4d5fda517a7dbb9f04ba3 Mon Sep 17 00:00:00 2001 From: CAD97 Date: Tue, 18 Feb 2020 13:18:33 -0500 Subject: [PATCH 002/203] Redesign the Step trait --- src/libcore/iter/range.rs | 638 +++++++++++++++------ src/libcore/tests/iter.rs | 133 ++++- src/libcore/tests/lib.rs | 1 + src/librustc_index/vec.rs | 32 +- src/test/ui/impl-trait/example-calendar.rs | 26 +- 5 files changed, 566 insertions(+), 264 deletions(-) diff --git a/src/libcore/iter/range.rs b/src/libcore/iter/range.rs index 28fbd00f36b3..ae88fb471a07 100644 --- a/src/libcore/iter/range.rs +++ b/src/libcore/iter/range.rs @@ -5,47 +5,179 @@ use crate::usize; use super::{FusedIterator, TrustedLen}; -/// Objects that can be stepped over in both directions. +/// Objects that have a notion of *successor* and *predecessor* operations. /// -/// The `steps_between` function provides a way to efficiently compare -/// two `Step` objects. -#[unstable( - feature = "step_trait", - reason = "likely to be replaced by finer-grained traits", - issue = "42168" -)] -pub trait Step: Clone + PartialOrd + Sized { - /// Returns the number of steps between two step objects. The count is - /// inclusive of `start` and exclusive of `end`. +/// The *successor* operation moves towards values that compare greater. +/// The *predecessor* operation moves towards values that compare lesser. +/// +/// # Safety +/// +/// This trait is `unsafe` because its implementation must be correct for +/// the safety of `unsafe trait TrustedLen` implementations, and the results +/// of using this trait can otherwise be trusted by `unsafe` code to be correct +/// and fulful the listed obligations. +#[unstable(feature = "step_trait", reason = "recently redesigned", issue = "42168")] +pub unsafe trait Step: Clone + PartialOrd + Sized { + /// Returns the number of *successor* steps required to get from `start` to `end`. /// - /// Returns `None` if it is not possible to calculate `steps_between` - /// without overflow. + /// Returns `None` if the number of steps would overflow `usize` + /// (or is infinite, or if `end` would never be reached). + /// + /// # Invariants + /// + /// For any `a`, `b`, and `n`: + /// + /// * `steps_between(&a, &b) == Some(n)` if and only if `Step::forward(&a, n) == Some(b)` + /// * `steps_between(&a, &b) == Some(n)` if and only if `Step::backward(&a, n) == Some(a)` + /// * `steps_between(&a, &b) == Some(n)` only if `a <= b` + /// * Corollary: `steps_between(&a, &b) == Some(0)` if and only if `a == b` + /// * Note that `a <= b` does _not_ imply `steps_between(&a, &b) != None`; + /// this is the case wheen it would require more than `usize::MAX` steps to get to `b` + /// * `steps_between(&a, &b) == None` if `a > b` fn steps_between(start: &Self, end: &Self) -> Option; - /// Replaces this step with `1`, returning a clone of itself. + /// Returns the value that would be obtained by taking the *successor* + /// of `self` `count` times. /// - /// The output of this method should always be greater than the output of replace_zero. - fn replace_one(&mut self) -> Self; - - /// Replaces this step with `0`, returning a clone of itself. + /// If this would overflow the range of values supported by `Self`, returns `None`. /// - /// The output of this method should always be less than the output of replace_one. - fn replace_zero(&mut self) -> Self; + /// # Invariants + /// + /// For any `a`, `n`, and `m`: + /// + /// * `Step::forward_checked(a, n).and_then(|x| Step::forward_checked(x, m)) == n.checked_add(m).and_then(|x| Step::forward_checked(a, x))` + /// * `Step::forward_checked(a, n).and_then(|x| Step::forward_checked(x, m)) == try { Step::forward_checked(a, n.checked_add(m)?) }` + /// + /// For any `a` and `n`: + /// + /// * `Step::forward_checked(a, n) == (0..n).try_fold(a, |x, _| Step::forward_checked(&x, 1))` + /// * Corollary: `Step::forward_checked(&a, 0) == Some(a)` + #[unstable(feature = "step_trait_ext", reason = "recently added", issue = "42168")] + fn forward_checked(start: Self, count: usize) -> Option; - /// Adds one to this step, returning the result. - fn add_one(&self) -> Self; + /// Returns the value that would be obtained by taking the *successor* + /// of `self` `count` times. + /// + /// If this would overflow the range of values supported by `Self`, + /// this function is allowed to panic, wrap, or saturate. + /// The suggested behavior is to panic when debug assertions are enabled, + /// and to wrap or saturate otherwise. + /// + /// Unsafe code should not rely on the correctness of behavior after overflow. + /// + /// # Invariants + /// + /// For any `a`, `n`, and `m`, where no overflow occurs: + /// + /// * `Step::forward(Step::forward(a, n), m) == Step::forward(a, n + m)` + /// + /// For any `a` and `n`, where no overflow occurs: + /// + /// * `Step::forward_checked(a, n) == Some(Step::forward(a, n))` + /// * `Step::forward(a, n) == (0..n).fold(a, |x, _| Step::forward(x, 1))` + /// * Corollary: `Step::forward(a, 0) == a` + /// * `Step::forward(a, n) >= a` + /// * `Step::backward(Step::forward(a, n), n) == a` + #[unstable(feature = "step_trait_ext", reason = "recently added", issue = "42168")] + fn forward(start: Self, count: usize) -> Self { + Step::forward_checked(start, count).expect("overflow in `Step::forward`") + } - /// Subtracts one to this step, returning the result. - fn sub_one(&self) -> Self; + /// Returns the value that would be obtained by taking the *successor* + /// of `self` `count` times. + /// + /// # Safety + /// + /// It is undefined behavior for this operation to overflow the + /// range of values supported by `Self`. If you cannot guarantee that this + /// will not overflow, use `forward` or `forward_checked` instead. + /// + /// # Invariants + /// + /// For any `a`: + /// + /// * if there exists `b` such that `b > a`, it is safe to call `Step::forward_unchecked(a, 1)` + /// * if there exists `b`, `n` such that `steps_between(&a, &b) == Some(n)`, + /// it is safe to call `Step::forward_unchecked(a, m)` for any `m <= n`. + /// + /// For any `a` and `n`, where no overflow occurs: + /// + /// * `Step::forward_unchecked(a, n)` is equivalent to `Step::forward(a, n)` + #[unstable(feature = "unchecked_math", reason = "niche optimization path", issue = "none")] + unsafe fn forward_unchecked(start: Self, count: usize) -> Self { + Step::forward(start, count) + } - /// Adds a `usize`, returning `None` on overflow. - fn add_usize(&self, n: usize) -> Option; + /// Returns the value that would be obtained by taking the *successor* + /// of `self` `count` times. + /// + /// If this would overflow the range of values supported by `Self`, returns `None`. + /// + /// # Invariants + /// + /// For any `a`, `n`, and `m`: + /// + /// * `Step::backward_checked(a, n).and_then(|x| Step::backward_checked(x, m)) == n.checked_add(m).and_then(|x| Step::backward_checked(a, x))` + /// * `Step::backward_checked(a, n).and_then(|x| Step::backward_checked(x, m)) == try { Step::backward_checked(a, n.checked_add(m)?) }` + /// + /// For any `a` and `n`: + /// + /// * `Step::backward_checked(a, n) == (0..n).try_fold(a, |x, _| Step::backward_checked(&x, 1))` + /// * Corollary: `Step::backward_checked(&a, 0) == Some(a)` + #[unstable(feature = "step_trait_ext", reason = "recently added", issue = "42168")] + fn backward_checked(start: Self, count: usize) -> Option; - /// Subtracts a `usize`, returning `None` on underflow. - fn sub_usize(&self, n: usize) -> Option { - // this default implementation makes the addition of `sub_usize` a non-breaking change - let _ = n; - unimplemented!() + /// Returns the value that would be obtained by taking the *predecessor* + /// of `self` `count` times. + /// + /// If this would overflow the range of values supported by `Self`, + /// this function is allowed to panic, wrap, or saturate. + /// The suggested behavior is to panic when debug assertions are enabled, + /// and to wrap or saturate otherwise. + /// + /// Unsafe code should not rely on the correctness of behavior after overflow. + /// + /// # Invariants + /// + /// For any `a`, `n`, and `m`, where no overflow occurs: + /// + /// * `Step::backward(Step::backward(a, n), m) == Step::backward(a, n + m)` + /// + /// For any `a` and `n`, where no overflow occurs: + /// + /// * `Step::backward_checked(a, n) == Some(Step::backward(a, n))` + /// * `Step::backward(a, n) == (0..n).fold(a, |x, _| Step::backward(x, 1))` + /// * Corollary: `Step::backward(a, 0) == a` + /// * `Step::backward(a, n) <= a` + /// * `Step::forward(Step::backward(a, n), n) == a` + #[unstable(feature = "step_trait_ext", reason = "recently added", issue = "42168")] + fn backward(start: Self, count: usize) -> Self { + Step::backward_checked(start, count).expect("overflow in `Step::backward`") + } + + /// Returns the value that would be obtained by taking the *predecessor* + /// of `self` `count` times. + /// + /// # Safety + /// + /// It is undefined behavior for this operation to overflow the + /// range of values supported by `Self`. If you cannot guarantee that this + /// will not overflow, use `backward` or `backward_checked` instead. + /// + /// # Invariants + /// + /// For any `a`: + /// + /// * if there exists `b` such that `b < a`, it is safe to call `Step::backward_unchecked(a, 1)` + /// * if there exists `b`, `n` such that `steps_between(&b, &a) == Some(n)`, + /// it is safe to call `Step::backward_unchecked(a, m)` for any `m <= n`. + /// + /// For any `a` and `n`, where no overflow occurs: + /// + /// * `Step::backward_unchecked(a, n)` is equivalent to `Step::backward(a, n)` + #[unstable(feature = "unchecked_math", reason = "niche optimization path", issue = "none")] + unsafe fn backward_unchecked(start: Self, count: usize) -> Self { + Step::backward(start, count) } } @@ -53,127 +185,243 @@ pub trait Step: Clone + PartialOrd + Sized { macro_rules! step_identical_methods { () => { #[inline] - fn replace_one(&mut self) -> Self { - mem::replace(self, 1) + unsafe fn forward_unchecked(start: Self, n: usize) -> Self { + start.unchecked_add(n as Self) } #[inline] - fn replace_zero(&mut self) -> Self { - mem::replace(self, 0) + unsafe fn backward_unchecked(start: Self, n: usize) -> Self { + start.unchecked_sub(n as Self) + } + }; + ( [$u:ident $i:ident] ) => { + step_identical_methods!(); + + #[inline] + fn forward(start: Self, n: usize) -> Self { + match Self::forward_checked(start, n) { + Some(result) => result, + None => { + let result = Add::add(start, n as Self); + // add one modular cycle to ensure overflow occurs + Add::add(Add::add(result as $u, $u::MAX), 1) as Self + } + } } #[inline] - fn add_one(&self) -> Self { - Add::add(*self, 1) + fn backward(start: Self, n: usize) -> Self { + match Self::backward_checked(start, n) { + Some(result) => result, + None => { + let result = Sub::sub(start, n as Self); + // sub one modular cycle to ensure overflow occurs + Sub::sub(Sub::sub(result as $u, $u::MAX), 1) as Self + } + } } - - #[inline] - fn sub_one(&self) -> Self { - Sub::sub(*self, 1) - } - } + }; } -macro_rules! step_impl_unsigned { - ($($t:ty)*) => ($( - #[unstable(feature = "step_trait", - reason = "likely to be replaced by finer-grained traits", - issue = "42168")] - impl Step for $t { - #[inline] - fn steps_between(start: &$t, end: &$t) -> Option { - if *start < *end { - usize::try_from(*end - *start).ok() - } else { - Some(0) - } - } - - #[inline] +macro_rules! step_integer_impls { + { + narrower than or same width as usize: + $( [ $u_narrower:ident $i_narrower:ident ] ),+; + wider than usize: + $( [ $u_wider:ident $i_wider:ident ] ),+; + } => { + $( #[allow(unreachable_patterns)] - fn add_usize(&self, n: usize) -> Option { - match <$t>::try_from(n) { - Ok(n_as_t) => self.checked_add(n_as_t), - Err(_) => None, - } - } + #[unstable(feature = "step_trait", reason = "recently redesigned", issue = "42168")] + unsafe impl Step for $u_narrower { + step_identical_methods!( [ $u_narrower $i_narrower ] ); - #[inline] - #[allow(unreachable_patterns)] - fn sub_usize(&self, n: usize) -> Option { - match <$t>::try_from(n) { - Ok(n_as_t) => self.checked_sub(n_as_t), - Err(_) => None, - } - } - - step_identical_methods!(); - } - )*) -} -macro_rules! step_impl_signed { - ($( [$t:ty : $unsigned:ty] )*) => ($( - #[unstable(feature = "step_trait", - reason = "likely to be replaced by finer-grained traits", - issue = "42168")] - impl Step for $t { - #[inline] - fn steps_between(start: &$t, end: &$t) -> Option { - if *start < *end { - // Use .wrapping_sub and cast to unsigned to compute the - // difference that may not fit inside the range of $t. - usize::try_from(end.wrapping_sub(*start) as $unsigned).ok() - } else { - Some(0) - } - } - - #[inline] - #[allow(unreachable_patterns)] - fn add_usize(&self, n: usize) -> Option { - match <$unsigned>::try_from(n) { - Ok(n_as_unsigned) => { - // Wrapping in unsigned space handles cases like - // `-120_i8.add_usize(200) == Some(80_i8)`, - // even though 200_usize is out of range for i8. - let wrapped = (*self as $unsigned).wrapping_add(n_as_unsigned) as $t; - if wrapped >= *self { - Some(wrapped) - } else { - None // Addition overflowed - } + #[inline] + fn steps_between(start: &Self, end: &Self) -> Option { + if *start <= *end { + // This relies on $u_narrower <= usize + Some((*end - *start) as usize) + } else { + None } - Err(_) => None, } - } - #[inline] - #[allow(unreachable_patterns)] - fn sub_usize(&self, n: usize) -> Option { - match <$unsigned>::try_from(n) { - Ok(n_as_unsigned) => { - // Wrapping in unsigned space handles cases like - // `80_i8.sub_usize(200) == Some(-120_i8)`, - // even though 200_usize is out of range for i8. - let wrapped = (*self as $unsigned).wrapping_sub(n_as_unsigned) as $t; - if wrapped <= *self { - Some(wrapped) - } else { - None // Subtraction underflowed - } + #[inline] + fn forward_checked(start: Self, n: usize) -> Option { + match Self::try_from(n) { + Ok(n) => start.checked_add(n), + Err(_) => None, // if n is out of range, `unsigned_start + n` is too + } + } + + #[inline] + fn backward_checked(start: Self, n: usize) -> Option { + match Self::try_from(n) { + Ok(n) => start.checked_sub(n), + Err(_) => None, // if n is out of range, `unsigned_start - n` is too } - Err(_) => None, } } - step_identical_methods!(); - } - )*) + #[allow(unreachable_patterns)] + #[unstable(feature = "step_trait", reason = "recently redesigned", issue = "42168")] + unsafe impl Step for $i_narrower { + step_identical_methods!( [ $u_narrower $i_narrower ] ); + + #[inline] + fn steps_between(start: &Self, end: &Self) -> Option { + if *start <= *end { + // This relies on $i_narrower <= usize + // + // Casting to isize extends the width but preserves the sign. + // Use wrapping_sub in isize space and cast to usize to compute + // the difference that may not fit inside the range of isize. + Some((*end as isize).wrapping_sub(*start as isize) as usize) + } else { + None + } + } + + #[inline] + fn forward_checked(start: Self, n: usize) -> Option { + match $u_narrower::try_from(n) { + Ok(n) => { + // Wrapping handles cases like + // `Step::forward(-120_i8, 200) == Some(80_i8)`, + // even though 200 is out of range for i8. + let wrapped = start.wrapping_add(n as Self); + if wrapped >= start { + Some(wrapped) + } else { + None // Addition overflowed + } + } + // If n is out of range of e.g. u8, + // then it is bigger than the entire range for i8 is wide + // so `any_i8 + n` necessarily overflows i8. + Err(_) => None, + } + } + + #[inline] + fn backward_checked(start: Self, n: usize) -> Option { + match $u_narrower::try_from(n) { + Ok(n) => { + // Wrapping handles cases like + // `Step::forward(-120_i8, 200) == Some(80_i8)`, + // even though 200 is out of range for i8. + let wrapped = start.wrapping_sub(n as Self); + if wrapped <= start { + Some(wrapped) + } else { + None // Subtraction overflowed + } + } + // If n is out of range of e.g. u8, + // then it is bigger than the entire range for i8 is wide + // so `any_i8 - n` necessarily overflows i8. + Err(_) => None, + } + } + } + )+ + + $( + #[allow(unreachable_patterns)] + #[unstable(feature = "step_trait", reason = "recently redesigned", issue = "42168")] + unsafe impl Step for $u_wider { + step_identical_methods!(); + + #[inline] + fn steps_between(start: &Self, end: &Self) -> Option { + if *start <= *end { + usize::try_from(*end - *start).ok() + } else { + None + } + } + + #[inline] + fn forward_checked(start: Self, n: usize) -> Option { + start.checked_add(n as Self) + } + + #[inline] + fn forward(start: Self, n: usize) -> Self { + Add::add(start, n as Self) + } + + #[inline] + fn backward_checked(start: Self, n: usize) -> Option { + start.checked_sub(n as Self) + } + + #[inline] + fn backward(start: Self, n: usize) -> Self { + Sub::sub(start, n as Self) + } + } + + #[allow(unreachable_patterns)] + #[unstable(feature = "step_trait", reason = "recently redesigned", issue = "42168")] + unsafe impl Step for $i_wider { + step_identical_methods!(); + + #[inline] + fn steps_between(start: &Self, end: &Self) -> Option { + if *start <= *end { + match end.checked_sub(*start) { + Some(result) => usize::try_from(result).ok(), + // If the difference is too big for e.g. i128, + // it's also gonna be too big for usize with fewer bits. + None => None, + } + } else { + None + } + } + + #[inline] + fn forward_checked(start: Self, n: usize) -> Option { + start.checked_add(n as Self) + } + + #[inline] + fn forward(start: Self, n: usize) -> Self { + Add::add(start, n as Self) + } + + #[inline] + fn backward_checked(start: Self, n: usize) -> Option { + start.checked_sub(n as Self) + } + + #[inline] + fn backward(start: Self, n: usize) -> Self { + Sub::sub(start, n as Self) + } + } + )+ + }; } -step_impl_unsigned!(usize u8 u16 u32 u64 u128); -step_impl_signed!([isize: usize][i8: u8][i16: u16]); -step_impl_signed!([i32: u32][i64: u64][i128: u128]); +#[cfg(target_pointer_width = "64")] +step_integer_impls! { + narrower than or same width as usize: [u8 i8], [u16 i16], [u32 i32], [u64 i64], [usize isize]; + wider than usize: [u128 i128]; +} + +#[cfg(target_pointer_width = "32")] +step_integer_impls! { + narrower than or same width as usize: [u8 i8], [u16 i16], [u32 i32], [usize isize]; + wider than usize: [u64 i64], [u128 i128]; +} + +#[cfg(target_pointer_width = "16")] +step_integer_impls! { + narrower than or same width as usize: [u8 i8], [u16 i16], [usize isize]; + wider than usize: [u32 i32], [u64 i64], [u128 i128]; +} macro_rules! range_exact_iter_impl { ($($t:ty)*) => ($( @@ -189,20 +437,6 @@ macro_rules! range_incl_exact_iter_impl { )*) } -macro_rules! range_trusted_len_impl { - ($($t:ty)*) => ($( - #[unstable(feature = "trusted_len", issue = "37572")] - unsafe impl TrustedLen for ops::Range<$t> { } - )*) -} - -macro_rules! range_incl_trusted_len_impl { - ($($t:ty)*) => ($( - #[unstable(feature = "trusted_len", issue = "37572")] - unsafe impl TrustedLen for ops::RangeInclusive<$t> { } - )*) -} - #[stable(feature = "rust1", since = "1.0.0")] impl Iterator for ops::Range { type Item = A; @@ -210,16 +444,12 @@ impl Iterator for ops::Range { #[inline] fn next(&mut self) -> Option { if self.start < self.end { - // We check for overflow here, even though it can't actually - // happen. Adding this check does however help llvm vectorize loops - // for some ranges that don't get vectorized otherwise, - // and this won't actually result in an extra check in an optimized build. - if let Some(mut n) = self.start.add_usize(1) { - mem::swap(&mut n, &mut self.start); - Some(n) - } else { - None - } + // SAFETY: just checked precondition + // We use the unchecked version here, because + // this helps LLVM vectorize loops for some ranges + // that don't get vectorized otherwise. + let n = unsafe { Step::forward_unchecked(self.start.clone(), 1) }; + Some(mem::replace(&mut self.start, n)) } else { None } @@ -227,17 +457,19 @@ impl Iterator for ops::Range { #[inline] fn size_hint(&self) -> (usize, Option) { - match Step::steps_between(&self.start, &self.end) { - Some(hint) => (hint, Some(hint)), - None => (usize::MAX, None), + if self.start < self.end { + let hint = Step::steps_between(&self.start, &self.end); + (hint.unwrap_or(usize::MAX), hint) + } else { + (0, Some(0)) } } #[inline] fn nth(&mut self, n: usize) -> Option { - if let Some(plus_n) = self.start.add_usize(n) { + if let Some(plus_n) = Step::forward_checked(self.start.clone(), n) { if plus_n < self.end { - self.start = plus_n.add_one(); + self.start = Step::forward(plus_n.clone(), 1); return Some(plus_n); } } @@ -263,25 +495,42 @@ impl Iterator for ops::Range { } // These macros generate `ExactSizeIterator` impls for various range types. -// Range<{u,i}64> and RangeInclusive<{u,i}{32,64,size}> are excluded -// because they cannot guarantee having a length <= usize::MAX, which is -// required by ExactSizeIterator. -range_exact_iter_impl!(usize u8 u16 u32 isize i8 i16 i32); -range_incl_exact_iter_impl!(u8 u16 i8 i16); - -// These macros generate `TrustedLen` impls. // -// They need to guarantee that .size_hint() is either exact, or that -// the upper bound is None when it does not fit the type limits. -range_trusted_len_impl!(usize isize u8 i8 u16 i16 u32 i32 u64 i64 u128 i128); -range_incl_trusted_len_impl!(usize isize u8 i8 u16 i16 u32 i32 u64 i64 u128 i128); +// * `ExactSizeIterator::len` is required to always return an exact `usize`, +// so no range can be longer than `usize::MAX`. +// * For integer types in `Range<_>` this is the case for types narrower than or as wide as `usize`. +// For integer types in `RangeInclusive<_>` +// this is the case for types *strictly narrower* than `usize` +// since e.g. `(0..=u64::MAX).len()` would be `u64::MAX + 1`. +range_exact_iter_impl! { + usize u8 u16 + isize i8 i16 + + // These are incorect per the reasoning above, + // but removing them would be a breaking change as they were stabilized in Rust 1.0.0. + // So e.g. `(0..66_000_u32).len()` for example will compile without error or warnings + // on 16-bit platforms, but continue to give a wrong result. + u32 + i32 +} +range_incl_exact_iter_impl! { + u8 + i8 + + // These are incorect per the reasoning above, + // but removing them would be a breaking change as they were stabilized in Rust 1.26.0. + // So e.g. `(0..=u16::MAX).len()` for example will compile without error or warnings + // on 16-bit platforms, but continue to give a wrong result. + u16 + i16 +} #[stable(feature = "rust1", since = "1.0.0")] impl DoubleEndedIterator for ops::Range { #[inline] fn next_back(&mut self) -> Option { if self.start < self.end { - self.end = self.end.sub_one(); + self.end = Step::backward(self.end.clone(), 1); Some(self.end.clone()) } else { None @@ -290,9 +539,9 @@ impl DoubleEndedIterator for ops::Range { #[inline] fn nth_back(&mut self, n: usize) -> Option { - if let Some(minus_n) = self.end.sub_usize(n) { + if let Some(minus_n) = Step::backward_checked(self.end.clone(), n) { if minus_n > self.start { - self.end = minus_n.sub_one(); + self.end = Step::backward(minus_n, 1); return Some(self.end.clone()); } } @@ -302,6 +551,9 @@ impl DoubleEndedIterator for ops::Range { } } +#[unstable(feature = "trusted_len", issue = "37572")] +unsafe impl TrustedLen for ops::Range {} + #[stable(feature = "fused", since = "1.26.0")] impl FusedIterator for ops::Range {} @@ -311,9 +563,8 @@ impl Iterator for ops::RangeFrom { #[inline] fn next(&mut self) -> Option { - let mut n = self.start.add_one(); - mem::swap(&mut n, &mut self.start); - Some(n) + let n = Step::forward(self.start.clone(), 1); + Some(mem::replace(&mut self.start, n)) } #[inline] @@ -323,8 +574,16 @@ impl Iterator for ops::RangeFrom { #[inline] fn nth(&mut self, n: usize) -> Option { - let plus_n = self.start.add_usize(n).expect("overflow in RangeFrom::nth"); - self.start = plus_n.add_one(); + // If we would jump over the maximum value, panic immediately. + // This is consistent with behavior before the Step redesign, + // even though it's inconsistent with n `next` calls. + // To get consistent behavior, change it to use `forward` instead. + // This change should go through FCP separately to the redesign, so is for now left as a + // FIXME: make this consistent + let plus_n = + Step::forward_checked(self.start.clone(), n).expect("overflow in RangeFrom::nth"); + // The final step should always be debug-checked. + self.start = Step::forward(plus_n.clone(), 1); Some(plus_n) } } @@ -346,7 +605,7 @@ impl Iterator for ops::RangeInclusive { } let is_iterating = self.start < self.end; Some(if is_iterating { - let n = self.start.add_one(); + let n = Step::forward(self.start.clone(), 1); mem::replace(&mut self.start, n) } else { self.exhausted = true; @@ -372,12 +631,12 @@ impl Iterator for ops::RangeInclusive { return None; } - if let Some(plus_n) = self.start.add_usize(n) { + if let Some(plus_n) = Step::forward_checked(self.start.clone(), n) { use crate::cmp::Ordering::*; match plus_n.partial_cmp(&self.end) { Some(Less) => { - self.start = plus_n.add_one(); + self.start = Step::forward(plus_n.clone(), 1); return Some(plus_n); } Some(Equal) => { @@ -408,7 +667,7 @@ impl Iterator for ops::RangeInclusive { let mut accum = init; while self.start < self.end { - let n = self.start.add_one(); + let n = Step::forward(self.start.clone(), 1); let n = mem::replace(&mut self.start, n); accum = f(accum, n)?; } @@ -447,7 +706,7 @@ impl DoubleEndedIterator for ops::RangeInclusive { } let is_iterating = self.start < self.end; Some(if is_iterating { - let n = self.end.sub_one(); + let n = Step::backward(self.end.clone(), 1); mem::replace(&mut self.end, n) } else { self.exhausted = true; @@ -461,12 +720,12 @@ impl DoubleEndedIterator for ops::RangeInclusive { return None; } - if let Some(minus_n) = self.end.sub_usize(n) { + if let Some(minus_n) = Step::backward_checked(self.end.clone(), n) { use crate::cmp::Ordering::*; match minus_n.partial_cmp(&self.start) { Some(Greater) => { - self.end = minus_n.sub_one(); + self.end = Step::backward(minus_n.clone(), 1); return Some(minus_n); } Some(Equal) => { @@ -497,7 +756,7 @@ impl DoubleEndedIterator for ops::RangeInclusive { let mut accum = init; while self.start < self.end { - let n = self.end.sub_one(); + let n = Step::backward(self.end.clone(), 1); let n = mem::replace(&mut self.end, n); accum = f(accum, n)?; } @@ -512,5 +771,8 @@ impl DoubleEndedIterator for ops::RangeInclusive { } } +#[unstable(feature = "trusted_len", issue = "37572")] +unsafe impl TrustedLen for ops::RangeInclusive {} + #[stable(feature = "fused", since = "1.26.0")] impl FusedIterator for ops::RangeInclusive {} diff --git a/src/libcore/tests/iter.rs b/src/libcore/tests/iter.rs index 1a1dbcd7b871..13c05dadbde7 100644 --- a/src/libcore/tests/iter.rs +++ b/src/libcore/tests/iter.rs @@ -228,7 +228,11 @@ fn test_iterator_chain_size_hint() { } fn size_hint(&self) -> (usize, Option) { - if self.is_empty { (0, Some(0)) } else { (1, Some(1)) } + if self.is_empty { + (0, Some(0)) + } else { + (1, Some(1)) + } } } @@ -1554,7 +1558,11 @@ fn test_find_map() { assert_eq!(iter.next(), Some(&7)); fn half_if_even(x: &isize) -> Option { - if x % 2 == 0 { Some(x / 2) } else { None } + if x % 2 == 0 { + Some(x / 2) + } else { + None + } } } @@ -2125,6 +2133,24 @@ fn test_range_inclusive_nth_back() { assert_eq!(ExactSizeIterator::is_empty(&r), true); } +#[test] +fn test_range_len() { + assert_eq!((0..10_u8).len(), 10); + assert_eq!((9..10_u8).len(), 1); + assert_eq!((10..10_u8).len(), 0); + assert_eq!((11..10_u8).len(), 0); + assert_eq!((100..10_u8).len(), 0); +} + +#[test] +fn test_range_inclusive_len() { + assert_eq!((0..=10_u8).len(), 11); + assert_eq!((9..=10_u8).len(), 2); + assert_eq!((10..=10_u8).len(), 1); + assert_eq!((11..=10_u8).len(), 0); + assert_eq!((100..=10_u8).len(), 0); +} + #[test] fn test_range_step() { #![allow(deprecated)] @@ -2495,42 +2521,91 @@ fn test_chain_fold() { } #[test] -fn test_step_replace_unsigned() { - let mut x = 4u32; - let y = x.replace_zero(); - assert_eq!(x, 0); - assert_eq!(y, 4); +fn test_steps_between() { + assert_eq!(Step::steps_between(&20_u8, &200_u8), Some(180_usize)); + assert_eq!(Step::steps_between(&-20_i8, &80_i8), Some(100_usize)); + assert_eq!(Step::steps_between(&-120_i8, &80_i8), Some(200_usize)); + assert_eq!(Step::steps_between(&20_u32, &4_000_100_u32), Some(4_000_080_usize)); + assert_eq!(Step::steps_between(&-20_i32, &80_i32), Some(100_usize)); + assert_eq!(Step::steps_between(&-2_000_030_i32, &2_000_050_i32), Some(4_000_080_usize)); - x = 5; - let y = x.replace_one(); - assert_eq!(x, 1); - assert_eq!(y, 5); + // Skip u64/i64 to avoid differences with 32-bit vs 64-bit platforms + + assert_eq!(Step::steps_between(&20_u128, &200_u128), Some(180_usize)); + assert_eq!(Step::steps_between(&-20_i128, &80_i128), Some(100_usize)); + if cfg!(target_pointer_width = "64") { + assert_eq!(Step::steps_between(&10_u128, &0x1_0000_0000_0000_0009_u128), Some(usize::MAX)); + } + assert_eq!(Step::steps_between(&10_u128, &0x1_0000_0000_0000_000a_u128), None); + assert_eq!(Step::steps_between(&10_i128, &0x1_0000_0000_0000_000a_i128), None); + assert_eq!( + Step::steps_between(&-0x1_0000_0000_0000_0000_i128, &0x1_0000_0000_0000_0000_i128,), + None, + ); } #[test] -fn test_step_replace_signed() { - let mut x = 4i32; - let y = x.replace_zero(); - assert_eq!(x, 0); - assert_eq!(y, 4); +fn test_step_forward() { + assert_eq!(Step::forward_checked(55_u8, 200_usize), Some(255_u8)); + assert_eq!(Step::forward_checked(252_u8, 200_usize), None); + assert_eq!(Step::forward_checked(0_u8, 256_usize), None); + assert_eq!(Step::forward_checked(-110_i8, 200_usize), Some(90_i8)); + assert_eq!(Step::forward_checked(-110_i8, 248_usize), None); + assert_eq!(Step::forward_checked(-126_i8, 256_usize), None); - x = 5; - let y = x.replace_one(); - assert_eq!(x, 1); - assert_eq!(y, 5); + assert_eq!(Step::forward_checked(35_u16, 100_usize), Some(135_u16)); + assert_eq!(Step::forward_checked(35_u16, 65500_usize), Some(u16::MAX)); + assert_eq!(Step::forward_checked(36_u16, 65500_usize), None); + assert_eq!(Step::forward_checked(-110_i16, 200_usize), Some(90_i16)); + assert_eq!(Step::forward_checked(-20_030_i16, 50_050_usize), Some(30_020_i16)); + assert_eq!(Step::forward_checked(-10_i16, 40_000_usize), None); + assert_eq!(Step::forward_checked(-10_i16, 70_000_usize), None); + + assert_eq!(Step::forward_checked(10_u128, 70_000_usize), Some(70_010_u128)); + assert_eq!(Step::forward_checked(10_i128, 70_030_usize), Some(70_040_i128)); + assert_eq!( + Step::forward_checked(0xffff_ffff_ffff_ffff__ffff_ffff_ffff_ff00_u128, 0xff_usize), + Some(u128::MAX), + ); + assert_eq!( + Step::forward_checked(0xffff_ffff_ffff_ffff__ffff_ffff_ffff_ff00_u128, 0x100_usize), + None + ); + assert_eq!( + Step::forward_checked(0x7fff_ffff_ffff_ffff__ffff_ffff_ffff_ff00_i128, 0xff_usize), + Some(i128::MAX), + ); + assert_eq!( + Step::forward_checked(0x7fff_ffff_ffff_ffff__ffff_ffff_ffff_ff00_i128, 0x100_usize), + None + ); } #[test] -fn test_step_replace_no_between() { - let mut x = 4u128; - let y = x.replace_zero(); - assert_eq!(x, 0); - assert_eq!(y, 4); +fn test_step_backward() { + assert_eq!(Step::backward_checked(255_u8, 200_usize), Some(55_u8)); + assert_eq!(Step::backward_checked(100_u8, 200_usize), None); + assert_eq!(Step::backward_checked(255_u8, 256_usize), None); + assert_eq!(Step::backward_checked(90_i8, 200_usize), Some(-110_i8)); + assert_eq!(Step::backward_checked(110_i8, 248_usize), None); + assert_eq!(Step::backward_checked(127_i8, 256_usize), None); - x = 5; - let y = x.replace_one(); - assert_eq!(x, 1); - assert_eq!(y, 5); + assert_eq!(Step::backward_checked(135_u16, 100_usize), Some(35_u16)); + assert_eq!(Step::backward_checked(u16::MAX, 65500_usize), Some(35_u16)); + assert_eq!(Step::backward_checked(10_u16, 11_usize), None); + assert_eq!(Step::backward_checked(90_i16, 200_usize), Some(-110_i16)); + assert_eq!(Step::backward_checked(30_020_i16, 50_050_usize), Some(-20_030_i16)); + assert_eq!(Step::backward_checked(-10_i16, 40_000_usize), None); + assert_eq!(Step::backward_checked(-10_i16, 70_000_usize), None); + + assert_eq!(Step::backward_checked(70_010_u128, 70_000_usize), Some(10_u128)); + assert_eq!(Step::backward_checked(70_020_i128, 70_030_usize), Some(-10_i128)); + assert_eq!(Step::backward_checked(10_u128, 7_usize), Some(3_u128)); + assert_eq!(Step::backward_checked(10_u128, 11_usize), None); + assert_eq!( + Step::backward_checked(-0x7fff_ffff_ffff_ffff__ffff_ffff_ffff_ff00_i128, 0x100_usize), + Some(i128::MIN) + ); } #[test] diff --git a/src/libcore/tests/lib.rs b/src/libcore/tests/lib.rs index 05f958cbe81f..3d6abb818e4e 100644 --- a/src/libcore/tests/lib.rs +++ b/src/libcore/tests/lib.rs @@ -22,6 +22,7 @@ #![feature(slice_partition_at_index)] #![feature(specialization)] #![feature(step_trait)] +#![feature(step_trait_ext)] #![feature(str_internals)] #![feature(test)] #![feature(trusted_len)] diff --git a/src/librustc_index/vec.rs b/src/librustc_index/vec.rs index a84f89c7cd95..67dcea58cf82 100644 --- a/src/librustc_index/vec.rs +++ b/src/librustc_index/vec.rs @@ -65,7 +65,7 @@ impl Idx for u32 { /// `u32::MAX`. You can also customize things like the `Debug` impl, /// what traits are derived, and so forth via the macro. #[macro_export] -#[allow_internal_unstable(step_trait, rustc_attrs)] +#[allow_internal_unstable(step_trait, step_trait_ext, rustc_attrs)] macro_rules! newtype_index { // ---- public rules ---- @@ -181,7 +181,7 @@ macro_rules! newtype_index { } } - impl ::std::iter::Step for $type { + unsafe impl ::std::iter::Step for $type { #[inline] fn steps_between(start: &Self, end: &Self) -> Option { ::steps_between( @@ -191,33 +191,13 @@ macro_rules! newtype_index { } #[inline] - fn replace_one(&mut self) -> Self { - ::std::mem::replace(self, Self::from_u32(1)) + fn forward_checked(start: Self, u: usize) -> Option { + Self::index(start).checked_add(u).map(Self::from_usize) } #[inline] - fn replace_zero(&mut self) -> Self { - ::std::mem::replace(self, Self::from_u32(0)) - } - - #[inline] - fn add_one(&self) -> Self { - Self::from_usize(Self::index(*self) + 1) - } - - #[inline] - fn sub_one(&self) -> Self { - Self::from_usize(Self::index(*self) - 1) - } - - #[inline] - fn add_usize(&self, u: usize) -> Option { - Self::index(*self).checked_add(u).map(Self::from_usize) - } - - #[inline] - fn sub_usize(&self, u: usize) -> Option { - Self::index(*self).checked_sub(u).map(Self::from_usize) + fn backward_checked(start: Self, u: usize) -> Option { + Self::index(start).checked_sub(u).map(Self::from_usize) } } diff --git a/src/test/ui/impl-trait/example-calendar.rs b/src/test/ui/impl-trait/example-calendar.rs index f1b1656745e7..fafab8a102a9 100644 --- a/src/test/ui/impl-trait/example-calendar.rs +++ b/src/test/ui/impl-trait/example-calendar.rs @@ -2,6 +2,7 @@ #![feature(fn_traits, step_trait, + step_trait_ext, unboxed_closures, )] @@ -10,7 +11,6 @@ //! Originally converted to Rust by [Daniel Keep](https://github.com/DanielKeep). use std::fmt::Write; -use std::mem; /// Date representation. #[derive(Copy, Clone, Debug, Eq, Ord, PartialEq, PartialOrd)] @@ -156,32 +156,16 @@ impl<'a, 'b> std::ops::Add<&'b NaiveDate> for &'a NaiveDate { } } -impl std::iter::Step for NaiveDate { +unsafe impl std::iter::Step for NaiveDate { fn steps_between(_: &Self, _: &Self) -> Option { unimplemented!() } - fn replace_one(&mut self) -> Self { - mem::replace(self, NaiveDate(0, 0, 1)) + fn forward_checked(start: Self, n: usize) -> Option { + Some((0..n).fold(start, |x, _| x.succ())) } - fn replace_zero(&mut self) -> Self { - mem::replace(self, NaiveDate(0, 0, 0)) - } - - fn add_one(&self) -> Self { - self.succ() - } - - fn sub_one(&self) -> Self { - unimplemented!() - } - - fn add_usize(&self, _: usize) -> Option { - unimplemented!() - } - - fn sub_usize(&self, _: usize) -> Option { + fn backward_checked(_: Self, _: usize) -> Option { unimplemented!() } } From f34322d71f6ba523fb2c0ebef258d7e51a7531c8 Mon Sep 17 00:00:00 2001 From: CAD97 Date: Sat, 14 Mar 2020 15:13:18 -0400 Subject: [PATCH 003/203] Adjust Step::forward_checked docs for large types Co-Authored-By: Nadrieril Feneanar --- src/libcore/iter/range.rs | 7 +++++-- src/libcore/tests/iter.rs | 12 ++---------- 2 files changed, 7 insertions(+), 12 deletions(-) diff --git a/src/libcore/iter/range.rs b/src/libcore/iter/range.rs index ae88fb471a07..1b0968939026 100644 --- a/src/libcore/iter/range.rs +++ b/src/libcore/iter/range.rs @@ -45,8 +45,11 @@ pub unsafe trait Step: Clone + PartialOrd + Sized { /// /// For any `a`, `n`, and `m`: /// - /// * `Step::forward_checked(a, n).and_then(|x| Step::forward_checked(x, m)) == n.checked_add(m).and_then(|x| Step::forward_checked(a, x))` - /// * `Step::forward_checked(a, n).and_then(|x| Step::forward_checked(x, m)) == try { Step::forward_checked(a, n.checked_add(m)?) }` + /// * `Step::forward_checked(a, n).and_then(|x| Step::forward_checked(x, m)) == Step::forward_checked(a, m).and_then(|x| Step::forward_checked(x, n))` + /// + /// For any `a`, `n`, and `m` where `n + m` does not overflow: + /// + /// * `Step::forward_checked(a, n).and_then(|x| Step::forward_checked(x, m)) == Step::forward_checked(a, n + m)` /// /// For any `a` and `n`: /// diff --git a/src/libcore/tests/iter.rs b/src/libcore/tests/iter.rs index 13c05dadbde7..e142641b8b51 100644 --- a/src/libcore/tests/iter.rs +++ b/src/libcore/tests/iter.rs @@ -228,11 +228,7 @@ fn test_iterator_chain_size_hint() { } fn size_hint(&self) -> (usize, Option) { - if self.is_empty { - (0, Some(0)) - } else { - (1, Some(1)) - } + if self.is_empty { (0, Some(0)) } else { (1, Some(1)) } } } @@ -1558,11 +1554,7 @@ fn test_find_map() { assert_eq!(iter.next(), Some(&7)); fn half_if_even(x: &isize) -> Option { - if x % 2 == 0 { - Some(x / 2) - } else { - None - } + if x % 2 == 0 { Some(x / 2) } else { None } } } From db1fbd4a11db579436f68be3a8f5fe03484aa45d Mon Sep 17 00:00:00 2001 From: Mohsen Zohrevandi Date: Wed, 25 Mar 2020 19:28:14 -0700 Subject: [PATCH 004/203] Process termination tests Related issues: - https://github.com/fortanix/rust-sgx/issues/109 --- .../process-termination-blocking-io.rs | 18 ++++++++++++++++++ .../process-termination-simple.rs | 12 ++++++++++++ 2 files changed, 30 insertions(+) create mode 100644 src/test/ui/process-termination/process-termination-blocking-io.rs create mode 100644 src/test/ui/process-termination/process-termination-simple.rs diff --git a/src/test/ui/process-termination/process-termination-blocking-io.rs b/src/test/ui/process-termination/process-termination-blocking-io.rs new file mode 100644 index 000000000000..d9027fc89e29 --- /dev/null +++ b/src/test/ui/process-termination/process-termination-blocking-io.rs @@ -0,0 +1,18 @@ +// program should terminate even if a thread is blocked on I/O. +// https://github.com/fortanix/rust-sgx/issues/109 + +// run-pass + +use std::{net::TcpListener, sync::mpsc, thread}; + +fn main() { + let (tx, rx) = mpsc::channel(); + thread::spawn(move || { + let listen = TcpListener::bind("0:0").unwrap(); + tx.send(()).unwrap(); + while let Ok(_) = listen.accept() {} + }); + rx.recv().unwrap(); + for _ in 0..3 { thread::yield_now(); } + println!("Exiting main thread"); +} diff --git a/src/test/ui/process-termination/process-termination-simple.rs b/src/test/ui/process-termination/process-termination-simple.rs new file mode 100644 index 000000000000..7098a34512ee --- /dev/null +++ b/src/test/ui/process-termination/process-termination-simple.rs @@ -0,0 +1,12 @@ +// program should terminate when std::process::exit is called from any thread + +// run-pass + +use std::{process, thread}; + +fn main() { + let h = thread::spawn(|| { + process::exit(0); + }); + let _ = h.join(); +} From 079817d62481ca8d84ca87dde9a276a1d5d663cf Mon Sep 17 00:00:00 2001 From: Donough Liu Date: Sat, 25 Apr 2020 08:56:07 +0800 Subject: [PATCH 005/203] Make `prefix` immutable --- src/librustc_typeck/check/demand.rs | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs index 7db376b20aaa..7e33bb8c2a74 100644 --- a/src/librustc_typeck/check/demand.rs +++ b/src/librustc_typeck/check/demand.rs @@ -614,24 +614,24 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // For now, don't suggest casting with `as`. let can_cast = false; - let mut prefix = String::new(); - if let Some(hir::Node::Expr(hir::Expr { - kind: hir::ExprKind::Struct(_, fields, _), .. + let prefix = if let Some(hir::Node::Expr(hir::Expr { + kind: hir::ExprKind::Struct(_, fields, _), + .. })) = self.tcx.hir().find(self.tcx.hir().get_parent_node(expr.hir_id)) { // `expr` is a literal field for a struct, only suggest if appropriate - for field in *fields { - if field.expr.hir_id == expr.hir_id && field.is_shorthand { - // This is a field literal - prefix = format!("{}: ", field.ident); - break; - } - } - if &prefix == "" { + match (*fields) + .iter() + .find(|field| field.expr.hir_id == expr.hir_id && field.is_shorthand) + { + // This is a field literal + Some(field) => format!("{}: ", field.ident), // Likely a field was meant, but this field wasn't found. Do not suggest anything. - return false; + None => return false, } - } + } else { + String::new() + }; if let hir::ExprKind::Call(path, args) = &expr.kind { if let (hir::ExprKind::Path(hir::QPath::TypeRelative(base_ty, path_segment)), 1) = (&path.kind, args.len()) @@ -723,7 +723,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let suggest_to_change_suffix_or_into = |err: &mut DiagnosticBuilder<'_>, is_fallible: bool| { - let into_sugg = into_suggestion.clone(); err.span_suggestion( expr.span, if literal_is_ty_suffixed(expr) { @@ -738,7 +737,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } else if is_fallible { try_into_suggestion } else { - into_sugg + into_suggestion.clone() }, Applicability::MachineApplicable, ); From cb2703945ca3c6c9664a5a9ec606430cb79ba2c8 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sun, 19 Apr 2020 12:34:00 +0100 Subject: [PATCH 006/203] Use min_specialization in liballoc - Remove a type parameter from `[A]RcFromIter`. - Remove an implementation of `[A]RcFromIter` that didn't actually specialize anything. - Remove unused implementation of `IsZero` for `Option<&mut T>`. - Change specializations of `[A]RcEqIdent` to use a marker trait version of `Eq`. - Remove `BTreeClone`. I couldn't find a way to make this work with `min_specialization`. - Add `rustc_unsafe_specialization_marker` to `Copy` and `TrustedLen`. --- src/liballoc/collections/btree/map.rs | 53 --------------------------- src/liballoc/lib.rs | 2 +- src/liballoc/rc.rs | 46 ++++++++++------------- src/liballoc/sync.rs | 40 +++++++------------- src/liballoc/vec.rs | 21 +++++------ src/libcore/iter/traits/marker.rs | 2 + src/libcore/marker.rs | 7 ++++ 7 files changed, 51 insertions(+), 120 deletions(-) diff --git a/src/liballoc/collections/btree/map.rs b/src/liballoc/collections/btree/map.rs index 099687bd6b08..61d2295ba8c1 100644 --- a/src/liballoc/collections/btree/map.rs +++ b/src/liballoc/collections/btree/map.rs @@ -215,59 +215,6 @@ impl Clone for BTreeMap { clone_subtree(self.root.as_ref().unwrap().as_ref()) } } - - fn clone_from(&mut self, other: &Self) { - BTreeClone::clone_from(self, other); - } -} - -trait BTreeClone { - fn clone_from(&mut self, other: &Self); -} - -impl BTreeClone for BTreeMap { - default fn clone_from(&mut self, other: &Self) { - *self = other.clone(); - } -} - -impl BTreeClone for BTreeMap { - fn clone_from(&mut self, other: &Self) { - // This truncates `self` to `other.len()` by calling `split_off` on - // the first key after `other.len()` elements if it exists. - let split_off_key = if self.len() > other.len() { - let diff = self.len() - other.len(); - if diff <= other.len() { - self.iter().nth_back(diff - 1).map(|pair| (*pair.0).clone()) - } else { - self.iter().nth(other.len()).map(|pair| (*pair.0).clone()) - } - } else { - None - }; - if let Some(key) = split_off_key { - self.split_off(&key); - } - - let mut siter = self.range_mut(..); - let mut oiter = other.iter(); - // After truncation, `self` is at most as long as `other` so this loop - // replaces every key-value pair in `self`. Since `oiter` is in sorted - // order and the structure of the `BTreeMap` stays the same, - // the BTree invariants are maintained at the end of the loop. - while !siter.is_empty() { - if let Some((ok, ov)) = oiter.next() { - // SAFETY: This is safe because `siter` is nonempty. - let (sk, sv) = unsafe { siter.next_unchecked() }; - sk.clone_from(ok); - sv.clone_from(ov); - } else { - break; - } - } - // If `other` is longer than `self`, the remaining elements are inserted. - self.extend(oiter.map(|(k, v)| ((*k).clone(), (*v).clone()))); - } } impl super::Recover for BTreeMap diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs index ecec1fb039b3..3ebb5662350a 100644 --- a/src/liballoc/lib.rs +++ b/src/liballoc/lib.rs @@ -108,7 +108,7 @@ #![feature(ptr_offset_from)] #![feature(rustc_attrs)] #![feature(receiver_trait)] -#![feature(specialization)] +#![feature(min_specialization)] #![feature(staged_api)] #![feature(std_internals)] #![feature(str_internals)] diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index 2f9505ec79ff..307f6714f323 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -249,7 +249,7 @@ use core::mem::{self, align_of, align_of_val, forget, size_of_val}; use core::ops::{CoerceUnsized, Deref, DispatchFromDyn, Receiver}; use core::pin::Pin; use core::ptr::{self, NonNull}; -use core::slice::{self, from_raw_parts_mut}; +use core::slice::from_raw_parts_mut; use crate::alloc::{box_free, handle_alloc_error, AllocInit, AllocRef, Global, Layout}; use crate::string::String; @@ -1221,6 +1221,12 @@ impl RcEqIdent for Rc { } } +// Hack to allow specializing on `Eq` even though `Eq` has a method. +#[rustc_unsafe_specialization_marker] +pub(crate) trait MarkerEq: PartialEq {} + +impl MarkerEq for T {} + /// We're doing this specialization here, and not as a more general optimization on `&T`, because it /// would otherwise add a cost to all equality checks on refs. We assume that `Rc`s are used to /// store large values, that are slow to clone, but also heavy to check for equality, causing this @@ -1229,7 +1235,7 @@ impl RcEqIdent for Rc { /// /// We can only do this when `T: Eq` as a `PartialEq` might be deliberately irreflexive. #[stable(feature = "rust1", since = "1.0.0")] -impl RcEqIdent for Rc { +impl RcEqIdent for Rc { #[inline] fn eq(&self, other: &Rc) -> bool { Rc::ptr_eq(self, other) || **self == **other @@ -1548,25 +1554,25 @@ impl iter::FromIterator for Rc<[T]> { /// # assert_eq!(&*evens, &*(0..10).collect::>()); /// ``` fn from_iter>(iter: I) -> Self { - RcFromIter::from_iter(iter.into_iter()) + ToRcSlice::to_rc_slice(iter.into_iter()) } } /// Specialization trait used for collecting into `Rc<[T]>`. -trait RcFromIter { - fn from_iter(iter: I) -> Self; +trait ToRcSlice: Iterator + Sized { + fn to_rc_slice(self) -> Rc<[T]>; } -impl> RcFromIter for Rc<[T]> { - default fn from_iter(iter: I) -> Self { - iter.collect::>().into() +impl> ToRcSlice for I { + default fn to_rc_slice(self) -> Rc<[T]> { + self.collect::>().into() } } -impl> RcFromIter for Rc<[T]> { - default fn from_iter(iter: I) -> Self { +impl> ToRcSlice for I { + fn to_rc_slice(self) -> Rc<[T]> { // This is the case for a `TrustedLen` iterator. - let (low, high) = iter.size_hint(); + let (low, high) = self.size_hint(); if let Some(high) = high { debug_assert_eq!( low, @@ -1577,29 +1583,15 @@ impl> RcFromIter for Rc<[T]> { unsafe { // SAFETY: We need to ensure that the iterator has an exact length and we have. - Rc::from_iter_exact(iter, low) + Rc::from_iter_exact(self, low) } } else { // Fall back to normal implementation. - iter.collect::>().into() + self.collect::>().into() } } } -impl<'a, T: 'a + Clone> RcFromIter<&'a T, slice::Iter<'a, T>> for Rc<[T]> { - fn from_iter(iter: slice::Iter<'a, T>) -> Self { - // Delegate to `impl From<&[T]> for Rc<[T]>`. - // - // In the case that `T: Copy`, we get to use `ptr::copy_nonoverlapping` - // which is even more performant. - // - // In the fall-back case we have `T: Clone`. This is still better - // than the `TrustedLen` implementation as slices have a known length - // and so we get to avoid calling `size_hint` and avoid the branching. - iter.as_slice().into() - } -} - /// `Weak` is a version of [`Rc`] that holds a non-owning reference to the /// managed allocation. The allocation is accessed by calling [`upgrade`] on the `Weak` /// pointer, which returns an [`Option`]`<`[`Rc`]`>`. diff --git a/src/liballoc/sync.rs b/src/liballoc/sync.rs index a81e0cf7e1d2..2b71378619c0 100644 --- a/src/liballoc/sync.rs +++ b/src/liballoc/sync.rs @@ -20,7 +20,7 @@ use core::mem::{self, align_of, align_of_val, size_of_val}; use core::ops::{CoerceUnsized, Deref, DispatchFromDyn, Receiver}; use core::pin::Pin; use core::ptr::{self, NonNull}; -use core::slice::{self, from_raw_parts_mut}; +use core::slice::from_raw_parts_mut; use core::sync::atomic; use core::sync::atomic::Ordering::{Acquire, Relaxed, Release, SeqCst}; @@ -1779,7 +1779,7 @@ impl ArcEqIdent for Arc { /// /// We can only do this when `T: Eq` as a `PartialEq` might be deliberately irreflexive. #[stable(feature = "rust1", since = "1.0.0")] -impl ArcEqIdent for Arc { +impl ArcEqIdent for Arc { #[inline] fn eq(&self, other: &Arc) -> bool { Arc::ptr_eq(self, other) || **self == **other @@ -2105,25 +2105,25 @@ impl iter::FromIterator for Arc<[T]> { /// # assert_eq!(&*evens, &*(0..10).collect::>()); /// ``` fn from_iter>(iter: I) -> Self { - ArcFromIter::from_iter(iter.into_iter()) + ToArcSlice::to_arc_slice(iter.into_iter()) } } /// Specialization trait used for collecting into `Arc<[T]>`. -trait ArcFromIter { - fn from_iter(iter: I) -> Self; +trait ToArcSlice: Iterator + Sized { + fn to_arc_slice(self) -> Arc<[T]>; } -impl> ArcFromIter for Arc<[T]> { - default fn from_iter(iter: I) -> Self { - iter.collect::>().into() +impl> ToArcSlice for I { + default fn to_arc_slice(self) -> Arc<[T]> { + self.collect::>().into() } } -impl> ArcFromIter for Arc<[T]> { - default fn from_iter(iter: I) -> Self { +impl> ToArcSlice for I { + fn to_arc_slice(self) -> Arc<[T]> { // This is the case for a `TrustedLen` iterator. - let (low, high) = iter.size_hint(); + let (low, high) = self.size_hint(); if let Some(high) = high { debug_assert_eq!( low, @@ -2134,29 +2134,15 @@ impl> ArcFromIter for Arc<[T]> { unsafe { // SAFETY: We need to ensure that the iterator has an exact length and we have. - Arc::from_iter_exact(iter, low) + Arc::from_iter_exact(self, low) } } else { // Fall back to normal implementation. - iter.collect::>().into() + self.collect::>().into() } } } -impl<'a, T: 'a + Clone> ArcFromIter<&'a T, slice::Iter<'a, T>> for Arc<[T]> { - fn from_iter(iter: slice::Iter<'a, T>) -> Self { - // Delegate to `impl From<&[T]> for Arc<[T]>`. - // - // In the case that `T: Copy`, we get to use `ptr::copy_nonoverlapping` - // which is even more performant. - // - // In the fall-back case we have `T: Clone`. This is still better - // than the `TrustedLen` implementation as slices have a known length - // and so we get to avoid calling `size_hint` and avoid the branching. - iter.as_slice().into() - } -} - #[stable(feature = "rust1", since = "1.0.0")] impl borrow::Borrow for Arc { fn borrow(&self) -> &T { diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs index b4a9da847876..624ca2820d75 100644 --- a/src/liballoc/vec.rs +++ b/src/liballoc/vec.rs @@ -1619,8 +1619,8 @@ impl Vec { #[unstable(feature = "vec_resize_default", issue = "41758")] #[rustc_deprecated( reason = "This is moving towards being removed in favor \ - of `.resize_with(Default::default)`. If you disagree, please comment \ - in the tracking issue.", + of `.resize_with(Default::default)`. If you disagree, please comment \ + in the tracking issue.", since = "1.33.0" )] pub fn resize_default(&mut self, new_len: usize) { @@ -1825,6 +1825,7 @@ impl SpecFromElem for T { } } +#[rustc_specialization_trait] unsafe trait IsZero { /// Whether this value is zero fn is_zero(&self) -> bool; @@ -1874,9 +1875,12 @@ unsafe impl IsZero for *mut T { } } -// `Option<&T>`, `Option<&mut T>` and `Option>` are guaranteed to represent `None` as null. -// For fat pointers, the bytes that would be the pointer metadata in the `Some` variant -// are padding in the `None` variant, so ignoring them and zero-initializing instead is ok. +// `Option<&T>` and `Option>` are guaranteed to represent `None` as null. +// For fat pointers, the bytes that would be the pointer metadata in the `Some` +// variant are padding in the `None` variant, so ignoring them and +// zero-initializing instead is ok. +// `Option<&mut T>` never implements `Clone`, so there's no need for an impl of +// `SpecFromElem`. unsafe impl IsZero for Option<&T> { #[inline] @@ -1885,13 +1889,6 @@ unsafe impl IsZero for Option<&T> { } } -unsafe impl IsZero for Option<&mut T> { - #[inline] - fn is_zero(&self) -> bool { - self.is_none() - } -} - unsafe impl IsZero for Option> { #[inline] fn is_zero(&self) -> bool { diff --git a/src/libcore/iter/traits/marker.rs b/src/libcore/iter/traits/marker.rs index 404cc84495c9..a9ba3908c389 100644 --- a/src/libcore/iter/traits/marker.rs +++ b/src/libcore/iter/traits/marker.rs @@ -13,6 +13,7 @@ /// [`Iterator::fuse`]: ../../std/iter/trait.Iterator.html#method.fuse /// [`Fuse`]: ../../std/iter/struct.Fuse.html #[stable(feature = "fused", since = "1.26.0")] +#[rustc_unsafe_specialization_marker] pub trait FusedIterator: Iterator {} #[stable(feature = "fused", since = "1.26.0")] @@ -38,6 +39,7 @@ impl FusedIterator for &mut I {} /// [`usize::MAX`]: ../../std/usize/constant.MAX.html /// [`.size_hint`]: ../../std/iter/trait.Iterator.html#method.size_hint #[unstable(feature = "trusted_len", issue = "37572")] +#[rustc_unsafe_specialization_marker] pub unsafe trait TrustedLen: Iterator {} #[unstable(feature = "trusted_len", issue = "37572")] diff --git a/src/libcore/marker.rs b/src/libcore/marker.rs index 09a8b417e6e2..339b07119c6d 100644 --- a/src/libcore/marker.rs +++ b/src/libcore/marker.rs @@ -363,6 +363,13 @@ pub trait StructuralEq { /// [impls]: #implementors #[stable(feature = "rust1", since = "1.0.0")] #[lang = "copy"] +// FIXME(matthewjasper) This allows copying a type that doesn't implement +// `Copy` because of unsatisfied lifetime bounds (copying `A<'_>` when only +// `A<'static>: Copy` and `A<'_>: Clone`). +// We have this attribute here for now only because there are quite a few +// existing specializations on `Copy` that already exist in the standard +// library, and there's no way to safely have this behavior right now. +#[rustc_unsafe_specialization_marker] pub trait Copy: Clone { // Empty. } From ad9ad6f402e3e15706519e59ef111a941d28d5af Mon Sep 17 00:00:00 2001 From: rail <12975677+rail-rain@users.noreply.github.com> Date: Mon, 27 Apr 2020 17:42:57 +1200 Subject: [PATCH 007/203] Don't negate resulted offsets when `offset` is subtraction by 0 --- clippy_lints/src/loops.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index cb44eccae684..f16b98883b80 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -960,8 +960,8 @@ fn detect_manual_memcpy<'a, 'tcx>( let print_sum = |arg1: &Offset, arg2: &Offset| -> String { match (&arg1.value[..], arg1.negate, &arg2.value[..], arg2.negate) { ("0", _, "0", _) => "".into(), - ("0", _, x, false) | (x, false, "0", false) => x.into(), - ("0", _, x, true) | (x, false, "0", true) => format!("-{}", x), + ("0", _, x, false) | (x, false, "0", _) => x.into(), + ("0", _, x, true) => format!("-{}", x), (x, false, y, false) => format!("({} + {})", x, y), (x, false, y, true) => { if x == y { From 37261a904ce2fbd4137180500c57f75f29945828 Mon Sep 17 00:00:00 2001 From: rail <12975677+rail-rain@users.noreply.github.com> Date: Mon, 27 Apr 2020 17:51:01 +1200 Subject: [PATCH 008/203] Print 0 when `end` and `offset` is 0, and also simplify the suggestion --- clippy_lints/src/loops.rs | 15 ++++++++++++--- tests/ui/manual_memcpy.stderr | 4 ++-- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index f16b98883b80..6b5a8498dc92 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -959,7 +959,7 @@ fn detect_manual_memcpy<'a, 'tcx>( if let PatKind::Binding(_, canonical_id, _, _) = pat.kind { let print_sum = |arg1: &Offset, arg2: &Offset| -> String { match (&arg1.value[..], arg1.negate, &arg2.value[..], arg2.negate) { - ("0", _, "0", _) => "".into(), + ("0", _, "0", _) => "0".into(), ("0", _, x, false) | (x, false, "0", _) => x.into(), ("0", _, x, true) => format!("-{}", x), (x, false, y, false) => format!("({} + {})", x, y), @@ -981,6 +981,15 @@ fn detect_manual_memcpy<'a, 'tcx>( } }; + let print_offset = |start_str: &Offset, inline_offset: &Offset| -> String { + let offset = print_sum(start_str, inline_offset); + if offset.as_str() == "0" { + "".into() + } else { + offset + } + }; + let print_limit = |end: &Option<&Expr<'_>>, offset: Offset, var_name: &str| { if let Some(end) = *end { if_chain! { @@ -1020,9 +1029,9 @@ fn detect_manual_memcpy<'a, 'tcx>( .into_iter() .map(|(dst_var, src_var)| { let start_str = Offset::positive(snippet(cx, start.span, "").to_string()); - let dst_offset = print_sum(&start_str, &dst_var.offset); + let dst_offset = print_offset(&start_str, &dst_var.offset); let dst_limit = print_limit(end, dst_var.offset, &dst_var.var_name); - let src_offset = print_sum(&start_str, &src_var.offset); + let src_offset = print_offset(&start_str, &src_var.offset); let src_limit = print_limit(end, src_var.offset, &src_var.var_name); let dst = if dst_offset == "" && dst_limit == "" { dst_var.var_name diff --git a/tests/ui/manual_memcpy.stderr b/tests/ui/manual_memcpy.stderr index 3dbb2155d4de..ec80f6070d62 100644 --- a/tests/ui/manual_memcpy.stderr +++ b/tests/ui/manual_memcpy.stderr @@ -58,13 +58,13 @@ error: it looks like you're manually copying between slices --> $DIR/manual_memcpy.rs:94:14 | LL | for i in from..from + src.len() { - | ^^^^^^^^^^^^^^^^^^^^^^ help: try replacing the loop by: `dst[from..from + src.len()].clone_from_slice(&src[0..(from + src.len() - from)])` + | ^^^^^^^^^^^^^^^^^^^^^^ help: try replacing the loop by: `dst[from..from + src.len()].clone_from_slice(&src[..(from + src.len() - from)])` error: it looks like you're manually copying between slices --> $DIR/manual_memcpy.rs:98:14 | LL | for i in from..from + 3 { - | ^^^^^^^^^^^^^^ help: try replacing the loop by: `dst[from..from + 3].clone_from_slice(&src[0..(from + 3 - from)])` + | ^^^^^^^^^^^^^^ help: try replacing the loop by: `dst[from..from + 3].clone_from_slice(&src[..(from + 3 - from)])` error: it looks like you're manually copying between slices --> $DIR/manual_memcpy.rs:105:14 From 75ad839cd26c1da17fe6ba3aae1153ee96de26c8 Mon Sep 17 00:00:00 2001 From: rail <12975677+rail-rain@users.noreply.github.com> Date: Mon, 27 Apr 2020 18:04:37 +1200 Subject: [PATCH 009/203] Do not trigger `manual_memcpy` for `RangeTo` --- clippy_lints/src/loops.rs | 52 ++++++++++++++++------------------- tests/ui/manual_memcpy.rs | 5 ++++ tests/ui/manual_memcpy.stderr | 2 +- 3 files changed, 30 insertions(+), 29 deletions(-) diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 6b5a8498dc92..ca61c97e3e3f 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -951,7 +951,7 @@ fn detect_manual_memcpy<'a, 'tcx>( ) { if let Some(higher::Range { start: Some(start), - ref end, + end: Some(end), limits, }) = higher::range(cx, arg) { @@ -990,35 +990,31 @@ fn detect_manual_memcpy<'a, 'tcx>( } }; - let print_limit = |end: &Option<&Expr<'_>>, offset: Offset, var_name: &str| { - if let Some(end) = *end { - if_chain! { - if let ExprKind::MethodCall(ref method, _, ref len_args) = end.kind; - if method.ident.name == sym!(len); - if len_args.len() == 1; - if let Some(arg) = len_args.get(0); - if snippet(cx, arg.span, "??") == var_name; - then { - return if offset.negate { - format!("({} - {})", snippet(cx, end.span, ".len()"), offset.value) - } else { - String::new() - }; - } + let print_limit = |end: &Expr<'_>, offset: Offset, var_name: &str| { + if_chain! { + if let ExprKind::MethodCall(ref method, _, ref len_args) = end.kind; + if method.ident.name == sym!(len); + if len_args.len() == 1; + if let Some(arg) = len_args.get(0); + if snippet(cx, arg.span, "??") == var_name; + then { + return if offset.negate { + format!("({} - {})", snippet(cx, end.span, ".len()"), offset.value) + } else { + String::new() + }; } - - let end_str = match limits { - ast::RangeLimits::Closed => { - let end = sugg::Sugg::hir(cx, end, ""); - format!("{}", end + sugg::ONE) - }, - ast::RangeLimits::HalfOpen => format!("{}", snippet(cx, end.span, "..")), - }; - - print_sum(&Offset::positive(end_str), &offset) - } else { - "..".into() } + + let end_str = match limits { + ast::RangeLimits::Closed => { + let end = sugg::Sugg::hir(cx, end, ""); + format!("{}", end + sugg::ONE) + }, + ast::RangeLimits::HalfOpen => format!("{}", snippet(cx, end.span, "..")), + }; + + print_sum(&Offset::positive(end_str), &offset) }; // The only statements in the for loops can be indexed assignments from diff --git a/tests/ui/manual_memcpy.rs b/tests/ui/manual_memcpy.rs index aa347288875d..1f41838fa169 100644 --- a/tests/ui/manual_memcpy.rs +++ b/tests/ui/manual_memcpy.rs @@ -98,6 +98,11 @@ pub fn manual_copy(src: &[i32], dst: &mut [i32], dst2: &mut [i32]) { for i in from..from + 3 { dst[i] = src[i - from]; } + + // `RangeTo` `for` loop - don't trigger lint + for i in 0.. { + dst[i] = src[i]; + } } #[warn(clippy::needless_range_loop, clippy::manual_memcpy)] diff --git a/tests/ui/manual_memcpy.stderr b/tests/ui/manual_memcpy.stderr index ec80f6070d62..95114c46f368 100644 --- a/tests/ui/manual_memcpy.stderr +++ b/tests/ui/manual_memcpy.stderr @@ -67,7 +67,7 @@ LL | for i in from..from + 3 { | ^^^^^^^^^^^^^^ help: try replacing the loop by: `dst[from..from + 3].clone_from_slice(&src[..(from + 3 - from)])` error: it looks like you're manually copying between slices - --> $DIR/manual_memcpy.rs:105:14 + --> $DIR/manual_memcpy.rs:110:14 | LL | for i in 0..src.len() { | ^^^^^^^^^^^^ help: try replacing the loop by: `dst[..src.len()].clone_from_slice(&src[..])` From c94f0f49f8e025aae11534f9f2b4c59c34b1edb8 Mon Sep 17 00:00:00 2001 From: rail <12975677+rail-rain@users.noreply.github.com> Date: Mon, 27 Apr 2020 18:22:10 +1200 Subject: [PATCH 010/203] Remove all `ref` keyword --- clippy_lints/src/loops.rs | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index ca61c97e3e3f..502bd42214ee 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -772,8 +772,8 @@ fn check_for_loop<'a, 'tcx>( fn same_var<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &Expr<'_>, var: HirId) -> bool { if_chain! { - if let ExprKind::Path(ref qpath) = expr.kind; - if let QPath::Resolved(None, ref path) = *qpath; + if let ExprKind::Path(qpath) = &expr.kind; + if let QPath::Resolved(None, path) = qpath; if path.segments.len() == 1; if let Res::Local(local_id) = qpath_res(cx, qpath, expr.hir_id); // our variable! @@ -821,8 +821,8 @@ fn is_slice_like<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: Ty<'_>) -> bool { fn get_fixed_offset_var<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &Expr<'_>, var: HirId) -> Option { fn extract_offset<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, e: &Expr<'_>, var: HirId) -> Option { - match e.kind { - ExprKind::Lit(ref l) => match l.node { + match &e.kind { + ExprKind::Lit(l) => match l.node { ast::LitKind::Int(x, _ty) => Some(x.to_string()), _ => None, }, @@ -831,14 +831,14 @@ fn get_fixed_offset_var<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &Expr<'_>, v } } - if let ExprKind::Index(ref seqexpr, ref idx) = expr.kind { + if let ExprKind::Index(seqexpr, idx) = expr.kind { let ty = cx.tables.expr_ty(seqexpr); if !is_slice_like(cx, ty) { return None; } let offset = match idx.kind { - ExprKind::Binary(op, ref lhs, ref rhs) => match op.node { + ExprKind::Binary(op, lhs, rhs) => match op.node { BinOpKind::Add => { let offset_opt = if same_var(cx, lhs, var) { extract_offset(cx, rhs, var) @@ -878,7 +878,7 @@ fn fetch_cloned_fixed_offset_var<'a, 'tcx>( var: HirId, ) -> Option { if_chain! { - if let ExprKind::MethodCall(ref method, _, ref args) = expr.kind; + if let ExprKind::MethodCall(method, _, args) = expr.kind; if method.ident.name == sym!(clone); if args.len() == 1; if let Some(arg) = args.get(0); @@ -900,7 +900,7 @@ fn get_indexed_assignments<'a, 'tcx>( e: &Expr<'_>, var: HirId, ) -> Option<(FixedOffsetVar, FixedOffsetVar)> { - if let ExprKind::Assign(ref lhs, ref rhs, _) = e.kind { + if let ExprKind::Assign(lhs, rhs, _) = e.kind { match ( get_fixed_offset_var(cx, lhs, var), fetch_cloned_fixed_offset_var(cx, rhs, var), @@ -920,16 +920,14 @@ fn get_indexed_assignments<'a, 'tcx>( } } - if let ExprKind::Block(ref b, _) = body.kind { - let Block { - ref stmts, ref expr, .. - } = **b; + if let ExprKind::Block(b, _) = body.kind { + let Block { stmts, expr, .. } = *b; stmts .iter() .map(|stmt| match stmt.kind { StmtKind::Local(..) | StmtKind::Item(..) => None, - StmtKind::Expr(ref e) | StmtKind::Semi(ref e) => Some(get_assignment(cx, e, var)), + StmtKind::Expr(e) | StmtKind::Semi(e) => Some(get_assignment(cx, e, var)), }) .chain(expr.as_ref().into_iter().map(|e| Some(get_assignment(cx, &*e, var)))) .filter_map(|op| op) @@ -992,7 +990,7 @@ fn detect_manual_memcpy<'a, 'tcx>( let print_limit = |end: &Expr<'_>, offset: Offset, var_name: &str| { if_chain! { - if let ExprKind::MethodCall(ref method, _, ref len_args) = end.kind; + if let ExprKind::MethodCall(method, _, len_args) = end.kind; if method.ident.name == sym!(len); if len_args.len() == 1; if let Some(arg) = len_args.get(0); From 7dd0f3459f558c1b557223a042f549b378cacae9 Mon Sep 17 00:00:00 2001 From: rail <12975677+rail-rain@users.noreply.github.com> Date: Mon, 27 Apr 2020 18:47:24 +1200 Subject: [PATCH 011/203] Refactor `if` to use `else` and iterator combinators --- clippy_lints/src/loops.rs | 50 +++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 28 deletions(-) diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 502bd42214ee..3dd3a79b2873 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -779,11 +779,11 @@ fn same_var<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &Expr<'_>, var: HirId) - // our variable! if local_id == var; then { - return true; + true + } else { + false } } - - false } struct Offset { @@ -853,13 +853,7 @@ fn get_fixed_offset_var<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &Expr<'_>, v BinOpKind::Sub if same_var(cx, lhs, var) => extract_offset(cx, rhs, var).map(Offset::negative), _ => None, }, - ExprKind::Path(..) => { - if same_var(cx, idx, var) { - Some(Offset::positive("0".into())) - } else { - None - } - }, + ExprKind::Path(..) if same_var(cx, idx, var) => Some(Offset::positive("0".into())), _ => None, }; @@ -883,11 +877,11 @@ fn fetch_cloned_fixed_offset_var<'a, 'tcx>( if args.len() == 1; if let Some(arg) = args.get(0); then { - return get_fixed_offset_var(cx, arg, var); + get_fixed_offset_var(cx, arg, var) + } else { + get_fixed_offset_var(cx, expr, var) } } - - get_fixed_offset_var(cx, expr, var) } fn get_indexed_assignments<'a, 'tcx>( @@ -925,12 +919,12 @@ fn get_indexed_assignments<'a, 'tcx>( stmts .iter() - .map(|stmt| match stmt.kind { + .filter_map(|stmt| match stmt.kind { StmtKind::Local(..) | StmtKind::Item(..) => None, - StmtKind::Expr(e) | StmtKind::Semi(e) => Some(get_assignment(cx, e, var)), + StmtKind::Expr(e) | StmtKind::Semi(e) => Some(e), }) - .chain(expr.as_ref().into_iter().map(|e| Some(get_assignment(cx, &*e, var)))) - .filter_map(|op| op) + .chain(expr.into_iter()) + .map(|op| get_assignment(cx, op, var)) .collect::>>() .unwrap_or_default() } else { @@ -996,23 +990,23 @@ fn detect_manual_memcpy<'a, 'tcx>( if let Some(arg) = len_args.get(0); if snippet(cx, arg.span, "??") == var_name; then { - return if offset.negate { + if offset.negate { format!("({} - {})", snippet(cx, end.span, ".len()"), offset.value) } else { String::new() + } + } else { + let end_str = match limits { + ast::RangeLimits::Closed => { + let end = sugg::Sugg::hir(cx, end, ""); + format!("{}", end + sugg::ONE) + }, + ast::RangeLimits::HalfOpen => format!("{}", snippet(cx, end.span, "..")), }; + + print_sum(&Offset::positive(end_str), &offset) } } - - let end_str = match limits { - ast::RangeLimits::Closed => { - let end = sugg::Sugg::hir(cx, end, ""); - format!("{}", end + sugg::ONE) - }, - ast::RangeLimits::HalfOpen => format!("{}", snippet(cx, end.span, "..")), - }; - - print_sum(&Offset::positive(end_str), &offset) }; // The only statements in the for loops can be indexed assignments from From 3f1e51b3f4a7bfb42c442caf2cb836ba62e2ba53 Mon Sep 17 00:00:00 2001 From: rail <12975677+rail-rain@users.noreply.github.com> Date: Mon, 27 Apr 2020 18:57:36 +1200 Subject: [PATCH 012/203] Rename `negate` to `sign` and make it strong types then make `art1` &str --- clippy_lints/src/loops.rs | 56 +++++++++++++++++++-------------------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 3dd3a79b2873..321d5265d0c2 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -786,20 +786,29 @@ fn same_var<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &Expr<'_>, var: HirId) - } } +#[derive(Clone, Copy)] +enum OffsetSign { + Positive, + Negative, +} + struct Offset { value: String, - negate: bool, + sign: OffsetSign, } impl Offset { - fn negative(s: String) -> Self { - Self { value: s, negate: true } + fn negative(value: String) -> Self { + Self { + value, + sign: OffsetSign::Negative, + } } - fn positive(s: String) -> Self { + fn positive(value: String) -> Self { Self { - value: s, - negate: false, + value, + sign: OffsetSign::Positive, } } } @@ -949,31 +958,23 @@ fn detect_manual_memcpy<'a, 'tcx>( { // the var must be a single name if let PatKind::Binding(_, canonical_id, _, _) = pat.kind { - let print_sum = |arg1: &Offset, arg2: &Offset| -> String { - match (&arg1.value[..], arg1.negate, &arg2.value[..], arg2.negate) { - ("0", _, "0", _) => "0".into(), - ("0", _, x, false) | (x, false, "0", _) => x.into(), - ("0", _, x, true) => format!("-{}", x), - (x, false, y, false) => format!("({} + {})", x, y), - (x, false, y, true) => { + let print_sum = |arg1: &str, arg2: &Offset| -> String { + match (arg1, &arg2.value[..], arg2.sign) { + ("0", "0", _) => "0".into(), + ("0", x, OffsetSign::Positive) | (x, "0", _) => x.into(), + ("0", x, OffsetSign::Negative) => format!("-{}", x), + (x, y, OffsetSign::Positive) => format!("({} + {})", x, y), + (x, y, OffsetSign::Negative) => { if x == y { "0".into() } else { format!("({} - {})", x, y) } }, - (x, true, y, false) => { - if x == y { - "0".into() - } else { - format!("({} - {})", y, x) - } - }, - (x, true, y, true) => format!("-({} + {})", x, y), } }; - let print_offset = |start_str: &Offset, inline_offset: &Offset| -> String { + let print_offset = |start_str: &str, inline_offset: &Offset| -> String { let offset = print_sum(start_str, inline_offset); if offset.as_str() == "0" { "".into() @@ -990,10 +991,9 @@ fn detect_manual_memcpy<'a, 'tcx>( if let Some(arg) = len_args.get(0); if snippet(cx, arg.span, "??") == var_name; then { - if offset.negate { - format!("({} - {})", snippet(cx, end.span, ".len()"), offset.value) - } else { - String::new() + match offset.sign { + OffsetSign::Negative => format!("({} - {})", snippet(cx, end.span, ".len()"), offset.value), + OffsetSign::Positive => "".into(), } } else { let end_str = match limits { @@ -1004,7 +1004,7 @@ fn detect_manual_memcpy<'a, 'tcx>( ast::RangeLimits::HalfOpen => format!("{}", snippet(cx, end.span, "..")), }; - print_sum(&Offset::positive(end_str), &offset) + print_sum(&end_str, &offset) } } }; @@ -1016,7 +1016,7 @@ fn detect_manual_memcpy<'a, 'tcx>( let big_sugg = manual_copies .into_iter() .map(|(dst_var, src_var)| { - let start_str = Offset::positive(snippet(cx, start.span, "").to_string()); + let start_str = snippet(cx, start.span, "").to_string(); let dst_offset = print_offset(&start_str, &dst_var.offset); let dst_limit = print_limit(end, dst_var.offset, &dst_var.var_name); let src_offset = print_offset(&start_str, &src_var.offset); From ecb472c052c746d87ce26f6b184f2c5f11537e0c Mon Sep 17 00:00:00 2001 From: rail <12975677+rail-rain@users.noreply.github.com> Date: Mon, 27 Apr 2020 19:02:08 +1200 Subject: [PATCH 013/203] Use `fn` instead of closures where unnecessary --- clippy_lints/src/loops.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 321d5265d0c2..e37c44dc026a 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -958,7 +958,7 @@ fn detect_manual_memcpy<'a, 'tcx>( { // the var must be a single name if let PatKind::Binding(_, canonical_id, _, _) = pat.kind { - let print_sum = |arg1: &str, arg2: &Offset| -> String { + fn print_sum(arg1: &str, arg2: &Offset) -> String { match (arg1, &arg2.value[..], arg2.sign) { ("0", "0", _) => "0".into(), ("0", x, OffsetSign::Positive) | (x, "0", _) => x.into(), @@ -972,16 +972,16 @@ fn detect_manual_memcpy<'a, 'tcx>( } }, } - }; + } - let print_offset = |start_str: &str, inline_offset: &Offset| -> String { + fn print_offset(start_str: &str, inline_offset: &Offset) -> String { let offset = print_sum(start_str, inline_offset); if offset.as_str() == "0" { "".into() } else { offset } - }; + } let print_limit = |end: &Expr<'_>, offset: Offset, var_name: &str| { if_chain! { From aab80eedf3e271ada92a6509727461cc3aa6bb12 Mon Sep 17 00:00:00 2001 From: rail <12975677+rail-rain@users.noreply.github.com> Date: Mon, 27 Apr 2020 19:04:56 +1200 Subject: [PATCH 014/203] Extract `get_fixed_offset_var`` from `fetch_cloned_fixed_offset_var` --- clippy_lints/src/loops.rs | 30 +++++++++++------------------- 1 file changed, 11 insertions(+), 19 deletions(-) diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index e37c44dc026a..2dc95f53078e 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -828,6 +828,16 @@ fn is_slice_like<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: Ty<'_>) -> bool { is_slice || is_type_diagnostic_item(cx, ty, sym!(vec_type)) || is_type_diagnostic_item(cx, ty, sym!(vecdeque_type)) } +fn fetch_cloned_expr<'tcx>(expr: &'tcx Expr<'tcx>) -> &'tcx Expr<'tcx> { + if_chain! { + if let ExprKind::MethodCall(method, _, args) = expr.kind; + if method.ident.name == sym!(clone); + if args.len() == 1; + if let Some(arg) = args.get(0); + then { arg } else { expr } + } +} + fn get_fixed_offset_var<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &Expr<'_>, var: HirId) -> Option { fn extract_offset<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, e: &Expr<'_>, var: HirId) -> Option { match &e.kind { @@ -875,24 +885,6 @@ fn get_fixed_offset_var<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &Expr<'_>, v } } -fn fetch_cloned_fixed_offset_var<'a, 'tcx>( - cx: &LateContext<'a, 'tcx>, - expr: &Expr<'_>, - var: HirId, -) -> Option { - if_chain! { - if let ExprKind::MethodCall(method, _, args) = expr.kind; - if method.ident.name == sym!(clone); - if args.len() == 1; - if let Some(arg) = args.get(0); - then { - get_fixed_offset_var(cx, arg, var) - } else { - get_fixed_offset_var(cx, expr, var) - } - } -} - fn get_indexed_assignments<'a, 'tcx>( cx: &LateContext<'a, 'tcx>, body: &Expr<'_>, @@ -906,7 +898,7 @@ fn get_indexed_assignments<'a, 'tcx>( if let ExprKind::Assign(lhs, rhs, _) = e.kind { match ( get_fixed_offset_var(cx, lhs, var), - fetch_cloned_fixed_offset_var(cx, rhs, var), + get_fixed_offset_var(cx, fetch_cloned_expr(rhs), var), ) { (Some(offset_left), Some(offset_right)) => { // Source and destination must be different From 3d121d53af9a73ba11226715cd8132f6981ffee9 Mon Sep 17 00:00:00 2001 From: rail <12975677+rail-rain@users.noreply.github.com> Date: Mon, 27 Apr 2020 19:15:51 +1200 Subject: [PATCH 015/203] Extract roles getting indexes from `get_indexed_assignments` --- clippy_lints/src/loops.rs | 106 ++++++++++++++++++++------------------ 1 file changed, 55 insertions(+), 51 deletions(-) diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 2dc95f53078e..0753b23e45b3 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -10,7 +10,6 @@ use crate::utils::{ }; use crate::utils::{is_type_diagnostic_item, qpath_res, same_tys, sext, sugg}; use if_chain::if_chain; -use itertools::Itertools; use rustc_ast::ast; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_errors::Applicability; @@ -885,52 +884,39 @@ fn get_fixed_offset_var<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &Expr<'_>, v } } -fn get_indexed_assignments<'a, 'tcx>( - cx: &LateContext<'a, 'tcx>, - body: &Expr<'_>, - var: HirId, -) -> Vec<(FixedOffsetVar, FixedOffsetVar)> { - fn get_assignment<'a, 'tcx>( - cx: &LateContext<'a, 'tcx>, - e: &Expr<'_>, - var: HirId, - ) -> Option<(FixedOffsetVar, FixedOffsetVar)> { +fn get_assignments<'a, 'tcx>( + body: &'tcx Expr<'tcx>, +) -> impl Iterator, &'tcx Expr<'tcx>)>> { + fn get_assignment<'a, 'tcx>(e: &'tcx Expr<'tcx>) -> Option<(&'tcx Expr<'tcx>, &'tcx Expr<'tcx>)> { if let ExprKind::Assign(lhs, rhs, _) = e.kind { - match ( - get_fixed_offset_var(cx, lhs, var), - get_fixed_offset_var(cx, fetch_cloned_expr(rhs), var), - ) { - (Some(offset_left), Some(offset_right)) => { - // Source and destination must be different - if offset_left.var_name == offset_right.var_name { - None - } else { - Some((offset_left, offset_right)) - } - }, - _ => None, - } + Some((lhs, rhs)) } else { None } } + // This is one of few ways to return different iterators + // derived from: https://stackoverflow.com/questions/29760668/conditionally-iterate-over-one-of-several-possible-iterators/52064434#52064434 + let mut iter_a = None; + let mut iter_b = None; + if let ExprKind::Block(b, _) = body.kind { let Block { stmts, expr, .. } = *b; - stmts + iter_a = stmts .iter() .filter_map(|stmt| match stmt.kind { StmtKind::Local(..) | StmtKind::Item(..) => None, StmtKind::Expr(e) | StmtKind::Semi(e) => Some(e), }) .chain(expr.into_iter()) - .map(|op| get_assignment(cx, op, var)) - .collect::>>() - .unwrap_or_default() + .map(get_assignment) + .into() } else { - get_assignment(cx, body, var).into_iter().collect() + iter_b = Some(get_assignment(body)) } + + iter_a.into_iter().flatten().chain(iter_b.into_iter()) } /// Checks for for loops that sequentially copy items from one slice-like @@ -1003,30 +989,48 @@ fn detect_manual_memcpy<'a, 'tcx>( // The only statements in the for loops can be indexed assignments from // indexed retrievals. - let manual_copies = get_indexed_assignments(cx, body, canonical_id); + let big_sugg = get_assignments(body) + .map(|o| { + o.and_then(|(lhs, rhs)| { + let rhs = fetch_cloned_expr(rhs); + if_chain! { + if let Some(offset_left) = get_fixed_offset_var(cx, lhs, canonical_id); + if let Some(offset_right) = get_fixed_offset_var(cx, rhs, canonical_id); - let big_sugg = manual_copies - .into_iter() - .map(|(dst_var, src_var)| { - let start_str = snippet(cx, start.span, "").to_string(); - let dst_offset = print_offset(&start_str, &dst_var.offset); - let dst_limit = print_limit(end, dst_var.offset, &dst_var.var_name); - let src_offset = print_offset(&start_str, &src_var.offset); - let src_limit = print_limit(end, src_var.offset, &src_var.var_name); - let dst = if dst_offset == "" && dst_limit == "" { - dst_var.var_name - } else { - format!("{}[{}..{}]", dst_var.var_name, dst_offset, dst_limit) - }; - - format!( - "{}.clone_from_slice(&{}[{}..{}])", - dst, src_var.var_name, src_offset, src_limit - ) + // Source and destination must be different + if offset_left.var_name != offset_right.var_name; + then { + Some((offset_left, offset_right)) + } else { + return None + } + } + }) }) - .join("\n "); + .map(|o| { + o.map(|(dst_var, src_var)| { + let start_str = snippet(cx, start.span, "").to_string(); + let dst_offset = print_offset(&start_str, &dst_var.offset); + let dst_limit = print_limit(end, dst_var.offset, &dst_var.var_name); + let src_offset = print_offset(&start_str, &src_var.offset); + let src_limit = print_limit(end, src_var.offset, &src_var.var_name); + let dst = if dst_offset == "" && dst_limit == "" { + dst_var.var_name + } else { + format!("{}[{}..{}]", dst_var.var_name, dst_offset, dst_limit) + }; - if !big_sugg.is_empty() { + format!( + "{}.clone_from_slice(&{}[{}..{}])", + dst, src_var.var_name, src_offset, src_limit + ) + }) + }) + .collect::>>() + .filter(|v| !v.is_empty()) + .map(|v| v.join("\n ")); + + if let Some(big_sugg) = big_sugg { span_lint_and_sugg( cx, MANUAL_MEMCPY, From 4f2617c059f693ec72e5d31ad31fd85eba019ab1 Mon Sep 17 00:00:00 2001 From: rail <12975677+rail-rain@users.noreply.github.com> Date: Mon, 27 Apr 2020 19:26:00 +1200 Subject: [PATCH 016/203] Separate getting offsets and getting index expressions --- clippy_lints/src/loops.rs | 63 +++++++++++++++++---------------------- 1 file changed, 28 insertions(+), 35 deletions(-) diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 0753b23e45b3..75955997af24 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -837,7 +837,7 @@ fn fetch_cloned_expr<'tcx>(expr: &'tcx Expr<'tcx>) -> &'tcx Expr<'tcx> { } } -fn get_fixed_offset_var<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &Expr<'_>, var: HirId) -> Option { +fn get_offset<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, idx: &Expr<'_>, var: HirId) -> Option { fn extract_offset<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, e: &Expr<'_>, var: HirId) -> Option { match &e.kind { ExprKind::Lit(l) => match l.node { @@ -849,38 +849,24 @@ fn get_fixed_offset_var<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &Expr<'_>, v } } - if let ExprKind::Index(seqexpr, idx) = expr.kind { - let ty = cx.tables.expr_ty(seqexpr); - if !is_slice_like(cx, ty) { - return None; - } + match idx.kind { + ExprKind::Binary(op, lhs, rhs) => match op.node { + BinOpKind::Add => { + let offset_opt = if same_var(cx, lhs, var) { + extract_offset(cx, rhs, var) + } else if same_var(cx, rhs, var) { + extract_offset(cx, lhs, var) + } else { + None + }; - let offset = match idx.kind { - ExprKind::Binary(op, lhs, rhs) => match op.node { - BinOpKind::Add => { - let offset_opt = if same_var(cx, lhs, var) { - extract_offset(cx, rhs, var) - } else if same_var(cx, rhs, var) { - extract_offset(cx, lhs, var) - } else { - None - }; - - offset_opt.map(Offset::positive) - }, - BinOpKind::Sub if same_var(cx, lhs, var) => extract_offset(cx, rhs, var).map(Offset::negative), - _ => None, + offset_opt.map(Offset::positive) }, - ExprKind::Path(..) if same_var(cx, idx, var) => Some(Offset::positive("0".into())), + BinOpKind::Sub if same_var(cx, lhs, var) => extract_offset(cx, rhs, var).map(Offset::negative), _ => None, - }; - - offset.map(|o| FixedOffsetVar { - var_name: snippet_opt(cx, seqexpr.span).unwrap_or_else(|| "???".into()), - offset: o, - }) - } else { - None + }, + ExprKind::Path(..) if same_var(cx, idx, var) => Some(Offset::positive("0".into())), + _ => None, } } @@ -994,15 +980,22 @@ fn detect_manual_memcpy<'a, 'tcx>( o.and_then(|(lhs, rhs)| { let rhs = fetch_cloned_expr(rhs); if_chain! { - if let Some(offset_left) = get_fixed_offset_var(cx, lhs, canonical_id); - if let Some(offset_right) = get_fixed_offset_var(cx, rhs, canonical_id); + if let ExprKind::Index(seqexpr_left, idx_left) = lhs.kind; + if let ExprKind::Index(seqexpr_right, idx_right) = rhs.kind; + if is_slice_like(cx, cx.tables.expr_ty(seqexpr_left)) + && is_slice_like(cx, cx.tables.expr_ty(seqexpr_right)); + if let Some(offset_left) = get_offset(cx, &idx_left, canonical_id); + if let Some(offset_right) = get_offset(cx, &idx_right, canonical_id); + let var_name_left = snippet_opt(cx, seqexpr_left.span).unwrap_or_else(|| "???".into()); + let var_name_right = snippet_opt(cx, seqexpr_right.span).unwrap_or_else(|| "???".into()); // Source and destination must be different - if offset_left.var_name != offset_right.var_name; + if var_name_left != var_name_right; then { - Some((offset_left, offset_right)) + Some((FixedOffsetVar { var_name: var_name_left, offset: offset_left }, + FixedOffsetVar { var_name: var_name_right, offset: offset_right })) } else { - return None + None } } }) From 9fc6f37778789de94caa280f41afdf651bf5ae10 Mon Sep 17 00:00:00 2001 From: rail <12975677+rail-rain@users.noreply.github.com> Date: Mon, 27 Apr 2020 19:34:41 +1200 Subject: [PATCH 017/203] Delay getting the snippet from slices --- clippy_lints/src/loops.rs | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 75955997af24..8ab355566706 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -812,8 +812,8 @@ impl Offset { } } -struct FixedOffsetVar { - var_name: String, +struct FixedOffsetVar<'hir> { + var: &'hir Expr<'hir>, offset: Offset, } @@ -947,13 +947,13 @@ fn detect_manual_memcpy<'a, 'tcx>( } } - let print_limit = |end: &Expr<'_>, offset: Offset, var_name: &str| { + let print_limit = |end: &Expr<'_>, offset: Offset, var: &Expr<'_>| { if_chain! { if let ExprKind::MethodCall(method, _, len_args) = end.kind; if method.ident.name == sym!(len); if len_args.len() == 1; if let Some(arg) = len_args.get(0); - if snippet(cx, arg.span, "??") == var_name; + if var_def_id(cx, arg) == var_def_id(cx, var); then { match offset.sign { OffsetSign::Negative => format!("({} - {})", snippet(cx, end.span, ".len()"), offset.value), @@ -986,14 +986,12 @@ fn detect_manual_memcpy<'a, 'tcx>( && is_slice_like(cx, cx.tables.expr_ty(seqexpr_right)); if let Some(offset_left) = get_offset(cx, &idx_left, canonical_id); if let Some(offset_right) = get_offset(cx, &idx_right, canonical_id); - let var_name_left = snippet_opt(cx, seqexpr_left.span).unwrap_or_else(|| "???".into()); - let var_name_right = snippet_opt(cx, seqexpr_right.span).unwrap_or_else(|| "???".into()); // Source and destination must be different - if var_name_left != var_name_right; + if var_def_id(cx, seqexpr_left) != var_def_id(cx, seqexpr_right); then { - Some((FixedOffsetVar { var_name: var_name_left, offset: offset_left }, - FixedOffsetVar { var_name: var_name_right, offset: offset_right })) + Some((FixedOffsetVar { var: seqexpr_left, offset: offset_left }, + FixedOffsetVar { var: seqexpr_right, offset: offset_right })) } else { None } @@ -1004,18 +1002,22 @@ fn detect_manual_memcpy<'a, 'tcx>( o.map(|(dst_var, src_var)| { let start_str = snippet(cx, start.span, "").to_string(); let dst_offset = print_offset(&start_str, &dst_var.offset); - let dst_limit = print_limit(end, dst_var.offset, &dst_var.var_name); + let dst_limit = print_limit(end, dst_var.offset, dst_var.var); let src_offset = print_offset(&start_str, &src_var.offset); - let src_limit = print_limit(end, src_var.offset, &src_var.var_name); + let src_limit = print_limit(end, src_var.offset, src_var.var); + + let dst_var_name = snippet_opt(cx, dst_var.var.span).unwrap_or_else(|| "???".into()); + let src_var_name = snippet_opt(cx, src_var.var.span).unwrap_or_else(|| "???".into()); + let dst = if dst_offset == "" && dst_limit == "" { - dst_var.var_name + dst_var_name } else { - format!("{}[{}..{}]", dst_var.var_name, dst_offset, dst_limit) + format!("{}[{}..{}]", dst_var_name, dst_offset, dst_limit) }; format!( "{}.clone_from_slice(&{}[{}..{}])", - dst, src_var.var_name, src_offset, src_limit + dst, src_var_name, src_offset, src_limit ) }) }) From 582614fbbe76fed1b06feb640229b71a1886ffd7 Mon Sep 17 00:00:00 2001 From: rail <12975677+rail-rain@users.noreply.github.com> Date: Mon, 27 Apr 2020 19:44:44 +1200 Subject: [PATCH 018/203] Extract building the suggestion of `manual_memcpy` --- clippy_lints/src/loops.rs | 154 ++++++++++++++++++++------------------ 1 file changed, 80 insertions(+), 74 deletions(-) diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 8ab355566706..7cf3e16bef9b 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -905,6 +905,85 @@ fn get_assignments<'a, 'tcx>( iter_a.into_iter().flatten().chain(iter_b.into_iter()) } +fn build_manual_memcpy_suggestion<'a, 'tcx>( + cx: &LateContext<'a, 'tcx>, + start: &Expr<'_>, + end: &Expr<'_>, + limits: ast::RangeLimits, + dst_var: FixedOffsetVar<'_>, + src_var: FixedOffsetVar<'_>, +) -> String { + fn print_sum(arg1: &str, arg2: &Offset) -> String { + match (arg1, &arg2.value[..], arg2.sign) { + ("0", "0", _) => "0".into(), + ("0", x, OffsetSign::Positive) | (x, "0", _) => x.into(), + ("0", x, OffsetSign::Negative) => format!("-{}", x), + (x, y, OffsetSign::Positive) => format!("({} + {})", x, y), + (x, y, OffsetSign::Negative) => { + if x == y { + "0".into() + } else { + format!("({} - {})", x, y) + } + }, + } + } + + fn print_offset(start_str: &str, inline_offset: &Offset) -> String { + let offset = print_sum(start_str, inline_offset); + if offset.as_str() == "0" { + "".into() + } else { + offset + } + } + + let print_limit = |end: &Expr<'_>, offset: Offset, var: &Expr<'_>| { + if_chain! { + if let ExprKind::MethodCall(method, _, len_args) = end.kind; + if method.ident.name == sym!(len); + if len_args.len() == 1; + if let Some(arg) = len_args.get(0); + if var_def_id(cx, arg) == var_def_id(cx, var); + then { + match offset.sign { + OffsetSign::Negative => format!("({} - {})", snippet(cx, end.span, ".len()"), offset.value), + OffsetSign::Positive => "".into(), + } + } else { + let end_str = match limits { + ast::RangeLimits::Closed => { + let end = sugg::Sugg::hir(cx, end, ""); + format!("{}", end + sugg::ONE) + }, + ast::RangeLimits::HalfOpen => format!("{}", snippet(cx, end.span, "..")), + }; + + print_sum(&end_str, &offset) + } + } + }; + + let start_str = snippet(cx, start.span, "").to_string(); + let dst_offset = print_offset(&start_str, &dst_var.offset); + let dst_limit = print_limit(end, dst_var.offset, dst_var.var); + let src_offset = print_offset(&start_str, &src_var.offset); + let src_limit = print_limit(end, src_var.offset, src_var.var); + + let dst_var_name = snippet_opt(cx, dst_var.var.span).unwrap_or_else(|| "???".into()); + let src_var_name = snippet_opt(cx, src_var.var.span).unwrap_or_else(|| "???".into()); + + let dst = if dst_offset == "" && dst_limit == "" { + dst_var_name + } else { + format!("{}[{}..{}]", dst_var_name, dst_offset, dst_limit) + }; + + format!( + "{}.clone_from_slice(&{}[{}..{}])", + dst, src_var_name, src_offset, src_limit + ) +} /// Checks for for loops that sequentially copy items from one slice-like /// object to another. fn detect_manual_memcpy<'a, 'tcx>( @@ -922,57 +1001,6 @@ fn detect_manual_memcpy<'a, 'tcx>( { // the var must be a single name if let PatKind::Binding(_, canonical_id, _, _) = pat.kind { - fn print_sum(arg1: &str, arg2: &Offset) -> String { - match (arg1, &arg2.value[..], arg2.sign) { - ("0", "0", _) => "0".into(), - ("0", x, OffsetSign::Positive) | (x, "0", _) => x.into(), - ("0", x, OffsetSign::Negative) => format!("-{}", x), - (x, y, OffsetSign::Positive) => format!("({} + {})", x, y), - (x, y, OffsetSign::Negative) => { - if x == y { - "0".into() - } else { - format!("({} - {})", x, y) - } - }, - } - } - - fn print_offset(start_str: &str, inline_offset: &Offset) -> String { - let offset = print_sum(start_str, inline_offset); - if offset.as_str() == "0" { - "".into() - } else { - offset - } - } - - let print_limit = |end: &Expr<'_>, offset: Offset, var: &Expr<'_>| { - if_chain! { - if let ExprKind::MethodCall(method, _, len_args) = end.kind; - if method.ident.name == sym!(len); - if len_args.len() == 1; - if let Some(arg) = len_args.get(0); - if var_def_id(cx, arg) == var_def_id(cx, var); - then { - match offset.sign { - OffsetSign::Negative => format!("({} - {})", snippet(cx, end.span, ".len()"), offset.value), - OffsetSign::Positive => "".into(), - } - } else { - let end_str = match limits { - ast::RangeLimits::Closed => { - let end = sugg::Sugg::hir(cx, end, ""); - format!("{}", end + sugg::ONE) - }, - ast::RangeLimits::HalfOpen => format!("{}", snippet(cx, end.span, "..")), - }; - - print_sum(&end_str, &offset) - } - } - }; - // The only statements in the for loops can be indexed assignments from // indexed retrievals. let big_sugg = get_assignments(body) @@ -998,29 +1026,7 @@ fn detect_manual_memcpy<'a, 'tcx>( } }) }) - .map(|o| { - o.map(|(dst_var, src_var)| { - let start_str = snippet(cx, start.span, "").to_string(); - let dst_offset = print_offset(&start_str, &dst_var.offset); - let dst_limit = print_limit(end, dst_var.offset, dst_var.var); - let src_offset = print_offset(&start_str, &src_var.offset); - let src_limit = print_limit(end, src_var.offset, src_var.var); - - let dst_var_name = snippet_opt(cx, dst_var.var.span).unwrap_or_else(|| "???".into()); - let src_var_name = snippet_opt(cx, src_var.var.span).unwrap_or_else(|| "???".into()); - - let dst = if dst_offset == "" && dst_limit == "" { - dst_var_name - } else { - format!("{}[{}..{}]", dst_var_name, dst_offset, dst_limit) - }; - - format!( - "{}.clone_from_slice(&{}[{}..{}])", - dst, src_var_name, src_offset, src_limit - ) - }) - }) + .map(|o| o.map(|(dst, src)| build_manual_memcpy_suggestion(cx, start, end, limits, dst, src))) .collect::>>() .filter(|v| !v.is_empty()) .map(|v| v.join("\n ")); From 51585a129892f42eb23b0b37fea0e729f6678994 Mon Sep 17 00:00:00 2001 From: rail <12975677+rail-rain@users.noreply.github.com> Date: Mon, 27 Apr 2020 20:37:21 +1200 Subject: [PATCH 019/203] Removed unused lifetimes and a needless bool --- clippy_lints/src/loops.rs | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 7cf3e16bef9b..5f7f08979436 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -775,10 +775,9 @@ fn same_var<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &Expr<'_>, var: HirId) - if let QPath::Resolved(None, path) = qpath; if path.segments.len() == 1; if let Res::Local(local_id) = qpath_res(cx, qpath, expr.hir_id); - // our variable! - if local_id == var; then { - true + // our variable! + local_id == var } else { false } @@ -870,10 +869,8 @@ fn get_offset<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, idx: &Expr<'_>, var: HirId) } } -fn get_assignments<'a, 'tcx>( - body: &'tcx Expr<'tcx>, -) -> impl Iterator, &'tcx Expr<'tcx>)>> { - fn get_assignment<'a, 'tcx>(e: &'tcx Expr<'tcx>) -> Option<(&'tcx Expr<'tcx>, &'tcx Expr<'tcx>)> { +fn get_assignments<'tcx>(body: &'tcx Expr<'tcx>) -> impl Iterator, &'tcx Expr<'tcx>)>> { + fn get_assignment<'tcx>(e: &'tcx Expr<'tcx>) -> Option<(&'tcx Expr<'tcx>, &'tcx Expr<'tcx>)> { if let ExprKind::Assign(lhs, rhs, _) = e.kind { Some((lhs, rhs)) } else { From 1afb6e6e3b23bd5555f34cc4dcd20349dfd789de Mon Sep 17 00:00:00 2001 From: Stanislav Tkach Date: Tue, 28 Apr 2020 12:08:38 +0300 Subject: [PATCH 020/203] Extend example for the `unneeded_field_pattern` lint Current example is incorrect (or pseudo-code) because a struct name is omitted. I have used the code from the tests instead. Perhaps this example can be made less verbose, but I think it is more convenient to see a "real" code as an example. --- clippy_lints/src/misc_early.rs | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/misc_early.rs b/clippy_lints/src/misc_early.rs index adfd8dfb1c18..62ee051624b4 100644 --- a/clippy_lints/src/misc_early.rs +++ b/clippy_lints/src/misc_early.rs @@ -24,8 +24,25 @@ declare_clippy_lint! { /// **Known problems:** None. /// /// **Example:** - /// ```ignore - /// let { a: _, b: ref b, c: _ } = .. + /// ```rust + /// # struct Foo { + /// # a: i32, + /// # b: i32, + /// # c: i32, + /// # } + /// let f = Foo { a: 0, b: 0, c: 0 }; + /// + /// // Bad + /// match f { + /// Foo { a: _, b: 0, .. } => {}, + /// Foo { a: _, b: _, c: _ } => {}, + /// } + /// + /// // Good + /// match f { + /// Foo { b: 0, .. } => {}, + /// Foo { .. } => {}, + /// } /// ``` pub UNNEEDED_FIELD_PATTERN, restriction, From bdfdc71d0f56a592fd888fcd89e6e9c6188b156c Mon Sep 17 00:00:00 2001 From: Mike Hommey Date: Wed, 29 Apr 2020 18:13:52 +0900 Subject: [PATCH 021/203] Implement FromStr for OsString --- src/libstd/ffi/os_str.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/libstd/ffi/os_str.rs b/src/libstd/ffi/os_str.rs index 4fde33169733..7a05aaf71f2c 100644 --- a/src/libstd/ffi/os_str.rs +++ b/src/libstd/ffi/os_str.rs @@ -4,6 +4,7 @@ use crate::fmt; use crate::hash::{Hash, Hasher}; use crate::ops; use crate::rc::Rc; +use crate::str::FromStr; use crate::sync::Arc; use crate::sys::os_str::{Buf, Slice}; @@ -1174,6 +1175,15 @@ impl AsInner for OsStr { } } +#[stable(feature = "osstring_from_str", since = "1.45.0")] +impl FromStr for OsString { + type Err = core::convert::Infallible; + + fn from_str(s: &str) -> Result { + Ok(OsString::from(s)) + } +} + #[cfg(test)] mod tests { use super::*; From cf5e4a749c13d3a472a6aed4097df5dc90194057 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Wed, 29 Apr 2020 10:58:36 -0400 Subject: [PATCH 022/203] Add explicit references to the BuildHasher trait --- src/libstd/collections/hash/map.rs | 10 ++++++++++ src/libstd/collections/hash/set.rs | 10 ++++++++++ 2 files changed, 20 insertions(+) diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs index e6da7426eb4a..56cf9be33919 100644 --- a/src/libstd/collections/hash/map.rs +++ b/src/libstd/collections/hash/map.rs @@ -251,6 +251,9 @@ impl HashMap { /// cause many collisions and very poor performance. Setting it /// manually using this function can expose a DoS attack vector. /// + /// The `hash_builder` passed should implement the [`BuildHasher`] trait for + /// the HashMap to be useful, see its documentation for details. + /// /// # Examples /// /// ``` @@ -261,6 +264,8 @@ impl HashMap { /// let mut map = HashMap::with_hasher(s); /// map.insert(1, 2); /// ``` + /// + /// [`BuildHasher`]: ../../std/hash/trait.BuildHasher.html #[inline] #[stable(feature = "hashmap_build_hasher", since = "1.7.0")] pub fn with_hasher(hash_builder: S) -> HashMap { @@ -278,6 +283,9 @@ impl HashMap { /// cause many collisions and very poor performance. Setting it /// manually using this function can expose a DoS attack vector. /// + /// The `hash_builder` passed should implement the [`BuildHasher`] trait for + /// the HashMap to be useful, see its documentation for details. + /// /// # Examples /// /// ``` @@ -288,6 +296,8 @@ impl HashMap { /// let mut map = HashMap::with_capacity_and_hasher(10, s); /// map.insert(1, 2); /// ``` + /// + /// [`BuildHasher`]: ../../std/hash/trait.BuildHasher.html #[inline] #[stable(feature = "hashmap_build_hasher", since = "1.7.0")] pub fn with_capacity_and_hasher(capacity: usize, hash_builder: S) -> HashMap { diff --git a/src/libstd/collections/hash/set.rs b/src/libstd/collections/hash/set.rs index c1a57f2ce612..ca06457291ca 100644 --- a/src/libstd/collections/hash/set.rs +++ b/src/libstd/collections/hash/set.rs @@ -273,6 +273,9 @@ impl HashSet { /// cause many collisions and very poor performance. Setting it /// manually using this function can expose a DoS attack vector. /// + /// The `hash_builder` passed should implement the [`BuildHasher`] trait for + /// the HashMap to be useful, see its documentation for details. + /// /// # Examples /// /// ``` @@ -283,6 +286,8 @@ impl HashSet { /// let mut set = HashSet::with_hasher(s); /// set.insert(2); /// ``` + /// + /// [`BuildHasher`]: ../../std/hash/trait.BuildHasher.html #[inline] #[stable(feature = "hashmap_build_hasher", since = "1.7.0")] pub fn with_hasher(hasher: S) -> HashSet { @@ -300,6 +305,9 @@ impl HashSet { /// cause many collisions and very poor performance. Setting it /// manually using this function can expose a DoS attack vector. /// + /// The `hash_builder` passed should implement the [`BuildHasher`] trait for + /// the HashMap to be useful, see its documentation for details. + /// /// # Examples /// /// ``` @@ -310,6 +318,8 @@ impl HashSet { /// let mut set = HashSet::with_capacity_and_hasher(10, s); /// set.insert(1); /// ``` + /// + /// [`BuildHasher`]: ../../std/hash/trait.BuildHasher.html #[inline] #[stable(feature = "hashmap_build_hasher", since = "1.7.0")] pub fn with_capacity_and_hasher(capacity: usize, hasher: S) -> HashSet { From 9d8f1170b1fa923373766e26a2847390e0a2ea91 Mon Sep 17 00:00:00 2001 From: Mohsen Zohrevandi Date: Wed, 29 Apr 2020 10:36:56 -0700 Subject: [PATCH 023/203] Ignore wasm in process termination tests --- .../ui/process-termination/process-termination-blocking-io.rs | 1 + src/test/ui/process-termination/process-termination-simple.rs | 1 + 2 files changed, 2 insertions(+) diff --git a/src/test/ui/process-termination/process-termination-blocking-io.rs b/src/test/ui/process-termination/process-termination-blocking-io.rs index d9027fc89e29..864fb776e867 100644 --- a/src/test/ui/process-termination/process-termination-blocking-io.rs +++ b/src/test/ui/process-termination/process-termination-blocking-io.rs @@ -2,6 +2,7 @@ // https://github.com/fortanix/rust-sgx/issues/109 // run-pass +// ignore-wasm no threads support use std::{net::TcpListener, sync::mpsc, thread}; diff --git a/src/test/ui/process-termination/process-termination-simple.rs b/src/test/ui/process-termination/process-termination-simple.rs index 7098a34512ee..3660f95b05bc 100644 --- a/src/test/ui/process-termination/process-termination-simple.rs +++ b/src/test/ui/process-termination/process-termination-simple.rs @@ -1,6 +1,7 @@ // program should terminate when std::process::exit is called from any thread // run-pass +// ignore-wasm no threads support use std::{process, thread}; From 461f4a34660691675434a318ac4fd61a83444428 Mon Sep 17 00:00:00 2001 From: rail <12975677+rail-rain@users.noreply.github.com> Date: Thu, 30 Apr 2020 17:32:37 +1200 Subject: [PATCH 024/203] Add missing tests --- tests/ui/manual_memcpy.rs | 10 ++++++++++ tests/ui/manual_memcpy.stderr | 16 ++++++++++++++-- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/tests/ui/manual_memcpy.rs b/tests/ui/manual_memcpy.rs index 1f41838fa169..9c24d6d4db1f 100644 --- a/tests/ui/manual_memcpy.rs +++ b/tests/ui/manual_memcpy.rs @@ -99,6 +99,16 @@ pub fn manual_copy(src: &[i32], dst: &mut [i32], dst2: &mut [i32]) { dst[i] = src[i - from]; } + #[allow(clippy::identity_op)] + for i in 0..5 { + dst[i - 0] = src[i]; + } + + #[allow(clippy::reverse_range_loop)] + for i in 0..0 { + dst[i] = src[i]; + } + // `RangeTo` `for` loop - don't trigger lint for i in 0.. { dst[i] = src[i]; diff --git a/tests/ui/manual_memcpy.stderr b/tests/ui/manual_memcpy.stderr index 95114c46f368..bad84a589008 100644 --- a/tests/ui/manual_memcpy.stderr +++ b/tests/ui/manual_memcpy.stderr @@ -67,10 +67,22 @@ LL | for i in from..from + 3 { | ^^^^^^^^^^^^^^ help: try replacing the loop by: `dst[from..from + 3].clone_from_slice(&src[..(from + 3 - from)])` error: it looks like you're manually copying between slices - --> $DIR/manual_memcpy.rs:110:14 + --> $DIR/manual_memcpy.rs:103:14 + | +LL | for i in 0..5 { + | ^^^^ help: try replacing the loop by: `dst[..5].clone_from_slice(&src[..5])` + +error: it looks like you're manually copying between slices + --> $DIR/manual_memcpy.rs:108:14 + | +LL | for i in 0..0 { + | ^^^^ help: try replacing the loop by: `dst[..0].clone_from_slice(&src[..0])` + +error: it looks like you're manually copying between slices + --> $DIR/manual_memcpy.rs:120:14 | LL | for i in 0..src.len() { | ^^^^^^^^^^^^ help: try replacing the loop by: `dst[..src.len()].clone_from_slice(&src[..])` -error: aborting due to 11 previous errors +error: aborting due to 13 previous errors From f072ded3bf6286668ff8eade5b58e471dbe66f2a Mon Sep 17 00:00:00 2001 From: Eduardo Broto Date: Fri, 1 May 2020 01:44:17 +0200 Subject: [PATCH 025/203] Implement the manual_non_exhaustive lint --- CHANGELOG.md | 1 + clippy_lints/src/lib.rs | 5 + clippy_lints/src/manual_non_exhaustive.rs | 167 ++++++++++++++++++++++ src/lintlist/mod.rs | 7 + tests/ui/manual_non_exhaustive.rs | 124 ++++++++++++++++ tests/ui/manual_non_exhaustive.stderr | 48 +++++++ 6 files changed, 352 insertions(+) create mode 100644 clippy_lints/src/manual_non_exhaustive.rs create mode 100644 tests/ui/manual_non_exhaustive.rs create mode 100644 tests/ui/manual_non_exhaustive.stderr diff --git a/CHANGELOG.md b/CHANGELOG.md index 575773580c0b..facf363e371e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1423,6 +1423,7 @@ Released 2018-09-13 [`macro_use_imports`]: https://rust-lang.github.io/rust-clippy/master/index.html#macro_use_imports [`main_recursion`]: https://rust-lang.github.io/rust-clippy/master/index.html#main_recursion [`manual_memcpy`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_memcpy +[`manual_non_exhaustive`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_non_exhaustive [`manual_saturating_arithmetic`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_saturating_arithmetic [`manual_swap`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_swap [`many_single_char_names`]: https://rust-lang.github.io/rust-clippy/master/index.html#many_single_char_names diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index c995be5edc25..64f3a8a0ebbb 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -247,6 +247,7 @@ mod literal_representation; mod loops; mod macro_use; mod main_recursion; +mod manual_non_exhaustive; mod map_clone; mod map_unit_fn; mod match_on_vec_items; @@ -628,6 +629,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: &loops::WHILE_LET_ON_ITERATOR, ¯o_use::MACRO_USE_IMPORTS, &main_recursion::MAIN_RECURSION, + &manual_non_exhaustive::MANUAL_NON_EXHAUSTIVE, &map_clone::MAP_CLONE, &map_unit_fn::OPTION_MAP_UNIT_FN, &map_unit_fn::RESULT_MAP_UNIT_FN, @@ -1064,6 +1066,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(|| box utils::internal_lints::CollapsibleCalls); store.register_late_pass(|| box if_let_mutex::IfLetMutex); store.register_late_pass(|| box match_on_vec_items::MatchOnVecItems); + store.register_early_pass(|| box manual_non_exhaustive::ManualNonExhaustive); store.register_group(true, "clippy::restriction", Some("clippy_restriction"), vec![ LintId::of(&arithmetic::FLOAT_ARITHMETIC), @@ -1280,6 +1283,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&loops::WHILE_LET_LOOP), LintId::of(&loops::WHILE_LET_ON_ITERATOR), LintId::of(&main_recursion::MAIN_RECURSION), + LintId::of(&manual_non_exhaustive::MANUAL_NON_EXHAUSTIVE), LintId::of(&map_clone::MAP_CLONE), LintId::of(&map_unit_fn::OPTION_MAP_UNIT_FN), LintId::of(&map_unit_fn::RESULT_MAP_UNIT_FN), @@ -1474,6 +1478,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&loops::NEEDLESS_RANGE_LOOP), LintId::of(&loops::WHILE_LET_ON_ITERATOR), LintId::of(&main_recursion::MAIN_RECURSION), + LintId::of(&manual_non_exhaustive::MANUAL_NON_EXHAUSTIVE), LintId::of(&map_clone::MAP_CLONE), LintId::of(&matches::INFALLIBLE_DESTRUCTURING_MATCH), LintId::of(&matches::MATCH_OVERLAPPING_ARM), diff --git a/clippy_lints/src/manual_non_exhaustive.rs b/clippy_lints/src/manual_non_exhaustive.rs new file mode 100644 index 000000000000..ca2a2cf2e1e7 --- /dev/null +++ b/clippy_lints/src/manual_non_exhaustive.rs @@ -0,0 +1,167 @@ +use crate::utils::{snippet_opt, span_lint_and_then}; +use if_chain::if_chain; +use rustc_ast::ast::{Attribute, Ident, Item, ItemKind, StructField, TyKind, Variant, VariantData, VisibilityKind}; +use rustc_attr as attr; +use rustc_errors::Applicability; +use rustc_lint::{EarlyContext, EarlyLintPass}; +use rustc_session::{declare_lint_pass, declare_tool_lint}; + +declare_clippy_lint! { + /// **What it does:** Checks for manual implementations of the non-exhaustive pattern. + /// + /// **Why is this bad?** Using the #[non_exhaustive] attribute expresses better the intent + /// and allows possible optimizations when applied to enums. + /// + /// **Known problems:** None. + /// + /// **Example:** + /// + /// ```rust + /// struct S { + /// pub a: i32, + /// pub b: i32, + /// _c: (), + /// } + /// + /// enum E { + /// A, + /// B, + /// #[doc(hidden)] + /// _C, + /// } + /// + /// struct T(pub i32, pub i32, ()); + /// ``` + /// Use instead: + /// ```rust + /// #[non_exhaustive] + /// struct S { + /// pub a: i32, + /// pub b: i32, + /// } + /// + /// #[non_exhaustive] + /// enum E { + /// A, + /// B, + /// } + /// + /// #[non_exhaustive] + /// struct T(pub i32, pub i32); + /// ``` + pub MANUAL_NON_EXHAUSTIVE, + style, + "manual implementations of the non-exhaustive pattern can be simplified using #[non_exhaustive]" +} + +declare_lint_pass!(ManualNonExhaustive => [MANUAL_NON_EXHAUSTIVE]); + +impl EarlyLintPass for ManualNonExhaustive { + fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) { + match &item.kind { + ItemKind::Enum(def, _) => { + check_manual_non_exhaustive_enum(cx, item, &def.variants); + }, + ItemKind::Struct(variant_data, _) => { + if let VariantData::Unit(..) = variant_data { + return; + } + + check_manual_non_exhaustive_struct(cx, item, variant_data); + }, + _ => {}, + } + } +} + +fn check_manual_non_exhaustive_enum(cx: &EarlyContext<'_>, item: &Item, variants: &[Variant]) { + fn is_non_exhaustive_marker(variant: &Variant) -> bool { + matches!(variant.data, VariantData::Unit(_)) + && variant.ident.as_str().starts_with('_') + && variant.attrs.iter().any(|a| is_doc_hidden(a)) + } + + fn is_doc_hidden(attr: &Attribute) -> bool { + attr.check_name(sym!(doc)) + && match attr.meta_item_list() { + Some(l) => attr::list_contains_name(&l, sym!(hidden)), + None => false, + } + } + + if_chain! { + if !attr::contains_name(&item.attrs, sym!(non_exhaustive)); + let markers = variants.iter().filter(|v| is_non_exhaustive_marker(v)).count(); + if markers == 1 && variants.len() > markers; + if let Some(variant) = variants.last(); + if is_non_exhaustive_marker(variant); + then { + span_lint_and_then( + cx, + MANUAL_NON_EXHAUSTIVE, + item.span, + "this seems like a manual implementation of the non-exhaustive pattern", + |diag| { + let header_span = cx.sess.source_map().span_until_char(item.span, '{'); + + if let Some(snippet) = snippet_opt(cx, header_span) { + diag.span_suggestion( + item.span, + "add the attribute", + format!("#[non_exhaustive] {}", snippet), + Applicability::Unspecified, + ); + diag.span_help(variant.span, "and remove this variant"); + } + }); + } + } +} + +fn check_manual_non_exhaustive_struct(cx: &EarlyContext<'_>, item: &Item, data: &VariantData) { + fn is_private(field: &StructField) -> bool { + matches!(field.vis.node, VisibilityKind::Inherited) + } + + fn is_non_exhaustive_marker(name: &Option) -> bool { + name.map(|n| n.as_str().starts_with('_')).unwrap_or(true) + } + + let fields = data.fields(); + let private_fields = fields.iter().filter(|f| is_private(f)).count(); + let public_fields = fields.iter().filter(|f| f.vis.node.is_pub()).count(); + + if_chain! { + if !attr::contains_name(&item.attrs, sym!(non_exhaustive)); + if private_fields == 1 && public_fields >= private_fields && public_fields == fields.len() - 1; + if let Some(field) = fields.iter().find(|f| is_private(f)); + if is_non_exhaustive_marker(&field.ident); + if let TyKind::Tup(tup_fields) = &field.ty.kind; + if tup_fields.is_empty(); + then { + span_lint_and_then( + cx, + MANUAL_NON_EXHAUSTIVE, + item.span, + "this seems like a manual implementation of the non-exhaustive pattern", + |diag| { + let delimiter = match data { + VariantData::Struct(..) => '{', + VariantData::Tuple(..) => '(', + _ => unreachable!(), + }; + let header_span = cx.sess.source_map().span_until_char(item.span, delimiter); + + if let Some(snippet) = snippet_opt(cx, header_span) { + diag.span_suggestion( + item.span, + "add the attribute", + format!("#[non_exhaustive] {}", snippet), + Applicability::Unspecified, + ); + diag.span_help(field.span, "and remove this field"); + } + }); + } + } +} diff --git a/src/lintlist/mod.rs b/src/lintlist/mod.rs index 72675c25175c..c5360002fa05 100644 --- a/src/lintlist/mod.rs +++ b/src/lintlist/mod.rs @@ -1088,6 +1088,13 @@ pub static ref ALL_LINTS: Vec = vec![ deprecation: None, module: "loops", }, + Lint { + name: "manual_non_exhaustive", + group: "style", + desc: "manual implementations of the non-exhaustive pattern can be simplified using #[non_exhaustive]", + deprecation: None, + module: "manual_non_exhaustive", + }, Lint { name: "manual_saturating_arithmetic", group: "style", diff --git a/tests/ui/manual_non_exhaustive.rs b/tests/ui/manual_non_exhaustive.rs new file mode 100644 index 000000000000..9c239db6e00d --- /dev/null +++ b/tests/ui/manual_non_exhaustive.rs @@ -0,0 +1,124 @@ +#![warn(clippy::manual_non_exhaustive)] +#![allow(unused)] + +mod enums { + enum E { + A, + B, + #[doc(hidden)] + _C, + } + + // last variant does not have doc hidden attribute, should be ignored + enum NoDocHidden { + A, + B, + _C, + } + + // name of variant with doc hidden does not start with underscore, should be ignored + enum NoUnderscore { + A, + B, + #[doc(hidden)] + C, + } + + // variant with doc hidden is not unit, should be ignored + enum NotUnit { + A, + B, + #[doc(hidden)] + _C(bool), + } + + // variant with doc hidden is not the last one, should be ignored + enum NotLast { + A, + #[doc(hidden)] + _B, + C, + } + + // variant with doc hidden is the only one, should be ignored + enum OnlyMarker { + #[doc(hidden)] + _A, + } + + // variant with multiple non-exhaustive "markers", should be ignored + enum MultipleMarkers { + A, + #[doc(hidden)] + _B, + #[doc(hidden)] + _C, + } + + // already non_exhaustive, should be ignored + #[non_exhaustive] + enum NonExhaustive { + A, + B, + } +} + +mod structs { + struct S { + pub a: i32, + pub b: i32, + _c: (), + } + + // some other fields are private, should be ignored + struct PrivateFields { + a: i32, + pub b: i32, + _c: (), + } + + // private field name does not start with underscore, should be ignored + struct NoUnderscore { + pub a: i32, + pub b: i32, + c: (), + } + + // private field is not unit type, should be ignored + struct NotUnit { + pub a: i32, + pub b: i32, + _c: i32, + } + + // private field is the only field, should be ignored + struct OnlyMarker { + _a: (), + } + + // already non exhaustive, should be ignored + #[non_exhaustive] + struct NonExhaustive { + pub a: i32, + pub b: i32, + } +} + +mod tuple_structs { + struct T(pub i32, pub i32, ()); + + // some other fields are private, should be ignored + struct PrivateFields(pub i32, i32, ()); + + // private field is not unit type, should be ignored + struct NotUnit(pub i32, pub i32, i32); + + // private field is the only field, should be ignored + struct OnlyMarker(()); + + // already non exhaustive, should be ignored + #[non_exhaustive] + struct NonExhaustive(pub i32, pub i32); +} + +fn main() {} diff --git a/tests/ui/manual_non_exhaustive.stderr b/tests/ui/manual_non_exhaustive.stderr new file mode 100644 index 000000000000..d6719bca0d4c --- /dev/null +++ b/tests/ui/manual_non_exhaustive.stderr @@ -0,0 +1,48 @@ +error: this seems like a manual implementation of the non-exhaustive pattern + --> $DIR/manual_non_exhaustive.rs:5:5 + | +LL | / enum E { +LL | | A, +LL | | B, +LL | | #[doc(hidden)] +LL | | _C, +LL | | } + | |_____^ help: add the attribute: `#[non_exhaustive] enum E` + | + = note: `-D clippy::manual-non-exhaustive` implied by `-D warnings` +help: and remove this variant + --> $DIR/manual_non_exhaustive.rs:9:9 + | +LL | _C, + | ^^ + +error: this seems like a manual implementation of the non-exhaustive pattern + --> $DIR/manual_non_exhaustive.rs:67:5 + | +LL | / struct S { +LL | | pub a: i32, +LL | | pub b: i32, +LL | | _c: (), +LL | | } + | |_____^ help: add the attribute: `#[non_exhaustive] struct S` + | +help: and remove this field + --> $DIR/manual_non_exhaustive.rs:70:9 + | +LL | _c: (), + | ^^^^^^ + +error: this seems like a manual implementation of the non-exhaustive pattern + --> $DIR/manual_non_exhaustive.rs:108:5 + | +LL | struct T(pub i32, pub i32, ()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: add the attribute: `#[non_exhaustive] struct T` + | +help: and remove this field + --> $DIR/manual_non_exhaustive.rs:108:32 + | +LL | struct T(pub i32, pub i32, ()); + | ^^ + +error: aborting due to 3 previous errors + From c66d02e3ba0d5ace4e42bab88e4df246f03b91d5 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 1 May 2020 11:16:38 +0200 Subject: [PATCH 026/203] liballoc tests: Miri supports threads now --- src/liballoc/alloc/tests.rs | 2 +- src/liballoc/collections/linked_list/tests.rs | 1 - src/liballoc/collections/vec_deque/tests.rs | 8 ++++---- src/liballoc/sync/tests.rs | 2 -- 4 files changed, 5 insertions(+), 8 deletions(-) diff --git a/src/liballoc/alloc/tests.rs b/src/liballoc/alloc/tests.rs index 1ad40eca93b6..1c003983df98 100644 --- a/src/liballoc/alloc/tests.rs +++ b/src/liballoc/alloc/tests.rs @@ -23,7 +23,7 @@ fn allocate_zeroed() { } #[bench] -#[cfg_attr(miri, ignore)] // Miri does not support benchmarks +#[cfg_attr(miri, ignore)] // isolated Miri does not support benchmarks fn alloc_owned_small(b: &mut Bencher) { b.iter(|| { let _: Box<_> = box 10; diff --git a/src/liballoc/collections/linked_list/tests.rs b/src/liballoc/collections/linked_list/tests.rs index 085f734ed916..b8c93a28bba8 100644 --- a/src/liballoc/collections/linked_list/tests.rs +++ b/src/liballoc/collections/linked_list/tests.rs @@ -182,7 +182,6 @@ fn test_insert_prev() { #[test] #[cfg_attr(target_os = "emscripten", ignore)] -#[cfg_attr(miri, ignore)] // Miri does not support threads fn test_send() { let n = list_from(&[1, 2, 3]); thread::spawn(move || { diff --git a/src/liballoc/collections/vec_deque/tests.rs b/src/liballoc/collections/vec_deque/tests.rs index 0a3f33003233..fc2ec7908e82 100644 --- a/src/liballoc/collections/vec_deque/tests.rs +++ b/src/liballoc/collections/vec_deque/tests.rs @@ -3,7 +3,7 @@ use super::*; use test; #[bench] -#[cfg_attr(miri, ignore)] // Miri does not support benchmarks +#[cfg_attr(miri, ignore)] // isolated Miri does not support benchmarks fn bench_push_back_100(b: &mut test::Bencher) { let mut deq = VecDeque::with_capacity(101); b.iter(|| { @@ -16,7 +16,7 @@ fn bench_push_back_100(b: &mut test::Bencher) { } #[bench] -#[cfg_attr(miri, ignore)] // Miri does not support benchmarks +#[cfg_attr(miri, ignore)] // isolated Miri does not support benchmarks fn bench_push_front_100(b: &mut test::Bencher) { let mut deq = VecDeque::with_capacity(101); b.iter(|| { @@ -29,7 +29,7 @@ fn bench_push_front_100(b: &mut test::Bencher) { } #[bench] -#[cfg_attr(miri, ignore)] // Miri does not support benchmarks +#[cfg_attr(miri, ignore)] // isolated Miri does not support benchmarks fn bench_pop_back_100(b: &mut test::Bencher) { let mut deq = VecDeque::::with_capacity(101); @@ -43,7 +43,7 @@ fn bench_pop_back_100(b: &mut test::Bencher) { } #[bench] -#[cfg_attr(miri, ignore)] // Miri does not support benchmarks +#[cfg_attr(miri, ignore)] // isolated Miri does not support benchmarks fn bench_pop_front_100(b: &mut test::Bencher) { let mut deq = VecDeque::::with_capacity(101); diff --git a/src/liballoc/sync/tests.rs b/src/liballoc/sync/tests.rs index edc2820ee22f..4a5cc9aa5910 100644 --- a/src/liballoc/sync/tests.rs +++ b/src/liballoc/sync/tests.rs @@ -32,7 +32,6 @@ impl Drop for Canary { #[test] #[cfg_attr(target_os = "emscripten", ignore)] -#[cfg_attr(miri, ignore)] // Miri does not support threads fn manually_share_arc() { let v = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; let arc_v = Arc::new(v); @@ -337,7 +336,6 @@ fn test_ptr_eq() { #[test] #[cfg_attr(target_os = "emscripten", ignore)] -#[cfg_attr(miri, ignore)] // Miri does not support threads fn test_weak_count_locked() { let mut a = Arc::new(atomic::AtomicBool::new(false)); let a2 = a.clone(); From 42b0b4754c881101cefb0307c489d6159c19b2f3 Mon Sep 17 00:00:00 2001 From: Eduardo Broto Date: Fri, 1 May 2020 22:37:14 +0200 Subject: [PATCH 027/203] Apply suggestions from PR review --- clippy_lints/src/manual_non_exhaustive.rs | 84 ++++++++++++----------- tests/ui/manual_non_exhaustive.rs | 39 +++++++---- tests/ui/manual_non_exhaustive.stderr | 81 ++++++++++++++++++---- 3 files changed, 139 insertions(+), 65 deletions(-) diff --git a/clippy_lints/src/manual_non_exhaustive.rs b/clippy_lints/src/manual_non_exhaustive.rs index ca2a2cf2e1e7..a4273da1d741 100644 --- a/clippy_lints/src/manual_non_exhaustive.rs +++ b/clippy_lints/src/manual_non_exhaustive.rs @@ -1,10 +1,11 @@ use crate::utils::{snippet_opt, span_lint_and_then}; use if_chain::if_chain; -use rustc_ast::ast::{Attribute, Ident, Item, ItemKind, StructField, TyKind, Variant, VariantData, VisibilityKind}; +use rustc_ast::ast::{Attribute, Item, ItemKind, StructField, Variant, VariantData, VisibilityKind}; use rustc_attr as attr; use rustc_errors::Applicability; use rustc_lint::{EarlyContext, EarlyLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_span::Span; declare_clippy_lint! { /// **What it does:** Checks for manual implementations of the non-exhaustive pattern. @@ -90,11 +91,9 @@ fn check_manual_non_exhaustive_enum(cx: &EarlyContext<'_>, item: &Item, variants } if_chain! { - if !attr::contains_name(&item.attrs, sym!(non_exhaustive)); - let markers = variants.iter().filter(|v| is_non_exhaustive_marker(v)).count(); - if markers == 1 && variants.len() > markers; - if let Some(variant) = variants.last(); - if is_non_exhaustive_marker(variant); + let mut markers = variants.iter().filter(|v| is_non_exhaustive_marker(v)); + if let Some(marker) = markers.next(); + if markers.count() == 0 && variants.len() > 1; then { span_lint_and_then( cx, @@ -102,17 +101,20 @@ fn check_manual_non_exhaustive_enum(cx: &EarlyContext<'_>, item: &Item, variants item.span, "this seems like a manual implementation of the non-exhaustive pattern", |diag| { - let header_span = cx.sess.source_map().span_until_char(item.span, '{'); - - if let Some(snippet) = snippet_opt(cx, header_span) { - diag.span_suggestion( - item.span, - "add the attribute", - format!("#[non_exhaustive] {}", snippet), - Applicability::Unspecified, - ); - diag.span_help(variant.span, "and remove this variant"); + if_chain! { + if !attr::contains_name(&item.attrs, sym!(non_exhaustive)); + let header_span = cx.sess.source_map().span_until_char(item.span, '{'); + if let Some(snippet) = snippet_opt(cx, header_span); + then { + diag.span_suggestion( + header_span, + "add the attribute", + format!("#[non_exhaustive] {}", snippet), + Applicability::Unspecified, + ); + } } + diag.span_help(marker.span, "remove this variant"); }); } } @@ -123,8 +125,18 @@ fn check_manual_non_exhaustive_struct(cx: &EarlyContext<'_>, item: &Item, data: matches!(field.vis.node, VisibilityKind::Inherited) } - fn is_non_exhaustive_marker(name: &Option) -> bool { - name.map(|n| n.as_str().starts_with('_')).unwrap_or(true) + fn is_non_exhaustive_marker(field: &StructField) -> bool { + is_private(field) && field.ty.kind.is_unit() && field.ident.map_or(true, |n| n.as_str().starts_with('_')) + } + + fn find_header_span(cx: &EarlyContext<'_>, item: &Item, data: &VariantData) -> Span { + let delimiter = match data { + VariantData::Struct(..) => '{', + VariantData::Tuple(..) => '(', + _ => unreachable!("`VariantData::Unit` is already handled above"), + }; + + cx.sess.source_map().span_until_char(item.span, delimiter) } let fields = data.fields(); @@ -132,12 +144,8 @@ fn check_manual_non_exhaustive_struct(cx: &EarlyContext<'_>, item: &Item, data: let public_fields = fields.iter().filter(|f| f.vis.node.is_pub()).count(); if_chain! { - if !attr::contains_name(&item.attrs, sym!(non_exhaustive)); - if private_fields == 1 && public_fields >= private_fields && public_fields == fields.len() - 1; - if let Some(field) = fields.iter().find(|f| is_private(f)); - if is_non_exhaustive_marker(&field.ident); - if let TyKind::Tup(tup_fields) = &field.ty.kind; - if tup_fields.is_empty(); + if private_fields == 1 && public_fields >= 1 && public_fields == fields.len() - 1; + if let Some(marker) = fields.iter().find(|f| is_non_exhaustive_marker(f)); then { span_lint_and_then( cx, @@ -145,22 +153,20 @@ fn check_manual_non_exhaustive_struct(cx: &EarlyContext<'_>, item: &Item, data: item.span, "this seems like a manual implementation of the non-exhaustive pattern", |diag| { - let delimiter = match data { - VariantData::Struct(..) => '{', - VariantData::Tuple(..) => '(', - _ => unreachable!(), - }; - let header_span = cx.sess.source_map().span_until_char(item.span, delimiter); - - if let Some(snippet) = snippet_opt(cx, header_span) { - diag.span_suggestion( - item.span, - "add the attribute", - format!("#[non_exhaustive] {}", snippet), - Applicability::Unspecified, - ); - diag.span_help(field.span, "and remove this field"); + if_chain! { + if !attr::contains_name(&item.attrs, sym!(non_exhaustive)); + let header_span = find_header_span(cx, item, data); + if let Some(snippet) = snippet_opt(cx, header_span); + then { + diag.span_suggestion( + header_span, + "add the attribute", + format!("#[non_exhaustive] {}", snippet), + Applicability::Unspecified, + ); + } } + diag.span_help(marker.span, "remove this field"); }); } } diff --git a/tests/ui/manual_non_exhaustive.rs b/tests/ui/manual_non_exhaustive.rs index 9c239db6e00d..7a788f485207 100644 --- a/tests/ui/manual_non_exhaustive.rs +++ b/tests/ui/manual_non_exhaustive.rs @@ -9,7 +9,16 @@ mod enums { _C, } - // last variant does not have doc hidden attribute, should be ignored + // user forgot to remove the marker + #[non_exhaustive] + enum Ep { + A, + B, + #[doc(hidden)] + _C, + } + + // marker variant does not have doc hidden attribute, should be ignored enum NoDocHidden { A, B, @@ -32,21 +41,13 @@ mod enums { _C(bool), } - // variant with doc hidden is not the last one, should be ignored - enum NotLast { - A, - #[doc(hidden)] - _B, - C, - } - // variant with doc hidden is the only one, should be ignored enum OnlyMarker { #[doc(hidden)] _A, } - // variant with multiple non-exhaustive "markers", should be ignored + // variant with multiple markers, should be ignored enum MultipleMarkers { A, #[doc(hidden)] @@ -55,7 +56,7 @@ mod enums { _C, } - // already non_exhaustive, should be ignored + // already non_exhaustive and no markers, should be ignored #[non_exhaustive] enum NonExhaustive { A, @@ -70,6 +71,14 @@ mod structs { _c: (), } + // user forgot to remove the private field + #[non_exhaustive] + struct Sp { + pub a: i32, + pub b: i32, + _c: (), + } + // some other fields are private, should be ignored struct PrivateFields { a: i32, @@ -96,7 +105,7 @@ mod structs { _a: (), } - // already non exhaustive, should be ignored + // already non exhaustive and no private fields, should be ignored #[non_exhaustive] struct NonExhaustive { pub a: i32, @@ -107,6 +116,10 @@ mod structs { mod tuple_structs { struct T(pub i32, pub i32, ()); + // user forgot to remove the private field + #[non_exhaustive] + struct Tp(pub i32, pub i32, ()); + // some other fields are private, should be ignored struct PrivateFields(pub i32, i32, ()); @@ -116,7 +129,7 @@ mod tuple_structs { // private field is the only field, should be ignored struct OnlyMarker(()); - // already non exhaustive, should be ignored + // already non exhaustive and no private fields, should be ignored #[non_exhaustive] struct NonExhaustive(pub i32, pub i32); } diff --git a/tests/ui/manual_non_exhaustive.stderr b/tests/ui/manual_non_exhaustive.stderr index d6719bca0d4c..613c5e8ca1d4 100644 --- a/tests/ui/manual_non_exhaustive.stderr +++ b/tests/ui/manual_non_exhaustive.stderr @@ -1,48 +1,103 @@ error: this seems like a manual implementation of the non-exhaustive pattern --> $DIR/manual_non_exhaustive.rs:5:5 | -LL | / enum E { +LL | enum E { + | ^----- + | | + | _____help: add the attribute: `#[non_exhaustive] enum E` + | | LL | | A, LL | | B, LL | | #[doc(hidden)] LL | | _C, LL | | } - | |_____^ help: add the attribute: `#[non_exhaustive] enum E` + | |_____^ | = note: `-D clippy::manual-non-exhaustive` implied by `-D warnings` -help: and remove this variant +help: remove this variant --> $DIR/manual_non_exhaustive.rs:9:9 | LL | _C, | ^^ error: this seems like a manual implementation of the non-exhaustive pattern - --> $DIR/manual_non_exhaustive.rs:67:5 + --> $DIR/manual_non_exhaustive.rs:14:5 | -LL | / struct S { +LL | / enum Ep { +LL | | A, +LL | | B, +LL | | #[doc(hidden)] +LL | | _C, +LL | | } + | |_____^ + | +help: remove this variant + --> $DIR/manual_non_exhaustive.rs:18:9 + | +LL | _C, + | ^^ + +error: this seems like a manual implementation of the non-exhaustive pattern + --> $DIR/manual_non_exhaustive.rs:68:5 + | +LL | struct S { + | ^------- + | | + | _____help: add the attribute: `#[non_exhaustive] struct S` + | | LL | | pub a: i32, LL | | pub b: i32, LL | | _c: (), LL | | } - | |_____^ help: add the attribute: `#[non_exhaustive] struct S` + | |_____^ | -help: and remove this field - --> $DIR/manual_non_exhaustive.rs:70:9 +help: remove this field + --> $DIR/manual_non_exhaustive.rs:71:9 | LL | _c: (), | ^^^^^^ error: this seems like a manual implementation of the non-exhaustive pattern - --> $DIR/manual_non_exhaustive.rs:108:5 + --> $DIR/manual_non_exhaustive.rs:76:5 + | +LL | / struct Sp { +LL | | pub a: i32, +LL | | pub b: i32, +LL | | _c: (), +LL | | } + | |_____^ + | +help: remove this field + --> $DIR/manual_non_exhaustive.rs:79:9 + | +LL | _c: (), + | ^^^^^^ + +error: this seems like a manual implementation of the non-exhaustive pattern + --> $DIR/manual_non_exhaustive.rs:117:5 | LL | struct T(pub i32, pub i32, ()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: add the attribute: `#[non_exhaustive] struct T` + | --------^^^^^^^^^^^^^^^^^^^^^^^ + | | + | help: add the attribute: `#[non_exhaustive] struct T` | -help: and remove this field - --> $DIR/manual_non_exhaustive.rs:108:32 +help: remove this field + --> $DIR/manual_non_exhaustive.rs:117:32 | LL | struct T(pub i32, pub i32, ()); | ^^ -error: aborting due to 3 previous errors +error: this seems like a manual implementation of the non-exhaustive pattern + --> $DIR/manual_non_exhaustive.rs:121:5 + | +LL | struct Tp(pub i32, pub i32, ()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove this field + --> $DIR/manual_non_exhaustive.rs:121:33 + | +LL | struct Tp(pub i32, pub i32, ()); + | ^^ + +error: aborting due to 6 previous errors From 10e3f9bdb854e3cabbc4fda69ed713388344d524 Mon Sep 17 00:00:00 2001 From: flip1995 Date: Fri, 1 May 2020 23:02:31 +0200 Subject: [PATCH 028/203] Move match_on_vec_items to pedantic --- clippy_lints/src/lib.rs | 3 +-- clippy_lints/src/match_on_vec_items.rs | 2 +- src/lintlist/mod.rs | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index c995be5edc25..06e21a5272ec 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -1138,6 +1138,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&loops::EXPLICIT_INTO_ITER_LOOP), LintId::of(&loops::EXPLICIT_ITER_LOOP), LintId::of(¯o_use::MACRO_USE_IMPORTS), + LintId::of(&match_on_vec_items::MATCH_ON_VEC_ITEMS), LintId::of(&matches::MATCH_BOOL), LintId::of(&matches::SINGLE_MATCH_ELSE), LintId::of(&methods::FILTER_MAP), @@ -1283,7 +1284,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&map_clone::MAP_CLONE), LintId::of(&map_unit_fn::OPTION_MAP_UNIT_FN), LintId::of(&map_unit_fn::RESULT_MAP_UNIT_FN), - LintId::of(&match_on_vec_items::MATCH_ON_VEC_ITEMS), LintId::of(&matches::INFALLIBLE_DESTRUCTURING_MATCH), LintId::of(&matches::MATCH_AS_REF), LintId::of(&matches::MATCH_OVERLAPPING_ARM), @@ -1647,7 +1647,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&loops::NEVER_LOOP), LintId::of(&loops::REVERSE_RANGE_LOOP), LintId::of(&loops::WHILE_IMMUTABLE_CONDITION), - LintId::of(&match_on_vec_items::MATCH_ON_VEC_ITEMS), LintId::of(&mem_discriminant::MEM_DISCRIMINANT_NON_ENUM), LintId::of(&mem_replace::MEM_REPLACE_WITH_UNINIT), LintId::of(&methods::CLONE_DOUBLE_REF), diff --git a/clippy_lints/src/match_on_vec_items.rs b/clippy_lints/src/match_on_vec_items.rs index 4071406cc84c..421571d2f2f4 100644 --- a/clippy_lints/src/match_on_vec_items.rs +++ b/clippy_lints/src/match_on_vec_items.rs @@ -38,7 +38,7 @@ declare_clippy_lint! { /// } /// ``` pub MATCH_ON_VEC_ITEMS, - correctness, + pedantic, "matching on vector elements can panic" } diff --git a/src/lintlist/mod.rs b/src/lintlist/mod.rs index 72675c25175c..f337db72ba00 100644 --- a/src/lintlist/mod.rs +++ b/src/lintlist/mod.rs @@ -1146,7 +1146,7 @@ pub static ref ALL_LINTS: Vec = vec![ }, Lint { name: "match_on_vec_items", - group: "correctness", + group: "pedantic", desc: "matching on vector elements can panic", deprecation: None, module: "match_on_vec_items", From 350c17de24c0bc7ee1b17981fe02f88ca6ec50a4 Mon Sep 17 00:00:00 2001 From: ebroto Date: Fri, 1 May 2020 23:00:16 +0200 Subject: [PATCH 029/203] Use the only variant left instead of a wildcard Co-authored-by: Philipp Krones --- clippy_lints/src/manual_non_exhaustive.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/manual_non_exhaustive.rs b/clippy_lints/src/manual_non_exhaustive.rs index a4273da1d741..f3b8902e26f6 100644 --- a/clippy_lints/src/manual_non_exhaustive.rs +++ b/clippy_lints/src/manual_non_exhaustive.rs @@ -133,7 +133,7 @@ fn check_manual_non_exhaustive_struct(cx: &EarlyContext<'_>, item: &Item, data: let delimiter = match data { VariantData::Struct(..) => '{', VariantData::Tuple(..) => '(', - _ => unreachable!("`VariantData::Unit` is already handled above"), + VariantData::Unit(_) => unreachable!("`VariantData::Unit` is already handled above"), }; cx.sess.source_map().span_until_char(item.span, delimiter) From 2e749a5ecd3831f8cb947761b15b2b108ca0ec7c Mon Sep 17 00:00:00 2001 From: Mohsen Zohrevandi Date: Fri, 1 May 2020 17:03:39 -0700 Subject: [PATCH 030/203] Correction: ignore emscripten in process termination tests --- .../ui/process-termination/process-termination-blocking-io.rs | 2 +- src/test/ui/process-termination/process-termination-simple.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/ui/process-termination/process-termination-blocking-io.rs b/src/test/ui/process-termination/process-termination-blocking-io.rs index 864fb776e867..df1a768ebbda 100644 --- a/src/test/ui/process-termination/process-termination-blocking-io.rs +++ b/src/test/ui/process-termination/process-termination-blocking-io.rs @@ -2,7 +2,7 @@ // https://github.com/fortanix/rust-sgx/issues/109 // run-pass -// ignore-wasm no threads support +// ignore-emscripten no threads support use std::{net::TcpListener, sync::mpsc, thread}; diff --git a/src/test/ui/process-termination/process-termination-simple.rs b/src/test/ui/process-termination/process-termination-simple.rs index 3660f95b05bc..8f2e5b94c3a6 100644 --- a/src/test/ui/process-termination/process-termination-simple.rs +++ b/src/test/ui/process-termination/process-termination-simple.rs @@ -1,7 +1,7 @@ // program should terminate when std::process::exit is called from any thread // run-pass -// ignore-wasm no threads support +// ignore-emscripten no threads support use std::{process, thread}; From 72ce6d5be9c54775b847bc0641f8d909b2977126 Mon Sep 17 00:00:00 2001 From: ThibsG Date: Fri, 24 Apr 2020 16:46:56 +0200 Subject: [PATCH 031/203] Fix unwrap lint when checks are done in parameters --- clippy_lints/src/unwrap.rs | 21 ++++++++++----- .../ui/checked_unwrap/simple_conditionals.rs | 27 +++++++++++++++++++ .../checked_unwrap/simple_conditionals.stderr | 24 ++++++++--------- 3 files changed, 54 insertions(+), 18 deletions(-) diff --git a/clippy_lints/src/unwrap.rs b/clippy_lints/src/unwrap.rs index 5235c98efab1..f3844c7d3b68 100644 --- a/clippy_lints/src/unwrap.rs +++ b/clippy_lints/src/unwrap.rs @@ -1,4 +1,7 @@ -use crate::utils::{higher::if_block, is_type_diagnostic_item, span_lint_and_then, usage::is_potentially_mutated}; +use crate::utils::{ + differing_macro_contexts, higher::if_block, is_type_diagnostic_item, span_lint_and_then, + usage::is_potentially_mutated, +}; use if_chain::if_chain; use rustc_hir::intravisit::{walk_expr, walk_fn, FnKind, NestedVisitorMap, Visitor}; use rustc_hir::{BinOpKind, Body, Expr, ExprKind, FnDecl, HirId, Path, QPath, UnOp}; @@ -73,6 +76,8 @@ struct UnwrapInfo<'tcx> { ident: &'tcx Path<'tcx>, /// The check, like `x.is_ok()` check: &'tcx Expr<'tcx>, + /// The branch where the check takes place, like `if x.is_ok() { .. }` + branch: &'tcx Expr<'tcx>, /// Whether `is_some()` or `is_ok()` was called (as opposed to `is_err()` or `is_none()`). safe_to_unwrap: bool, } @@ -82,19 +87,20 @@ struct UnwrapInfo<'tcx> { fn collect_unwrap_info<'a, 'tcx>( cx: &'a LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>, + branch: &'tcx Expr<'_>, invert: bool, ) -> Vec> { if let ExprKind::Binary(op, left, right) = &expr.kind { match (invert, op.node) { (false, BinOpKind::And) | (false, BinOpKind::BitAnd) | (true, BinOpKind::Or) | (true, BinOpKind::BitOr) => { - let mut unwrap_info = collect_unwrap_info(cx, left, invert); - unwrap_info.append(&mut collect_unwrap_info(cx, right, invert)); + let mut unwrap_info = collect_unwrap_info(cx, left, branch, invert); + unwrap_info.append(&mut collect_unwrap_info(cx, right, branch, invert)); return unwrap_info; }, _ => (), } } else if let ExprKind::Unary(UnOp::UnNot, expr) = &expr.kind { - return collect_unwrap_info(cx, expr, !invert); + return collect_unwrap_info(cx, expr, branch, !invert); } else { if_chain! { if let ExprKind::MethodCall(method_name, _, args) = &expr.kind; @@ -111,7 +117,7 @@ fn collect_unwrap_info<'a, 'tcx>( _ => unreachable!(), }; let safe_to_unwrap = unwrappable != invert; - return vec![UnwrapInfo { ident: path, check: expr, safe_to_unwrap }]; + return vec![UnwrapInfo { ident: path, check: expr, branch, safe_to_unwrap }]; } } } @@ -121,7 +127,7 @@ fn collect_unwrap_info<'a, 'tcx>( impl<'a, 'tcx> UnwrappableVariablesVisitor<'a, 'tcx> { fn visit_branch(&mut self, cond: &'tcx Expr<'_>, branch: &'tcx Expr<'_>, else_branch: bool) { let prev_len = self.unwrappables.len(); - for unwrap_info in collect_unwrap_info(self.cx, cond, else_branch) { + for unwrap_info in collect_unwrap_info(self.cx, cond, branch, else_branch) { if is_potentially_mutated(unwrap_info.ident, cond, self.cx) || is_potentially_mutated(unwrap_info.ident, branch, self.cx) { @@ -158,6 +164,9 @@ impl<'a, 'tcx> Visitor<'tcx> for UnwrappableVariablesVisitor<'a, 'tcx> { let call_to_unwrap = method_name.ident.name == sym!(unwrap); if let Some(unwrappable) = self.unwrappables.iter() .find(|u| u.ident.res == path.res); + // Span contexts should not differ with the conditional branch + if !differing_macro_contexts(unwrappable.branch.span, expr.span); + if !differing_macro_contexts(unwrappable.branch.span, unwrappable.check.span); then { if call_to_unwrap == unwrappable.safe_to_unwrap { span_lint_and_then( diff --git a/tests/ui/checked_unwrap/simple_conditionals.rs b/tests/ui/checked_unwrap/simple_conditionals.rs index b0fc26ff76de..3e7b4b390bad 100644 --- a/tests/ui/checked_unwrap/simple_conditionals.rs +++ b/tests/ui/checked_unwrap/simple_conditionals.rs @@ -9,6 +9,30 @@ macro_rules! m { }; } +macro_rules! checks_in_param { + ($a:expr, $b:expr) => { + if $a { + $b; + } + }; +} + +macro_rules! checks_unwrap { + ($a:expr, $b:expr) => { + if $a.is_some() { + $b; + } + }; +} + +macro_rules! checks_some { + ($a:expr, $b:expr) => { + if $a { + $b.unwrap(); + } + }; +} + fn main() { let x = Some(()); if x.is_some() { @@ -22,6 +46,9 @@ fn main() { x.unwrap(); // unnecessary } m!(x); + checks_in_param!(x.is_some(), x.unwrap()); // ok + checks_unwrap!(x, x.unwrap()); // ok + checks_some!(x.is_some(), x); // ok let mut x: Result<(), ()> = Ok(()); if x.is_ok() { x.unwrap(); // unnecessary diff --git a/tests/ui/checked_unwrap/simple_conditionals.stderr b/tests/ui/checked_unwrap/simple_conditionals.stderr index e40542e2e4f9..4013d1ed667f 100644 --- a/tests/ui/checked_unwrap/simple_conditionals.stderr +++ b/tests/ui/checked_unwrap/simple_conditionals.stderr @@ -1,5 +1,5 @@ error: You checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. - --> $DIR/simple_conditionals.rs:15:9 + --> $DIR/simple_conditionals.rs:39:9 | LL | if x.is_some() { | ----------- the check is happening here @@ -13,7 +13,7 @@ LL | #![deny(clippy::panicking_unwrap, clippy::unnecessary_unwrap)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: This call to `unwrap()` will always panic. - --> $DIR/simple_conditionals.rs:17:9 + --> $DIR/simple_conditionals.rs:41:9 | LL | if x.is_some() { | ----------- because of this check @@ -28,7 +28,7 @@ LL | #![deny(clippy::panicking_unwrap, clippy::unnecessary_unwrap)] | ^^^^^^^^^^^^^^^^^^^^^^^^ error: This call to `unwrap()` will always panic. - --> $DIR/simple_conditionals.rs:20:9 + --> $DIR/simple_conditionals.rs:44:9 | LL | if x.is_none() { | ----------- because of this check @@ -36,7 +36,7 @@ LL | x.unwrap(); // will panic | ^^^^^^^^^^ error: You checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. - --> $DIR/simple_conditionals.rs:22:9 + --> $DIR/simple_conditionals.rs:46:9 | LL | if x.is_none() { | ----------- the check is happening here @@ -58,7 +58,7 @@ LL | m!(x); = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: You checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. - --> $DIR/simple_conditionals.rs:27:9 + --> $DIR/simple_conditionals.rs:54:9 | LL | if x.is_ok() { | --------- the check is happening here @@ -66,7 +66,7 @@ LL | x.unwrap(); // unnecessary | ^^^^^^^^^^ error: This call to `unwrap_err()` will always panic. - --> $DIR/simple_conditionals.rs:28:9 + --> $DIR/simple_conditionals.rs:55:9 | LL | if x.is_ok() { | --------- because of this check @@ -75,7 +75,7 @@ LL | x.unwrap_err(); // will panic | ^^^^^^^^^^^^^^ error: This call to `unwrap()` will always panic. - --> $DIR/simple_conditionals.rs:30:9 + --> $DIR/simple_conditionals.rs:57:9 | LL | if x.is_ok() { | --------- because of this check @@ -84,7 +84,7 @@ LL | x.unwrap(); // will panic | ^^^^^^^^^^ error: You checked before that `unwrap_err()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. - --> $DIR/simple_conditionals.rs:31:9 + --> $DIR/simple_conditionals.rs:58:9 | LL | if x.is_ok() { | --------- the check is happening here @@ -93,7 +93,7 @@ LL | x.unwrap_err(); // unnecessary | ^^^^^^^^^^^^^^ error: This call to `unwrap()` will always panic. - --> $DIR/simple_conditionals.rs:34:9 + --> $DIR/simple_conditionals.rs:61:9 | LL | if x.is_err() { | ---------- because of this check @@ -101,7 +101,7 @@ LL | x.unwrap(); // will panic | ^^^^^^^^^^ error: You checked before that `unwrap_err()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. - --> $DIR/simple_conditionals.rs:35:9 + --> $DIR/simple_conditionals.rs:62:9 | LL | if x.is_err() { | ---------- the check is happening here @@ -110,7 +110,7 @@ LL | x.unwrap_err(); // unnecessary | ^^^^^^^^^^^^^^ error: You checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. - --> $DIR/simple_conditionals.rs:37:9 + --> $DIR/simple_conditionals.rs:64:9 | LL | if x.is_err() { | ---------- the check is happening here @@ -119,7 +119,7 @@ LL | x.unwrap(); // unnecessary | ^^^^^^^^^^ error: This call to `unwrap_err()` will always panic. - --> $DIR/simple_conditionals.rs:38:9 + --> $DIR/simple_conditionals.rs:65:9 | LL | if x.is_err() { | ---------- because of this check From d0c1f8ada2306801f2a6ce193e1f9f75471dbb3c Mon Sep 17 00:00:00 2001 From: Aleksei Latyshev Date: Sat, 2 May 2020 14:18:27 +0300 Subject: [PATCH 032/203] fix fp on while-let-on-iterator - fix `is_refutable` for slice patterns - fix `is_refutable` for bindings - add some TODO-s for cases, which can not be fixed easily --- clippy_lints/src/utils/mod.rs | 34 ++++++++++------ tests/ui/while_let_on_iterator.fixed | 58 +++++++++++++++++++++++++++ tests/ui/while_let_on_iterator.rs | 58 +++++++++++++++++++++++++++ tests/ui/while_let_on_iterator.stderr | 28 ++++++++++--- 4 files changed, 160 insertions(+), 18 deletions(-) diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 04b4b4237619..1c7b40fa9087 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -933,6 +933,7 @@ pub fn is_ctor_or_promotable_const_function(cx: &LateContext<'_, '_>, expr: &Exp } /// Returns `true` if a pattern is refutable. +// TODO: should be implemented using rustc/mir_build/hair machinery pub fn is_refutable(cx: &LateContext<'_, '_>, pat: &Pat<'_>) -> bool { fn is_enum_variant(cx: &LateContext<'_, '_>, qpath: &QPath<'_>, id: HirId) -> bool { matches!( @@ -946,27 +947,34 @@ pub fn is_refutable(cx: &LateContext<'_, '_>, pat: &Pat<'_>) -> bool { } match pat.kind { - PatKind::Binding(..) | PatKind::Wild => false, + PatKind::Wild => false, + PatKind::Binding(_, _, _, pat) => pat.map_or(false, |pat| is_refutable(cx, pat)), PatKind::Box(ref pat) | PatKind::Ref(ref pat, _) => is_refutable(cx, pat), PatKind::Lit(..) | PatKind::Range(..) => true, PatKind::Path(ref qpath) => is_enum_variant(cx, qpath, pat.hir_id), - PatKind::Or(ref pats) | PatKind::Tuple(ref pats, _) => are_refutable(cx, pats.iter().map(|pat| &**pat)), + PatKind::Or(ref pats) => { + // TODO: should be the honest check, that pats is exhaustive set + are_refutable(cx, pats.iter().map(|pat| &**pat)) + }, + PatKind::Tuple(ref pats, _) => are_refutable(cx, pats.iter().map(|pat| &**pat)), PatKind::Struct(ref qpath, ref fields, _) => { - if is_enum_variant(cx, qpath, pat.hir_id) { - true - } else { - are_refutable(cx, fields.iter().map(|field| &*field.pat)) - } + is_enum_variant(cx, qpath, pat.hir_id) || are_refutable(cx, fields.iter().map(|field| &*field.pat)) }, PatKind::TupleStruct(ref qpath, ref pats, _) => { - if is_enum_variant(cx, qpath, pat.hir_id) { - true - } else { - are_refutable(cx, pats.iter().map(|pat| &**pat)) - } + is_enum_variant(cx, qpath, pat.hir_id) || are_refutable(cx, pats.iter().map(|pat| &**pat)) }, PatKind::Slice(ref head, ref middle, ref tail) => { - are_refutable(cx, head.iter().chain(middle).chain(tail.iter()).map(|pat| &**pat)) + match &cx.tables.node_type(pat.hir_id).kind { + ty::Slice(..) => { + // [..] is the only irrefutable slice pattern. + !head.is_empty() || middle.is_none() || !tail.is_empty() + }, + ty::Array(..) => are_refutable(cx, head.iter().chain(middle).chain(tail.iter()).map(|pat| &**pat)), + _ => { + // unreachable!() + true + }, + } }, } } diff --git a/tests/ui/while_let_on_iterator.fixed b/tests/ui/while_let_on_iterator.fixed index f5fcabf63fd3..e99c98ac79f2 100644 --- a/tests/ui/while_let_on_iterator.fixed +++ b/tests/ui/while_let_on_iterator.fixed @@ -2,6 +2,7 @@ #![warn(clippy::while_let_on_iterator)] #![allow(clippy::never_loop, unreachable_code, unused_mut)] +#![feature(or_patterns)] fn base() { let mut iter = 1..20; @@ -77,6 +78,62 @@ fn refutable() { // */ } +fn refutable2() { + // Issue 3780 + { + let v = vec![1, 2, 3]; + let mut it = v.windows(2); + while let Some([x, y]) = it.next() { + println!("x: {}", x); + println!("y: {}", y); + } + + let mut it = v.windows(2); + while let Some([x, ..]) = it.next() { + println!("x: {}", x); + } + + let mut it = v.windows(2); + while let Some([.., y]) = it.next() { + println!("y: {}", y); + } + + let mut it = v.windows(2); + for [..] in it {} + + let v = vec![[1], [2], [3]]; + let mut it = v.iter(); + while let Some([1]) = it.next() {} + + let mut it = v.iter(); + for [_x] in it {} + } + + // binding + { + let v = vec![1, 2, 3]; + let mut it = v.iter(); + while let Some(x @ 1) = it.next() { + println!("{}", x); + } + + let v = vec![[1], [2], [3]]; + let mut it = v.iter(); + for x @ [_] in it { + println!("{:?}", x); + } + } + + // false negative + { + let v = vec![1, 2, 3]; + let mut it = v.iter().map(Some); + while let Some(Some(_) | None) = it.next() { + println!("1"); + } + } +} + fn nested_loops() { let a = [42, 1337]; let mut y = a.iter(); @@ -152,6 +209,7 @@ fn issue1654() { fn main() { base(); refutable(); + refutable2(); nested_loops(); issue1121(); issue2965(); diff --git a/tests/ui/while_let_on_iterator.rs b/tests/ui/while_let_on_iterator.rs index 04dce8a02898..ba13172428e1 100644 --- a/tests/ui/while_let_on_iterator.rs +++ b/tests/ui/while_let_on_iterator.rs @@ -2,6 +2,7 @@ #![warn(clippy::while_let_on_iterator)] #![allow(clippy::never_loop, unreachable_code, unused_mut)] +#![feature(or_patterns)] fn base() { let mut iter = 1..20; @@ -77,6 +78,62 @@ fn refutable() { // */ } +fn refutable2() { + // Issue 3780 + { + let v = vec![1, 2, 3]; + let mut it = v.windows(2); + while let Some([x, y]) = it.next() { + println!("x: {}", x); + println!("y: {}", y); + } + + let mut it = v.windows(2); + while let Some([x, ..]) = it.next() { + println!("x: {}", x); + } + + let mut it = v.windows(2); + while let Some([.., y]) = it.next() { + println!("y: {}", y); + } + + let mut it = v.windows(2); + while let Some([..]) = it.next() {} + + let v = vec![[1], [2], [3]]; + let mut it = v.iter(); + while let Some([1]) = it.next() {} + + let mut it = v.iter(); + while let Some([_x]) = it.next() {} + } + + // binding + { + let v = vec![1, 2, 3]; + let mut it = v.iter(); + while let Some(x @ 1) = it.next() { + println!("{}", x); + } + + let v = vec![[1], [2], [3]]; + let mut it = v.iter(); + while let Some(x @ [_]) = it.next() { + println!("{:?}", x); + } + } + + // false negative + { + let v = vec![1, 2, 3]; + let mut it = v.iter().map(Some); + while let Some(Some(_) | None) = it.next() { + println!("1"); + } + } +} + fn nested_loops() { let a = [42, 1337]; let mut y = a.iter(); @@ -152,6 +209,7 @@ fn issue1654() { fn main() { base(); refutable(); + refutable2(); nested_loops(); issue1121(); issue2965(); diff --git a/tests/ui/while_let_on_iterator.stderr b/tests/ui/while_let_on_iterator.stderr index 6de138d7227b..aa980d9965c7 100644 --- a/tests/ui/while_let_on_iterator.stderr +++ b/tests/ui/while_let_on_iterator.stderr @@ -1,5 +1,5 @@ error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:8:5 + --> $DIR/while_let_on_iterator.rs:9:5 | LL | while let Option::Some(x) = iter.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x in iter` @@ -7,22 +7,40 @@ LL | while let Option::Some(x) = iter.next() { = note: `-D clippy::while-let-on-iterator` implied by `-D warnings` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:13:5 + --> $DIR/while_let_on_iterator.rs:14:5 | LL | while let Some(x) = iter.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x in iter` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:18:5 + --> $DIR/while_let_on_iterator.rs:19:5 | LL | while let Some(_) = iter.next() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for _ in iter` error: this loop could be written as a `for` loop - --> $DIR/while_let_on_iterator.rs:97:9 + --> $DIR/while_let_on_iterator.rs:102:9 + | +LL | while let Some([..]) = it.next() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for [..] in it` + +error: this loop could be written as a `for` loop + --> $DIR/while_let_on_iterator.rs:109:9 + | +LL | while let Some([_x]) = it.next() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for [_x] in it` + +error: this loop could be written as a `for` loop + --> $DIR/while_let_on_iterator.rs:122:9 + | +LL | while let Some(x @ [_]) = it.next() { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x @ [_] in it` + +error: this loop could be written as a `for` loop + --> $DIR/while_let_on_iterator.rs:154:9 | LL | while let Some(_) = y.next() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for _ in y` -error: aborting due to 4 previous errors +error: aborting due to 7 previous errors From e7138e06291d13163e8ab2a57fe2465451fac193 Mon Sep 17 00:00:00 2001 From: CrazyRoka Date: Sat, 2 May 2020 14:25:45 +0300 Subject: [PATCH 033/203] Fix match on vec items: match on vec[..] - Added new tests - Fixed false positive when matching on full range, which will never panic --- clippy_lints/src/match_on_vec_items.rs | 21 ++++++++++++++++----- tests/ui/match_on_vec_items.rs | 22 ++++++++++++++++++++++ 2 files changed, 38 insertions(+), 5 deletions(-) diff --git a/clippy_lints/src/match_on_vec_items.rs b/clippy_lints/src/match_on_vec_items.rs index 421571d2f2f4..236362130e54 100644 --- a/clippy_lints/src/match_on_vec_items.rs +++ b/clippy_lints/src/match_on_vec_items.rs @@ -1,4 +1,4 @@ -use crate::utils::{is_type_diagnostic_item, snippet, span_lint_and_sugg, walk_ptrs_ty}; +use crate::utils::{is_type_diagnostic_item, match_type, snippet, span_lint_and_sugg, walk_ptrs_ty}; use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind, MatchSource}; @@ -75,10 +75,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MatchOnVecItems { fn is_vec_indexing<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'tcx>) -> Option<&'tcx Expr<'tcx>> { if_chain! { - if let ExprKind::Index(ref array, _) = expr.kind; - let ty = cx.tables.expr_ty(array); - let ty = walk_ptrs_ty(ty); - if is_type_diagnostic_item(cx, ty, sym!(vec_type)); + if let ExprKind::Index(ref array, ref index) = expr.kind; + if is_vector(cx, array); + if !is_full_range(cx, index); then { return Some(expr); @@ -87,3 +86,15 @@ fn is_vec_indexing<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'tcx>) None } + +fn is_vector(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> bool { + let ty = cx.tables.expr_ty(expr); + let ty = walk_ptrs_ty(ty); + is_type_diagnostic_item(cx, ty, sym!(vec_type)) +} + +fn is_full_range(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> bool { + let ty = cx.tables.expr_ty(expr); + let ty = walk_ptrs_ty(ty); + match_type(cx, ty, &["core", "ops", "range", "RangeFull"]) +} diff --git a/tests/ui/match_on_vec_items.rs b/tests/ui/match_on_vec_items.rs index 0bb39d77e461..30415e3b94dc 100644 --- a/tests/ui/match_on_vec_items.rs +++ b/tests/ui/match_on_vec_items.rs @@ -120,6 +120,27 @@ fn match_with_array() { } } +fn match_with_endless_range() { + let arr = vec![0, 1, 2, 3]; + let range = ..; + + // Ok + match arr[range] { + [0, 1] => println!("0 1"), + [1, 2] => println!("1 2"), + [0, 1, 2, 3] => println!("0, 1, 2, 3"), + _ => {}, + } + + // Ok + match arr[..] { + [0, 1] => println!("0 1"), + [1, 2] => println!("1 2"), + [0, 1, 2, 3] => println!("0, 1, 2, 3"), + _ => {}, + } +} + fn main() { match_with_wildcard(); match_without_wildcard(); @@ -127,4 +148,5 @@ fn main() { match_vec_ref(); match_with_get(); match_with_array(); + match_with_endless_range(); } From de58c5644de0d9ffe46e7e2923d2301eaf4dd347 Mon Sep 17 00:00:00 2001 From: CrazyRoka Date: Sat, 2 May 2020 17:36:26 +0300 Subject: [PATCH 034/203] Changed RANGE_FULL constant in utils --- clippy_lints/src/match_on_vec_items.rs | 4 ++-- clippy_lints/src/utils/paths.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/match_on_vec_items.rs b/clippy_lints/src/match_on_vec_items.rs index 236362130e54..ee69628e9f05 100644 --- a/clippy_lints/src/match_on_vec_items.rs +++ b/clippy_lints/src/match_on_vec_items.rs @@ -1,4 +1,4 @@ -use crate::utils::{is_type_diagnostic_item, match_type, snippet, span_lint_and_sugg, walk_ptrs_ty}; +use crate::utils::{self, is_type_diagnostic_item, match_type, snippet, span_lint_and_sugg, walk_ptrs_ty}; use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind, MatchSource}; @@ -96,5 +96,5 @@ fn is_vector(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> bool { fn is_full_range(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> bool { let ty = cx.tables.expr_ty(expr); let ty = walk_ptrs_ty(ty); - match_type(cx, ty, &["core", "ops", "range", "RangeFull"]) + match_type(cx, ty, &utils::paths::RANGE_FULL) } diff --git a/clippy_lints/src/utils/paths.rs b/clippy_lints/src/utils/paths.rs index ca2c4ade1556..79ca6845c6f2 100644 --- a/clippy_lints/src/utils/paths.rs +++ b/clippy_lints/src/utils/paths.rs @@ -85,7 +85,7 @@ pub const RANGE: [&str; 3] = ["core", "ops", "Range"]; pub const RANGE_ARGUMENT_TRAIT: [&str; 3] = ["core", "ops", "RangeBounds"]; pub const RANGE_FROM: [&str; 3] = ["core", "ops", "RangeFrom"]; pub const RANGE_FROM_STD: [&str; 3] = ["std", "ops", "RangeFrom"]; -pub const RANGE_FULL: [&str; 3] = ["core", "ops", "RangeFull"]; +pub const RANGE_FULL: [&str; 4] = ["core", "ops", "range", "RangeFull"]; pub const RANGE_FULL_STD: [&str; 3] = ["std", "ops", "RangeFull"]; pub const RANGE_INCLUSIVE_NEW: [&str; 4] = ["core", "ops", "RangeInclusive", "new"]; pub const RANGE_INCLUSIVE_STD_NEW: [&str; 4] = ["std", "ops", "RangeInclusive", "new"]; From e5a1be8597c21c7b547a02231e5cf072dd3a0179 Mon Sep 17 00:00:00 2001 From: marmeladema Date: Sat, 2 May 2020 18:42:36 +0100 Subject: [PATCH 035/203] Use `LocalDefId` in `DumpVisitor::nest_tables` This is a partial fix for #71104 --- src/librustc_save_analysis/dump_visitor.rs | 70 +++++++++++++--------- src/librustc_typeck/check/mod.rs | 7 --- 2 files changed, 41 insertions(+), 36 deletions(-) diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs index ccce72fb0ac2..e2eb39c3e1cb 100644 --- a/src/librustc_save_analysis/dump_visitor.rs +++ b/src/librustc_save_analysis/dump_visitor.rs @@ -21,7 +21,7 @@ use rustc_ast::walk_list; use rustc_ast_pretty::pprust::{bounds_to_string, generic_params_to_string, ty_to_string}; use rustc_data_structures::fx::FxHashSet; use rustc_hir::def::{DefKind as HirDefKind, Res}; -use rustc_hir::def_id::DefId; +use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_middle::span_bug; use rustc_middle::ty::{self, DefIdTree, TyCtxt}; use rustc_session::config::Input; @@ -103,12 +103,10 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> { self.dumper.analysis() } - fn nest_tables(&mut self, item_id: NodeId, f: F) + fn nest_tables(&mut self, item_def_id: LocalDefId, f: F) where F: FnOnce(&mut Self), { - let item_def_id = self.tcx.hir().local_def_id_from_node_id(item_id); - let tables = if self.tcx.has_typeck_tables(item_def_id) { self.tcx.typeck_tables_of(item_def_id) } else { @@ -271,8 +269,9 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> { ) { debug!("process_method: {}:{}", id, ident); - let hir_id = self.tcx.hir().node_id_to_hir_id(id); - self.nest_tables(id, |v| { + let map = &self.tcx.hir(); + let hir_id = map.node_id_to_hir_id(id); + self.nest_tables(map.local_def_id(hir_id), |v| { if let Some(mut method_data) = v.save_ctxt.get_method_data(id, ident, span) { v.process_formals(&sig.decl.inputs, &method_data.qualname); v.process_generic_params(&generics, &method_data.qualname, id); @@ -295,7 +294,8 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> { // start walking from the newly-created definition. match sig.header.asyncness { ast::Async::Yes { return_impl_trait_id, .. } => { - v.nest_tables(return_impl_trait_id, |v| v.visit_ty(ret_ty)) + let hir_id = map.node_id_to_hir_id(return_impl_trait_id); + v.nest_tables(map.local_def_id(hir_id), |v| v.visit_ty(ret_ty)) } _ => v.visit_ty(ret_ty), } @@ -363,8 +363,9 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> { ty_params: &'l ast::Generics, body: Option<&'l ast::Block>, ) { - let hir_id = self.tcx.hir().node_id_to_hir_id(item.id); - self.nest_tables(item.id, |v| { + let map = &self.tcx.hir(); + let hir_id = map.node_id_to_hir_id(item.id); + self.nest_tables(map.local_def_id(hir_id), |v| { if let Some(fn_data) = v.save_ctxt.get_item_data(item) { down_cast_data!(fn_data, DefData, item.span); v.process_formals(&decl.inputs, &fn_data.qualname); @@ -388,7 +389,8 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> { // start walking from the newly-created definition. match header.asyncness { ast::Async::Yes { return_impl_trait_id, .. } => { - v.nest_tables(return_impl_trait_id, |v| v.visit_ty(ret_ty)) + let hir_id = map.node_id_to_hir_id(return_impl_trait_id); + v.nest_tables(map.local_def_id(hir_id), |v| v.visit_ty(ret_ty)) } _ => v.visit_ty(ret_ty), } @@ -406,7 +408,7 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> { expr: Option<&'l ast::Expr>, ) { let hir_id = self.tcx.hir().node_id_to_hir_id(item.id); - self.nest_tables(item.id, |v| { + self.nest_tables(self.tcx.hir().local_def_id(hir_id), |v| { if let Some(var_data) = v.save_ctxt.get_item_data(item) { down_cast_data!(var_data, DefData, item.span); v.dumper.dump_def(&access_from!(v.save_ctxt, item, hir_id), var_data); @@ -426,15 +428,13 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> { vis: ast::Visibility, attrs: &'l [Attribute], ) { - let qualname = format!( - "::{}", - self.tcx.def_path_str(self.tcx.hir().local_def_id_from_node_id(id).to_def_id()) - ); + let hir_id = self.tcx.hir().node_id_to_hir_id(id); + let qualname = + format!("::{}", self.tcx.def_path_str(self.tcx.hir().local_def_id(hir_id).to_def_id())); if !self.span.filter_generated(ident.span) { let sig = sig::assoc_const_signature(id, ident.name, typ, expr, &self.save_ctxt); let span = self.span_from_span(ident.span); - let hir_id = self.tcx.hir().node_id_to_hir_id(id); self.dumper.dump_def( &access_from_vis!(self.save_ctxt, vis, hir_id), @@ -456,7 +456,7 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> { } // walk type and init value - self.nest_tables(id, |v| { + self.nest_tables(self.tcx.hir().local_def_id(hir_id), |v| { v.visit_ty(typ); if let Some(expr) = expr { v.visit_expr(expr); @@ -473,10 +473,9 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> { ) { debug!("process_struct {:?} {:?}", item, item.span); let name = item.ident.to_string(); - let qualname = format!( - "::{}", - self.tcx.def_path_str(self.tcx.hir().local_def_id_from_node_id(item.id).to_def_id()) - ); + let hir_id = self.tcx.hir().node_id_to_hir_id(item.id); + let qualname = + format!("::{}", self.tcx.def_path_str(self.tcx.hir().local_def_id(hir_id).to_def_id())); let kind = match item.kind { ast::ItemKind::Struct(_, _) => DefKind::Struct, @@ -508,7 +507,6 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> { if !self.span.filter_generated(item.ident.span) { let span = self.span_from_span(item.ident.span); - let hir_id = self.tcx.hir().node_id_to_hir_id(item.id); self.dumper.dump_def( &access_from!(self.save_ctxt, item, hir_id), Def { @@ -528,7 +526,7 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> { ); } - self.nest_tables(item.id, |v| { + self.nest_tables(self.tcx.hir().local_def_id(hir_id), |v| { for field in def.fields() { v.process_struct_field_def(field, item.id); v.visit_ty(&field.ty); @@ -668,14 +666,15 @@ impl<'l, 'tcx> DumpVisitor<'l, 'tcx> { } let map = &self.tcx.hir(); - self.nest_tables(item.id, |v| { + let hir_id = map.node_id_to_hir_id(item.id); + self.nest_tables(map.local_def_id(hir_id), |v| { v.visit_ty(&typ); if let &Some(ref trait_ref) = trait_ref { v.process_path(trait_ref.ref_id, &trait_ref.path); } v.process_generic_params(generics, "", item.id); for impl_item in impl_items { - v.process_impl_item(impl_item, map.local_def_id_from_node_id(item.id).to_def_id()); + v.process_impl_item(impl_item, map.local_def_id(hir_id).to_def_id()); } }); } @@ -1410,7 +1409,10 @@ impl<'l, 'tcx> Visitor<'l> for DumpVisitor<'l, 'tcx> { } ast::TyKind::Array(ref element, ref length) => { self.visit_ty(element); - self.nest_tables(length.id, |v| v.visit_expr(&length.value)); + let hir_id = self.tcx.hir().node_id_to_hir_id(length.id); + self.nest_tables(self.tcx.hir().local_def_id(hir_id), |v| { + v.visit_expr(&length.value) + }); } ast::TyKind::ImplTrait(id, ref bounds) => { // FIXME: As of writing, the opaque type lowering introduces @@ -1422,7 +1424,13 @@ impl<'l, 'tcx> Visitor<'l> for DumpVisitor<'l, 'tcx> { // bounds... // This will panic if called on return type `impl Trait`, which // we guard against in `process_fn`. - self.nest_tables(id, |v| v.process_bounds(bounds)); + // FIXME(#71104) Should really be using just `node_id_to_hir_id` but + // some `NodeId` do not seem to have a corresponding HirId. + if let Some(hir_id) = self.tcx.hir().opt_node_id_to_hir_id(id) { + self.nest_tables(self.tcx.hir().local_def_id(hir_id), |v| { + v.process_bounds(bounds) + }); + } } _ => visit::walk_ty(self, t), } @@ -1470,7 +1478,8 @@ impl<'l, 'tcx> Visitor<'l> for DumpVisitor<'l, 'tcx> { } // walk the body - self.nest_tables(ex.id, |v| { + let hir_id = self.tcx.hir().node_id_to_hir_id(ex.id); + self.nest_tables(self.tcx.hir().local_def_id(hir_id), |v| { v.process_formals(&decl.inputs, &id); v.visit_expr(body) }); @@ -1487,7 +1496,10 @@ impl<'l, 'tcx> Visitor<'l> for DumpVisitor<'l, 'tcx> { } ast::ExprKind::Repeat(ref element, ref count) => { self.visit_expr(element); - self.nest_tables(count.id, |v| v.visit_expr(&count.value)); + let hir_id = self.tcx.hir().node_id_to_hir_id(count.id); + self.nest_tables(self.tcx.hir().local_def_id(hir_id), |v| { + v.visit_expr(&count.value) + }); } // In particular, we take this branch for call and path expressions, // where we'll index the idents involved just by continuing to walk. diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index adbab3d4cb62..d95eb5f28fe1 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -831,13 +831,6 @@ fn primary_body_of( } fn has_typeck_tables(tcx: TyCtxt<'_>, def_id: DefId) -> bool { - // FIXME(#71104) some `LocalDefId` do not seem to have a corresponding `HirId`. - if let Some(def_id) = def_id.as_local() { - if tcx.hir().opt_local_def_id_to_hir_id(def_id).is_none() { - return false; - } - } - // Closures' tables come from their outermost function, // as they are part of the same "inference environment". let outer_def_id = tcx.closure_base_def_id(def_id); From c9f1162a6ffc81adcb114a616899edad0f7d0750 Mon Sep 17 00:00:00 2001 From: Laurence Tratt Date: Mon, 4 May 2020 10:17:39 +0100 Subject: [PATCH 036/203] Rephrase the any::type_name docs a bit. This attempts to be a little clearer (including in terminology) about the lack of guarantees that any::type_name provides. --- src/libcore/any.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/libcore/any.rs b/src/libcore/any.rs index 39df803bbea3..67698e5409f6 100644 --- a/src/libcore/any.rs +++ b/src/libcore/any.rs @@ -446,14 +446,14 @@ impl TypeId { /// # Note /// /// This is intended for diagnostic use. The exact contents and format of the -/// string are not specified, other than being a best-effort description of the -/// type. For example, `type_name::>()` could return the -/// `"Option"` or `"std::option::Option"`, but not -/// `"foobar"`. In addition, the output may change between versions of the -/// compiler. +/// string retrned are not specified, other than being a best-effort description +/// of the type. For example, amongst the strings +/// that `type_name::>()` might map to are `"Option"` and +/// `"std::option::Option"`. /// -/// The type name should not be considered a unique identifier of a type; -/// multiple types may share the same type name. +/// The returned string must not be considered to be a unique identifier of a +/// type as multiple types may map to the same type name. In addition, the +/// output may change between versions of the compiler. /// /// The current implementation uses the same infrastructure as compiler /// diagnostics and debuginfo, but this is not guaranteed. From 93f877ce870e9fd13ad7c6a05ccb4abd46a3d106 Mon Sep 17 00:00:00 2001 From: Laurence Tratt Date: Mon, 4 May 2020 11:01:31 +0100 Subject: [PATCH 037/203] Document that lifetimes do not currently appear in any::type_name()'s output. --- src/libcore/any.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/libcore/any.rs b/src/libcore/any.rs index 67698e5409f6..2628f8903323 100644 --- a/src/libcore/any.rs +++ b/src/libcore/any.rs @@ -452,7 +452,9 @@ impl TypeId { /// `"std::option::Option"`. /// /// The returned string must not be considered to be a unique identifier of a -/// type as multiple types may map to the same type name. In addition, the +/// type as multiple types may map to the same type name. Similarly, there is no +/// guarantee that all parts of a type will appear in the returned string: for +/// example, lifetime specifiers are currently not included. In addition, the /// output may change between versions of the compiler. /// /// The current implementation uses the same infrastructure as compiler From 7744cf4e53c4e19e5753e2063be420b9d0c0d38a Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Mon, 4 May 2020 15:13:07 +0200 Subject: [PATCH 038/203] Update to rustc changes --- clippy_lints/src/redundant_clone.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/redundant_clone.rs b/clippy_lints/src/redundant_clone.rs index d5cace0c6474..d563eb886ae7 100644 --- a/clippy_lints/src/redundant_clone.rs +++ b/clippy_lints/src/redundant_clone.rs @@ -591,7 +591,7 @@ struct PossibleBorrowerMap<'a, 'tcx> { impl PossibleBorrowerMap<'_, '_> { /// Returns true if the set of borrowers of `borrowed` living at `at` matches with `borrowers`. fn only_borrowers(&mut self, borrowers: &[mir::Local], borrowed: mir::Local, at: mir::Location) -> bool { - self.maybe_live.seek_after(at); + self.maybe_live.seek_after_primary_effect(at); self.bitset.0.clear(); let maybe_live = &mut self.maybe_live; From 876001c8ac331a15661638fbb18b8b64facf2c96 Mon Sep 17 00:00:00 2001 From: Laurence Tratt Date: Mon, 4 May 2020 14:28:58 +0100 Subject: [PATCH 039/203] Fix typo. --- src/libcore/any.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libcore/any.rs b/src/libcore/any.rs index 2628f8903323..996a9cdfc4d9 100644 --- a/src/libcore/any.rs +++ b/src/libcore/any.rs @@ -446,8 +446,8 @@ impl TypeId { /// # Note /// /// This is intended for diagnostic use. The exact contents and format of the -/// string retrned are not specified, other than being a best-effort description -/// of the type. For example, amongst the strings +/// string returned are not specified, other than being a best-effort +/// description of the type. For example, amongst the strings /// that `type_name::>()` might map to are `"Option"` and /// `"std::option::Option"`. /// From 5cb2fa487bf6405a18c13041bc18544884f603a7 Mon Sep 17 00:00:00 2001 From: Dolpheyn Date: Mon, 4 May 2020 22:14:25 +0800 Subject: [PATCH 040/203] Document From trait for Option implementations --- src/libcore/option.rs | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/src/libcore/option.rs b/src/libcore/option.rs index 63a5277100fa..a87f3c1804cb 100644 --- a/src/libcore/option.rs +++ b/src/libcore/option.rs @@ -1357,12 +1357,38 @@ impl<'a, T> IntoIterator for &'a mut Option { #[stable(since = "1.12.0", feature = "option_from")] impl From for Option { + /// Copies val to a new Option::Some + /// + /// # Examples + /// + /// ``` + /// let o: Option = Option::from(67); + /// assert_eq!(Some(67), o); + /// ``` fn from(val: T) -> Option { Some(val) } } #[stable(feature = "option_ref_from_ref_option", since = "1.30.0")] + /// Converts from &Option to Option<&T> + /// + /// # Examples + /// Converts an `Option<`[`String`]`>` into an `Option<`[`usize`]`>`, preserving the original. + /// The [`map`] method takes the `self` argument by value, consuming the original, + /// so this technique uses `as_ref` to first take an `Option` to a reference + /// to the value inside the original. + /// + /// [`map`]: enum.Option.html#method.map + /// [`String`]: ../../std/string/struct.String.html + /// [`usize`]: ../../std/primitive.usize.html + /// + /// ``` + /// let s: Option = Some(String::from("Hello, Rustaceans!")); + /// let o: Option = Option::from(&s).map(|ss: &String| ss.len()); + /// println!("Can still print s: {}", s); + /// assert_eq!(o, Some(18)); + /// ``` impl<'a, T> From<&'a Option> for Option<&'a T> { fn from(o: &'a Option) -> Option<&'a T> { o.as_ref() @@ -1371,6 +1397,19 @@ impl<'a, T> From<&'a Option> for Option<&'a T> { #[stable(feature = "option_ref_from_ref_option", since = "1.30.0")] impl<'a, T> From<&'a mut Option> for Option<&'a mut T> { + /// Converts from &mut Option to Option<&mut T> + /// + /// # Examples + /// + /// ``` + /// let mut s = Some(String::from("Hello")); + /// let o: Option<&mut String> = Option::from(&mut s); + /// match o { + /// Some(t) => *t = String::from("Hello, Rustaceans!"), + /// None => (), + /// } + /// assert_eq!(s, Some(String::from("Hello, Rustaceans!"))); + /// ``` fn from(o: &'a mut Option) -> Option<&'a mut T> { o.as_mut() } From 3471bc8306e206ed7d5cc86b1eeadc9a8bb8bc76 Mon Sep 17 00:00:00 2001 From: mibac138 <5672750+mibac138@users.noreply.github.com> Date: Tue, 5 May 2020 01:55:03 +0200 Subject: [PATCH 041/203] Fix unused_parens false positive when using binary operations --- src/librustc_lint/unused.rs | 16 ++++++++++++---- .../ui/lint/issue-71290-unused-paren-binop.rs | 17 +++++++++++++++++ 2 files changed, 29 insertions(+), 4 deletions(-) create mode 100644 src/test/ui/lint/issue-71290-unused-paren-binop.rs diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs index ddd252cb290e..4f7a1f9c3109 100644 --- a/src/librustc_lint/unused.rs +++ b/src/librustc_lint/unused.rs @@ -380,11 +380,19 @@ trait UnusedDelimLint { ); fn is_expr_delims_necessary(inner: &ast::Expr, followed_by_block: bool) -> bool { - followed_by_block - && match inner.kind { - ExprKind::Ret(_) | ExprKind::Break(..) => true, - _ => parser::contains_exterior_struct_lit(&inner), + // Prevent false-positives in cases like `fn x() -> u8 { ({ 0 } + 1) }` + let lhs_needs_parens = match &inner.kind { + ExprKind::Binary(_, lhs, _rhs) => { + !rustc_ast::util::classify::expr_requires_semi_to_be_stmt(&*lhs) } + _ => false, + }; + lhs_needs_parens + || (followed_by_block + && match inner.kind { + ExprKind::Ret(_) | ExprKind::Break(..) => true, + _ => parser::contains_exterior_struct_lit(&inner), + }) } fn emit_unused_delims_expr( diff --git a/src/test/ui/lint/issue-71290-unused-paren-binop.rs b/src/test/ui/lint/issue-71290-unused-paren-binop.rs new file mode 100644 index 000000000000..619be02566f5 --- /dev/null +++ b/src/test/ui/lint/issue-71290-unused-paren-binop.rs @@ -0,0 +1,17 @@ +// check-pass +// Make sure unused parens lint doesn't emit a false positive. +// See https://github.com/rust-lang/rust/issues/71290 for details. + +fn x() -> u8 { + ({ 0 }) + 1 +} + +fn y() -> u8 { + ({ 0 } + 1) +} + +pub fn foo(a: bool, b: bool) -> u8 { + (if a { 1 } else { 0 } + if b { 1 } else { 0 }) +} + +fn main() {} From 73f07a47b892216c47a741e229924b90a86585e1 Mon Sep 17 00:00:00 2001 From: Dolpheyn Date: Tue, 5 May 2020 08:25:20 +0800 Subject: [PATCH 042/203] Fix comment position --- src/libcore/option.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcore/option.rs b/src/libcore/option.rs index a87f3c1804cb..480fe4fd4bef 100644 --- a/src/libcore/option.rs +++ b/src/libcore/option.rs @@ -1371,6 +1371,7 @@ impl From for Option { } #[stable(feature = "option_ref_from_ref_option", since = "1.30.0")] +impl<'a, T> From<&'a Option> for Option<&'a T> { /// Converts from &Option to Option<&T> /// /// # Examples @@ -1389,7 +1390,6 @@ impl From for Option { /// println!("Can still print s: {}", s); /// assert_eq!(o, Some(18)); /// ``` -impl<'a, T> From<&'a Option> for Option<&'a T> { fn from(o: &'a Option) -> Option<&'a T> { o.as_ref() } From 2badd41d043c9ff549855ad832e7bcd2ad44970d Mon Sep 17 00:00:00 2001 From: Dolpheyn Date: Tue, 5 May 2020 09:50:59 +0800 Subject: [PATCH 043/203] Fix example --- src/libcore/option.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcore/option.rs b/src/libcore/option.rs index 480fe4fd4bef..4647ad010067 100644 --- a/src/libcore/option.rs +++ b/src/libcore/option.rs @@ -1387,7 +1387,7 @@ impl<'a, T> From<&'a Option> for Option<&'a T> { /// ``` /// let s: Option = Some(String::from("Hello, Rustaceans!")); /// let o: Option = Option::from(&s).map(|ss: &String| ss.len()); - /// println!("Can still print s: {}", s); + /// println!("Can still print s: {:?}", s); /// assert_eq!(o, Some(18)); /// ``` fn from(o: &'a Option) -> Option<&'a T> { From 780a63a1ba84597eaf33e4d546bcf0edd6225836 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Tue, 5 May 2020 15:11:59 +0200 Subject: [PATCH 044/203] Update ui tests --- tests/ui/builtin-type-shadow.stderr | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/ui/builtin-type-shadow.stderr b/tests/ui/builtin-type-shadow.stderr index b6a4adde8488..bc785b075e02 100644 --- a/tests/ui/builtin-type-shadow.stderr +++ b/tests/ui/builtin-type-shadow.stderr @@ -18,8 +18,6 @@ LL | 42 | = note: expected type parameter `u32` found type `{integer}` - = help: type parameters must be constrained to match other types - = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters error: aborting due to 2 previous errors From 717a7a8486a448d7c746db213d1d987593088692 Mon Sep 17 00:00:00 2001 From: Michael <5672750+mibac138@users.noreply.github.com> Date: Tue, 5 May 2020 16:58:13 +0200 Subject: [PATCH 045/203] Update src/test/ui/lint/issue-71290-unused-paren-binop.rs Co-authored-by: Bastian Kauschke --- src/test/ui/lint/issue-71290-unused-paren-binop.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/test/ui/lint/issue-71290-unused-paren-binop.rs b/src/test/ui/lint/issue-71290-unused-paren-binop.rs index 619be02566f5..f11d2d377378 100644 --- a/src/test/ui/lint/issue-71290-unused-paren-binop.rs +++ b/src/test/ui/lint/issue-71290-unused-paren-binop.rs @@ -1,6 +1,7 @@ // check-pass // Make sure unused parens lint doesn't emit a false positive. // See https://github.com/rust-lang/rust/issues/71290 for details. +#![deny(unused_parens)] fn x() -> u8 { ({ 0 }) + 1 From 6f7e9a842debd31590d8f347bd4f7534159d6a91 Mon Sep 17 00:00:00 2001 From: mibac138 <5672750+mibac138@users.noreply.github.com> Date: Tue, 5 May 2020 18:43:37 +0200 Subject: [PATCH 046/203] Add strikethrough support to rustdoc --- src/librustdoc/html/markdown.rs | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index 4bb50f757919..bdda45fdcd4d 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -44,7 +44,7 @@ use pulldown_cmark::{html, CodeBlockKind, CowStr, Event, Options, Parser, Tag}; mod tests; fn opts() -> Options { - Options::ENABLE_TABLES | Options::ENABLE_FOOTNOTES + Options::ENABLE_TABLES | Options::ENABLE_FOOTNOTES | Options::ENABLE_STRIKETHROUGH } /// When `to_string` is called, this struct will emit the HTML corresponding to @@ -933,7 +933,11 @@ impl MarkdownSummaryLine<'_> { } }; - let p = Parser::new_with_broken_link_callback(md, Options::empty(), Some(&replacer)); + let p = Parser::new_with_broken_link_callback( + md, + Options::ENABLE_STRIKETHROUGH, + Some(&replacer), + ); let mut s = String::new(); @@ -975,7 +979,11 @@ pub fn plain_summary_line(md: &str) -> String { } } let mut s = String::with_capacity(md.len() * 3 / 2); - let p = ParserWrapper { inner: Parser::new(md), is_in: 0, is_first: true }; + let p = ParserWrapper { + inner: Parser::new_ext(md, Options::ENABLE_STRIKETHROUGH), + is_in: 0, + is_first: true, + }; p.filter(|t| !t.is_empty()).for_each(|i| s.push_str(&i)); s } From 4b7a92838c98929a9f4c7a64583b5ea49ebb3a35 Mon Sep 17 00:00:00 2001 From: mibac138 <5672750+mibac138@users.noreply.github.com> Date: Wed, 6 May 2020 01:50:55 +0200 Subject: [PATCH 047/203] Fix unused_parens nested binary op false positive --- src/librustc_lint/unused.rs | 16 ++++++++++++---- .../ui/lint/issue-71290-unused-paren-binop.rs | 5 +++++ 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs index 4f7a1f9c3109..c24079a6e4be 100644 --- a/src/librustc_lint/unused.rs +++ b/src/librustc_lint/unused.rs @@ -381,12 +381,20 @@ trait UnusedDelimLint { fn is_expr_delims_necessary(inner: &ast::Expr, followed_by_block: bool) -> bool { // Prevent false-positives in cases like `fn x() -> u8 { ({ 0 } + 1) }` - let lhs_needs_parens = match &inner.kind { - ExprKind::Binary(_, lhs, _rhs) => { - !rustc_ast::util::classify::expr_requires_semi_to_be_stmt(&*lhs) + let lhs_needs_parens = { + let mut innermost = inner; + loop { + if let ExprKind::Binary(_, lhs, _rhs) = &innermost.kind { + innermost = lhs; + if !rustc_ast::util::classify::expr_requires_semi_to_be_stmt(innermost) { + break true; + } + } else { + break false; + } } - _ => false, }; + lhs_needs_parens || (followed_by_block && match inner.kind { diff --git a/src/test/ui/lint/issue-71290-unused-paren-binop.rs b/src/test/ui/lint/issue-71290-unused-paren-binop.rs index f11d2d377378..24d77e36d94f 100644 --- a/src/test/ui/lint/issue-71290-unused-paren-binop.rs +++ b/src/test/ui/lint/issue-71290-unused-paren-binop.rs @@ -15,4 +15,9 @@ pub fn foo(a: bool, b: bool) -> u8 { (if a { 1 } else { 0 } + if b { 1 } else { 0 }) } +pub fn bar() -> u8 { + // Make sure nested expressions are handled correctly as well + ({ 0 } + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9) +} + fn main() {} From a1ebb94775daa63cb105cc1c410022c20002667b Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Wed, 6 May 2020 19:28:48 +0200 Subject: [PATCH 048/203] Const prop aggregates even if partially or fully modified --- src/librustc_mir/transform/const_prop.rs | 100 ++++++++++-------- .../mir-opt/const_prop/mutable_variable.rs | 8 ++ .../rustc.main.ConstProp.diff | 53 ++++++++++ .../const_prop/mutable_variable_aggregate.rs | 8 ++ .../rustc.main.ConstProp.diff | 67 ++++++++++++ .../mutable_variable_aggregate_mut_ref.rs | 9 ++ .../rustc.main.ConstProp.diff | 58 ++++++++++ .../const_prop/mutable_variable_no_prop.rs | 12 +++ .../rustc.main.ConstProp.diff | 69 ++++++++++++ 9 files changed, 342 insertions(+), 42 deletions(-) create mode 100644 src/test/mir-opt/const_prop/mutable_variable.rs create mode 100644 src/test/mir-opt/const_prop/mutable_variable/rustc.main.ConstProp.diff create mode 100644 src/test/mir-opt/const_prop/mutable_variable_aggregate.rs create mode 100644 src/test/mir-opt/const_prop/mutable_variable_aggregate/rustc.main.ConstProp.diff create mode 100644 src/test/mir-opt/const_prop/mutable_variable_aggregate_mut_ref.rs create mode 100644 src/test/mir-opt/const_prop/mutable_variable_aggregate_mut_ref/rustc.main.ConstProp.diff create mode 100644 src/test/mir-opt/const_prop/mutable_variable_no_prop.rs create mode 100644 src/test/mir-opt/const_prop/mutable_variable_no_prop/rustc.main.ConstProp.diff diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index 7926bf535b3b..4dd7c0330530 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -349,8 +349,8 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { } } - fn get_const(&self, local: Local) -> Option> { - let op = self.ecx.access_local(self.ecx.frame(), local, None).ok(); + fn get_const(&self, place: Place<'tcx>) -> Option> { + let op = self.ecx.eval_place_to_op(place, None).ok(); // Try to read the local as an immediate so that if it is representable as a scalar, we can // handle it as such, but otherwise, just return the value as is. @@ -772,13 +772,25 @@ impl<'tcx> Visitor<'tcx> for CanConstProp { fn visit_local(&mut self, &local: &Local, context: PlaceContext, _: Location) { use rustc_middle::mir::visit::PlaceContext::*; match context { - // Constants must have at most one write - // FIXME(oli-obk): we could be more powerful here, if the multiple writes - // only occur in independent execution paths - MutatingUse(MutatingUseContext::Store) => { + // Projections are fine, because `&mut foo.x` will be caught by + // `MutatingUseContext::Borrow` elsewhere. + MutatingUse(MutatingUseContext::Projection) + | MutatingUse(MutatingUseContext::Store) => { if !self.found_assignment.insert(local) { - trace!("local {:?} can't be propagated because of multiple assignments", local); - self.can_const_prop[local] = ConstPropMode::NoPropagation; + match &mut self.can_const_prop[local] { + // If the local can only get propagated in its own block, then we don't have + // to worry about multiple assignments, as we'll nuke the const state at the + // end of the block anyway, and inside the block we overwrite previous + // states as applicable. + ConstPropMode::OnlyInsideOwnBlock => {} + other => { + trace!( + "local {:?} can't be propagated because of multiple assignments", + local, + ); + *other = ConstPropMode::NoPropagation; + } + } } } // Reading constants is allowed an arbitrary number of times @@ -787,12 +799,6 @@ impl<'tcx> Visitor<'tcx> for CanConstProp { | NonMutatingUse(NonMutatingUseContext::Inspect) | NonMutatingUse(NonMutatingUseContext::Projection) | NonUse(_) => {} - // FIXME(felix91gr): explain the reasoning behind this - MutatingUse(MutatingUseContext::Projection) => { - if self.local_kinds[local] != LocalKind::Temp { - self.can_const_prop[local] = ConstPropMode::NoPropagation; - } - } _ => { trace!("local {:?} can't be propagaged because it's used: {:?}", local, context); self.can_const_prop[local] = ConstPropMode::NoPropagation; @@ -826,40 +832,50 @@ impl<'mir, 'tcx> MutVisitor<'tcx> for ConstPropagator<'mir, 'tcx> { if let StatementKind::Assign(box (place, ref mut rval)) = statement.kind { let place_ty: Ty<'tcx> = place.ty(&self.local_decls, self.tcx).ty; if let Ok(place_layout) = self.tcx.layout_of(self.param_env.and(place_ty)) { - if let Some(local) = place.as_local() { - let can_const_prop = self.can_const_prop[local]; - if let Some(()) = self.const_prop(rval, place_layout, source_info, place) { - if can_const_prop != ConstPropMode::NoPropagation { - // This will return None for Locals that are from other blocks, - // so it should be okay to propagate from here on down. - if let Some(value) = self.get_const(local) { - if self.should_const_prop(value) { - trace!("replacing {:?} with {:?}", rval, value); - self.replace_with_const(rval, value, statement.source_info); - if can_const_prop == ConstPropMode::FullConstProp - || can_const_prop == ConstPropMode::OnlyInsideOwnBlock - { - trace!("propagated into {:?}", local); - } - } - if can_const_prop == ConstPropMode::OnlyInsideOwnBlock { - trace!( - "found local restricted to its block. Will remove it from const-prop after block is finished. Local: {:?}", - local - ); - self.locals_of_current_block.insert(local); + let can_const_prop = self.can_const_prop[place.local]; + if let Some(()) = self.const_prop(rval, place_layout, source_info, place) { + if can_const_prop != ConstPropMode::NoPropagation { + // This will return None for variables that are from other blocks, + // so it should be okay to propagate from here on down. + if let Some(value) = self.get_const(place) { + if self.should_const_prop(value) { + trace!("replacing {:?} with {:?}", rval, value); + self.replace_with_const(rval, value, statement.source_info); + if can_const_prop == ConstPropMode::FullConstProp + || can_const_prop == ConstPropMode::OnlyInsideOwnBlock + { + trace!("propagated into {:?}", place); } } + if can_const_prop == ConstPropMode::OnlyInsideOwnBlock { + trace!( + "found local restricted to its block. Will remove it from const-prop after block is finished. Local: {:?}", + place.local + ); + self.locals_of_current_block.insert(place.local); + } } } - if self.can_const_prop[local] == ConstPropMode::OnlyPropagateInto - || self.can_const_prop[local] == ConstPropMode::NoPropagation + if can_const_prop == ConstPropMode::OnlyPropagateInto + || can_const_prop == ConstPropMode::NoPropagation { - trace!("can't propagate into {:?}", local); - if local != RETURN_PLACE { - Self::remove_const(&mut self.ecx, local); + trace!("can't propagate into {:?}", place); + if place.local != RETURN_PLACE { + Self::remove_const(&mut self.ecx, place.local); } } + } else { + // Const prop failed, so erase the destination, ensuring that whatever happens + // from here on, does not know about the previous value. + // This is important in case we have + // ```rust + // let mut x = 42; + // x = SOME_MUTABLE_STATIC; + // // x must now be undefined + // ``` + // FIXME: we overzealously erase the entire local, because that's easier to + // implement. + Self::remove_const(&mut self.ecx, place.local); } } } else { @@ -993,7 +1009,7 @@ impl<'mir, 'tcx> MutVisitor<'tcx> for ConstPropagator<'mir, 'tcx> { arguments are of the variant `Operand::Copy`. This allows us to simplify our handling of `Operands` in this case. */ - if let Some(l) = opr.place().and_then(|p| p.as_local()) { + if let Some(l) = opr.place() { if let Some(value) = self.get_const(l) { if self.should_const_prop(value) { // FIXME(felix91gr): this code only handles `Scalar` cases. diff --git a/src/test/mir-opt/const_prop/mutable_variable.rs b/src/test/mir-opt/const_prop/mutable_variable.rs new file mode 100644 index 000000000000..b3a2d80fa950 --- /dev/null +++ b/src/test/mir-opt/const_prop/mutable_variable.rs @@ -0,0 +1,8 @@ +// compile-flags: -O + +// EMIT_MIR rustc.main.ConstProp.diff +fn main() { + let mut x = 42; + x = 99; + let y = x; +} diff --git a/src/test/mir-opt/const_prop/mutable_variable/rustc.main.ConstProp.diff b/src/test/mir-opt/const_prop/mutable_variable/rustc.main.ConstProp.diff new file mode 100644 index 000000000000..c6c5b0cf7263 --- /dev/null +++ b/src/test/mir-opt/const_prop/mutable_variable/rustc.main.ConstProp.diff @@ -0,0 +1,53 @@ +- // MIR for `main` before ConstProp ++ // MIR for `main` after ConstProp + + fn main() -> () { + let mut _0: (); // return place in scope 0 at $DIR/mutable_variable.rs:4:11: 4:11 + let mut _1: i32; // in scope 0 at $DIR/mutable_variable.rs:5:9: 5:14 + scope 1 { + debug x => _1; // in scope 1 at $DIR/mutable_variable.rs:5:9: 5:14 + let _2: i32; // in scope 1 at $DIR/mutable_variable.rs:7:9: 7:10 + scope 2 { + debug y => _2; // in scope 2 at $DIR/mutable_variable.rs:7:9: 7:10 + } + } + + bb0: { + StorageLive(_1); // scope 0 at $DIR/mutable_variable.rs:5:9: 5:14 + _1 = const 42i32; // scope 0 at $DIR/mutable_variable.rs:5:17: 5:19 + // ty::Const + // + ty: i32 + // + val: Value(Scalar(0x0000002a)) + // mir::Constant + // + span: $DIR/mutable_variable.rs:5:17: 5:19 + // + literal: Const { ty: i32, val: Value(Scalar(0x0000002a)) } + _1 = const 99i32; // scope 1 at $DIR/mutable_variable.rs:6:5: 6:11 + // ty::Const + // + ty: i32 + // + val: Value(Scalar(0x00000063)) + // mir::Constant +- // + span: $DIR/mutable_variable.rs:6:9: 6:11 ++ // + span: $DIR/mutable_variable.rs:6:5: 6:11 + // + literal: Const { ty: i32, val: Value(Scalar(0x00000063)) } + StorageLive(_2); // scope 1 at $DIR/mutable_variable.rs:7:9: 7:10 +- _2 = _1; // scope 1 at $DIR/mutable_variable.rs:7:13: 7:14 ++ _2 = const 99i32; // scope 1 at $DIR/mutable_variable.rs:7:13: 7:14 ++ // ty::Const ++ // + ty: i32 ++ // + val: Value(Scalar(0x00000063)) ++ // mir::Constant ++ // + span: $DIR/mutable_variable.rs:7:13: 7:14 ++ // + literal: Const { ty: i32, val: Value(Scalar(0x00000063)) } + _0 = const (); // scope 0 at $DIR/mutable_variable.rs:4:11: 8:2 + // ty::Const + // + ty: () + // + val: Value(Scalar()) + // mir::Constant + // + span: $DIR/mutable_variable.rs:4:11: 8:2 + // + literal: Const { ty: (), val: Value(Scalar()) } + StorageDead(_2); // scope 1 at $DIR/mutable_variable.rs:8:1: 8:2 + StorageDead(_1); // scope 0 at $DIR/mutable_variable.rs:8:1: 8:2 + return; // scope 0 at $DIR/mutable_variable.rs:8:2: 8:2 + } + } + diff --git a/src/test/mir-opt/const_prop/mutable_variable_aggregate.rs b/src/test/mir-opt/const_prop/mutable_variable_aggregate.rs new file mode 100644 index 000000000000..3c5fb4574b61 --- /dev/null +++ b/src/test/mir-opt/const_prop/mutable_variable_aggregate.rs @@ -0,0 +1,8 @@ +// compile-flags: -O + +// EMIT_MIR rustc.main.ConstProp.diff +fn main() { + let mut x = (42, 43); + x.1 = 99; + let y = x; +} diff --git a/src/test/mir-opt/const_prop/mutable_variable_aggregate/rustc.main.ConstProp.diff b/src/test/mir-opt/const_prop/mutable_variable_aggregate/rustc.main.ConstProp.diff new file mode 100644 index 000000000000..26f0250d94c0 --- /dev/null +++ b/src/test/mir-opt/const_prop/mutable_variable_aggregate/rustc.main.ConstProp.diff @@ -0,0 +1,67 @@ +- // MIR for `main` before ConstProp ++ // MIR for `main` after ConstProp + + fn main() -> () { + let mut _0: (); // return place in scope 0 at $DIR/mutable_variable_aggregate.rs:4:11: 4:11 + let mut _1: (i32, i32); // in scope 0 at $DIR/mutable_variable_aggregate.rs:5:9: 5:14 + scope 1 { + debug x => _1; // in scope 1 at $DIR/mutable_variable_aggregate.rs:5:9: 5:14 + let _2: (i32, i32); // in scope 1 at $DIR/mutable_variable_aggregate.rs:7:9: 7:10 + scope 2 { + debug y => _2; // in scope 2 at $DIR/mutable_variable_aggregate.rs:7:9: 7:10 + } + } + + bb0: { + StorageLive(_1); // scope 0 at $DIR/mutable_variable_aggregate.rs:5:9: 5:14 + _1 = (const 42i32, const 43i32); // scope 0 at $DIR/mutable_variable_aggregate.rs:5:17: 5:25 + // ty::Const + // + ty: i32 + // + val: Value(Scalar(0x0000002a)) + // mir::Constant +- // + span: $DIR/mutable_variable_aggregate.rs:5:18: 5:20 ++ // + span: $DIR/mutable_variable_aggregate.rs:5:17: 5:25 + // + literal: Const { ty: i32, val: Value(Scalar(0x0000002a)) } + // ty::Const + // + ty: i32 + // + val: Value(Scalar(0x0000002b)) + // mir::Constant +- // + span: $DIR/mutable_variable_aggregate.rs:5:22: 5:24 ++ // + span: $DIR/mutable_variable_aggregate.rs:5:17: 5:25 + // + literal: Const { ty: i32, val: Value(Scalar(0x0000002b)) } + (_1.1: i32) = const 99i32; // scope 1 at $DIR/mutable_variable_aggregate.rs:6:5: 6:13 + // ty::Const + // + ty: i32 + // + val: Value(Scalar(0x00000063)) + // mir::Constant +- // + span: $DIR/mutable_variable_aggregate.rs:6:11: 6:13 ++ // + span: $DIR/mutable_variable_aggregate.rs:6:5: 6:13 + // + literal: Const { ty: i32, val: Value(Scalar(0x00000063)) } + StorageLive(_2); // scope 1 at $DIR/mutable_variable_aggregate.rs:7:9: 7:10 +- _2 = _1; // scope 1 at $DIR/mutable_variable_aggregate.rs:7:13: 7:14 ++ _2 = (const 42i32, const 99i32); // scope 1 at $DIR/mutable_variable_aggregate.rs:7:13: 7:14 ++ // ty::Const ++ // + ty: i32 ++ // + val: Value(Scalar(0x0000002a)) ++ // mir::Constant ++ // + span: $DIR/mutable_variable_aggregate.rs:7:13: 7:14 ++ // + literal: Const { ty: i32, val: Value(Scalar(0x0000002a)) } ++ // ty::Const ++ // + ty: i32 ++ // + val: Value(Scalar(0x00000063)) ++ // mir::Constant ++ // + span: $DIR/mutable_variable_aggregate.rs:7:13: 7:14 ++ // + literal: Const { ty: i32, val: Value(Scalar(0x00000063)) } + _0 = const (); // scope 0 at $DIR/mutable_variable_aggregate.rs:4:11: 8:2 + // ty::Const + // + ty: () + // + val: Value(Scalar()) + // mir::Constant + // + span: $DIR/mutable_variable_aggregate.rs:4:11: 8:2 + // + literal: Const { ty: (), val: Value(Scalar()) } + StorageDead(_2); // scope 1 at $DIR/mutable_variable_aggregate.rs:8:1: 8:2 + StorageDead(_1); // scope 0 at $DIR/mutable_variable_aggregate.rs:8:1: 8:2 + return; // scope 0 at $DIR/mutable_variable_aggregate.rs:8:2: 8:2 + } + } + diff --git a/src/test/mir-opt/const_prop/mutable_variable_aggregate_mut_ref.rs b/src/test/mir-opt/const_prop/mutable_variable_aggregate_mut_ref.rs new file mode 100644 index 000000000000..fc13cbf2abd5 --- /dev/null +++ b/src/test/mir-opt/const_prop/mutable_variable_aggregate_mut_ref.rs @@ -0,0 +1,9 @@ +// compile-flags: -O + +// EMIT_MIR rustc.main.ConstProp.diff +fn main() { + let mut x = (42, 43); + let z = &mut x; + z.1 = 99; + let y = x; +} diff --git a/src/test/mir-opt/const_prop/mutable_variable_aggregate_mut_ref/rustc.main.ConstProp.diff b/src/test/mir-opt/const_prop/mutable_variable_aggregate_mut_ref/rustc.main.ConstProp.diff new file mode 100644 index 000000000000..44203ac327ab --- /dev/null +++ b/src/test/mir-opt/const_prop/mutable_variable_aggregate_mut_ref/rustc.main.ConstProp.diff @@ -0,0 +1,58 @@ +- // MIR for `main` before ConstProp ++ // MIR for `main` after ConstProp + + fn main() -> () { + let mut _0: (); // return place in scope 0 at $DIR/mutable_variable_aggregate_mut_ref.rs:4:11: 4:11 + let mut _1: (i32, i32); // in scope 0 at $DIR/mutable_variable_aggregate_mut_ref.rs:5:9: 5:14 + scope 1 { + debug x => _1; // in scope 1 at $DIR/mutable_variable_aggregate_mut_ref.rs:5:9: 5:14 + let _2: &mut (i32, i32); // in scope 1 at $DIR/mutable_variable_aggregate_mut_ref.rs:6:9: 6:10 + scope 2 { + debug z => _2; // in scope 2 at $DIR/mutable_variable_aggregate_mut_ref.rs:6:9: 6:10 + let _3: (i32, i32); // in scope 2 at $DIR/mutable_variable_aggregate_mut_ref.rs:8:9: 8:10 + scope 3 { + debug y => _3; // in scope 3 at $DIR/mutable_variable_aggregate_mut_ref.rs:8:9: 8:10 + } + } + } + + bb0: { + StorageLive(_1); // scope 0 at $DIR/mutable_variable_aggregate_mut_ref.rs:5:9: 5:14 + _1 = (const 42i32, const 43i32); // scope 0 at $DIR/mutable_variable_aggregate_mut_ref.rs:5:17: 5:25 + // ty::Const + // + ty: i32 + // + val: Value(Scalar(0x0000002a)) + // mir::Constant + // + span: $DIR/mutable_variable_aggregate_mut_ref.rs:5:18: 5:20 + // + literal: Const { ty: i32, val: Value(Scalar(0x0000002a)) } + // ty::Const + // + ty: i32 + // + val: Value(Scalar(0x0000002b)) + // mir::Constant + // + span: $DIR/mutable_variable_aggregate_mut_ref.rs:5:22: 5:24 + // + literal: Const { ty: i32, val: Value(Scalar(0x0000002b)) } + StorageLive(_2); // scope 1 at $DIR/mutable_variable_aggregate_mut_ref.rs:6:9: 6:10 + _2 = &mut _1; // scope 1 at $DIR/mutable_variable_aggregate_mut_ref.rs:6:13: 6:19 + ((*_2).1: i32) = const 99i32; // scope 2 at $DIR/mutable_variable_aggregate_mut_ref.rs:7:5: 7:13 + // ty::Const + // + ty: i32 + // + val: Value(Scalar(0x00000063)) + // mir::Constant + // + span: $DIR/mutable_variable_aggregate_mut_ref.rs:7:11: 7:13 + // + literal: Const { ty: i32, val: Value(Scalar(0x00000063)) } + StorageLive(_3); // scope 2 at $DIR/mutable_variable_aggregate_mut_ref.rs:8:9: 8:10 + _3 = _1; // scope 2 at $DIR/mutable_variable_aggregate_mut_ref.rs:8:13: 8:14 + _0 = const (); // scope 0 at $DIR/mutable_variable_aggregate_mut_ref.rs:4:11: 9:2 + // ty::Const + // + ty: () + // + val: Value(Scalar()) + // mir::Constant + // + span: $DIR/mutable_variable_aggregate_mut_ref.rs:4:11: 9:2 + // + literal: Const { ty: (), val: Value(Scalar()) } + StorageDead(_3); // scope 2 at $DIR/mutable_variable_aggregate_mut_ref.rs:9:1: 9:2 + StorageDead(_2); // scope 1 at $DIR/mutable_variable_aggregate_mut_ref.rs:9:1: 9:2 + StorageDead(_1); // scope 0 at $DIR/mutable_variable_aggregate_mut_ref.rs:9:1: 9:2 + return; // scope 0 at $DIR/mutable_variable_aggregate_mut_ref.rs:9:2: 9:2 + } + } + diff --git a/src/test/mir-opt/const_prop/mutable_variable_no_prop.rs b/src/test/mir-opt/const_prop/mutable_variable_no_prop.rs new file mode 100644 index 000000000000..8c9cd0050962 --- /dev/null +++ b/src/test/mir-opt/const_prop/mutable_variable_no_prop.rs @@ -0,0 +1,12 @@ +// compile-flags: -O + +static mut STATIC: u32 = 42; + +// EMIT_MIR rustc.main.ConstProp.diff +fn main() { + let mut x = 42; + unsafe { + x = STATIC; + } + let y = x; +} diff --git a/src/test/mir-opt/const_prop/mutable_variable_no_prop/rustc.main.ConstProp.diff b/src/test/mir-opt/const_prop/mutable_variable_no_prop/rustc.main.ConstProp.diff new file mode 100644 index 000000000000..1e9cbe6024c9 --- /dev/null +++ b/src/test/mir-opt/const_prop/mutable_variable_no_prop/rustc.main.ConstProp.diff @@ -0,0 +1,69 @@ +- // MIR for `main` before ConstProp ++ // MIR for `main` after ConstProp + + fn main() -> () { + let mut _0: (); // return place in scope 0 at $DIR/mutable_variable_no_prop.rs:6:11: 6:11 + let mut _1: u32; // in scope 0 at $DIR/mutable_variable_no_prop.rs:7:9: 7:14 + let _2: (); // in scope 0 at $DIR/mutable_variable_no_prop.rs:8:5: 10:6 + let mut _3: u32; // in scope 0 at $DIR/mutable_variable_no_prop.rs:9:13: 9:19 + let mut _4: *mut u32; // in scope 0 at $DIR/mutable_variable_no_prop.rs:9:13: 9:19 + scope 1 { + debug x => _1; // in scope 1 at $DIR/mutable_variable_no_prop.rs:7:9: 7:14 + let _5: u32; // in scope 1 at $DIR/mutable_variable_no_prop.rs:11:9: 11:10 + scope 2 { + } + scope 3 { + debug y => _5; // in scope 3 at $DIR/mutable_variable_no_prop.rs:11:9: 11:10 + } + } + + bb0: { + StorageLive(_1); // scope 0 at $DIR/mutable_variable_no_prop.rs:7:9: 7:14 + _1 = const 42u32; // scope 0 at $DIR/mutable_variable_no_prop.rs:7:17: 7:19 + // ty::Const + // + ty: u32 + // + val: Value(Scalar(0x0000002a)) + // mir::Constant + // + span: $DIR/mutable_variable_no_prop.rs:7:17: 7:19 + // + literal: Const { ty: u32, val: Value(Scalar(0x0000002a)) } + StorageLive(_2); // scope 1 at $DIR/mutable_variable_no_prop.rs:8:5: 10:6 + StorageLive(_3); // scope 2 at $DIR/mutable_variable_no_prop.rs:9:13: 9:19 + StorageLive(_4); // scope 2 at $DIR/mutable_variable_no_prop.rs:9:13: 9:19 + _4 = const {alloc0+0x0: *mut u32}; // scope 2 at $DIR/mutable_variable_no_prop.rs:9:13: 9:19 + // ty::Const + // + ty: *mut u32 + // + val: Value(Scalar(alloc0+0x0)) + // mir::Constant + // + span: $DIR/mutable_variable_no_prop.rs:9:13: 9:19 + // + literal: Const { ty: *mut u32, val: Value(Scalar(alloc0+0x0)) } + _3 = (*_4); // scope 2 at $DIR/mutable_variable_no_prop.rs:9:13: 9:19 + _1 = move _3; // scope 2 at $DIR/mutable_variable_no_prop.rs:9:9: 9:19 + StorageDead(_3); // scope 2 at $DIR/mutable_variable_no_prop.rs:9:18: 9:19 + StorageDead(_4); // scope 2 at $DIR/mutable_variable_no_prop.rs:9:19: 9:20 + _2 = const (); // scope 2 at $DIR/mutable_variable_no_prop.rs:8:5: 10:6 + // ty::Const + // + ty: () + // + val: Value(Scalar()) + // mir::Constant + // + span: $DIR/mutable_variable_no_prop.rs:8:5: 10:6 + // + literal: Const { ty: (), val: Value(Scalar()) } + StorageDead(_2); // scope 1 at $DIR/mutable_variable_no_prop.rs:10:5: 10:6 + StorageLive(_5); // scope 1 at $DIR/mutable_variable_no_prop.rs:11:9: 11:10 + _5 = _1; // scope 1 at $DIR/mutable_variable_no_prop.rs:11:13: 11:14 + _0 = const (); // scope 0 at $DIR/mutable_variable_no_prop.rs:6:11: 12:2 + // ty::Const + // + ty: () + // + val: Value(Scalar()) + // mir::Constant + // + span: $DIR/mutable_variable_no_prop.rs:6:11: 12:2 + // + literal: Const { ty: (), val: Value(Scalar()) } + StorageDead(_5); // scope 1 at $DIR/mutable_variable_no_prop.rs:12:1: 12:2 + StorageDead(_1); // scope 0 at $DIR/mutable_variable_no_prop.rs:12:1: 12:2 + return; // scope 0 at $DIR/mutable_variable_no_prop.rs:12:2: 12:2 + } + } + + alloc0 (static: STATIC, size: 4, align: 4) { + 2a 00 00 00 │ *... + } + From 2b3adc9b9472e1d1e384422ceac783f9921f3b0b Mon Sep 17 00:00:00 2001 From: Mohsen Zohrevandi Date: Wed, 6 May 2020 23:41:38 -0700 Subject: [PATCH 049/203] Fix bind address in process-termination-blocking-io test --- .../ui/process-termination/process-termination-blocking-io.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/ui/process-termination/process-termination-blocking-io.rs b/src/test/ui/process-termination/process-termination-blocking-io.rs index df1a768ebbda..f306a61a5387 100644 --- a/src/test/ui/process-termination/process-termination-blocking-io.rs +++ b/src/test/ui/process-termination/process-termination-blocking-io.rs @@ -9,7 +9,7 @@ use std::{net::TcpListener, sync::mpsc, thread}; fn main() { let (tx, rx) = mpsc::channel(); thread::spawn(move || { - let listen = TcpListener::bind("0:0").unwrap(); + let listen = TcpListener::bind("0.0.0.0:0").unwrap(); tx.send(()).unwrap(); while let Ok(_) = listen.accept() {} }); From d80ac14fe69676c34efdec0c1cc589d28cd03ab1 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 30 Apr 2020 15:37:00 +0200 Subject: [PATCH 050/203] Extend rustdoc-js tester to allow to test multiple queries in one file --- src/tools/rustdoc-js/tester.js | 100 ++++++++++++++++++++++----------- 1 file changed, 66 insertions(+), 34 deletions(-) diff --git a/src/tools/rustdoc-js/tester.js b/src/tools/rustdoc-js/tester.js index 03f06fc1c6c7..72bc496c5b5d 100644 --- a/src/tools/rustdoc-js/tester.js +++ b/src/tools/rustdoc-js/tester.js @@ -181,7 +181,7 @@ function loadThings(thingsToLoad, kindOfLoad, funcToCall, fileContent) { for (var i = 0; i < thingsToLoad.length; ++i) { var tmp = funcToCall(fileContent, thingsToLoad[i]); if (tmp === null) { - console.error('unable to find ' + kindOfLoad + ' "' + thingsToLoad[i] + '"'); + console.log('unable to find ' + kindOfLoad + ' "' + thingsToLoad[i] + '"'); process.exit(1); } content += tmp; @@ -223,7 +223,8 @@ function loadMainJsAndIndex(mainJs, aliases, searchIndex, crate) { searchIndex.pop(); } searchIndex.pop(); - searchIndex = loadContent(searchIndex.join("\n") + '\nexports.searchIndex = searchIndex;'); + var fullSearchIndex = searchIndex.join("\n") + '\nexports.rawSearchIndex = searchIndex;'; + searchIndex = loadContent(fullSearchIndex); var finalJS = ""; var arraysToLoad = ["itemTypes"]; @@ -235,7 +236,7 @@ function loadMainJsAndIndex(mainJs, aliases, searchIndex, crate) { // execQuery last parameter is built in buildIndex. // buildIndex requires the hashmap from search-index. var functionsToLoad = ["buildHrefAndPath", "pathSplitter", "levenshtein", "validateResult", - "getQuery", "buildIndex", "execQuery", "execSearch"]; + "handleAliases", "getQuery", "buildIndex", "execQuery", "execSearch"]; finalJS += 'window = { "currentCrate": "' + crate + '" };\n'; finalJS += 'var rootPath = "../";\n'; @@ -245,24 +246,19 @@ function loadMainJsAndIndex(mainJs, aliases, searchIndex, crate) { finalJS += loadThings(functionsToLoad, 'function', extractFunction, mainJs); var loaded = loadContent(finalJS); - var index = loaded.buildIndex(searchIndex.searchIndex); + var index = loaded.buildIndex(searchIndex.rawSearchIndex); + // We make it "global" so that the "loaded.execSearch" function will find it. + rawSearchIndex = searchIndex.rawSearchIndex; return [loaded, index]; } -function runChecks(testFile, loaded, index) { - var errors = 0; - var loadedFile = loadContent( - readFile(testFile) + 'exports.QUERY = QUERY;exports.EXPECTED = EXPECTED;'); - - const expected = loadedFile.EXPECTED; - const query = loadedFile.QUERY; +function runSearch(query, expected, index, loaded, loadedFile, queryName) { const filter_crate = loadedFile.FILTER_CRATE; const ignore_order = loadedFile.ignore_order; const exact_check = loadedFile.exact_check; - const should_fail = loadedFile.should_fail; - var results = loaded.execSearch(loaded.getQuery(query), index); + var results = loaded.execSearch(loaded.getQuery(query), index, filter_crate); var error_text = []; for (var key in expected) { @@ -278,32 +274,68 @@ function runChecks(testFile, loaded, index) { for (var i = 0; i < entry.length; ++i) { var entry_pos = lookForEntry(entry[i], results[key]); if (entry_pos === null) { - error_text.push("==> Result not found in '" + key + "': '" + + error_text.push(queryName + "==> Result not found in '" + key + "': '" + JSON.stringify(entry[i]) + "'"); } else if (exact_check === true && prev_pos + 1 !== entry_pos) { - error_text.push("==> Exact check failed at position " + (prev_pos + 1) + ": " + - "expected '" + JSON.stringify(entry[i]) + "' but found '" + + error_text.push(queryName + "==> Exact check failed at position " + (prev_pos + 1) + + ": expected '" + JSON.stringify(entry[i]) + "' but found '" + JSON.stringify(results[key][i]) + "'"); } else if (ignore_order === false && entry_pos < prev_pos) { - error_text.push("==> '" + JSON.stringify(entry[i]) + "' was supposed to be " + - " before '" + JSON.stringify(results[key][entry_pos]) + "'"); + error_text.push(queryName + "==> '" + JSON.stringify(entry[i]) + "' was supposed " + + "to be before '" + JSON.stringify(results[key][entry_pos]) + "'"); } else { prev_pos = entry_pos; } } } - if (error_text.length === 0 && should_fail === true) { - errors += 1; - console.error("FAILED"); - console.error("==> Test was supposed to fail but all items were found..."); - } else if (error_text.length !== 0 && should_fail === false) { - errors += 1; - console.error("FAILED"); - console.error(error_text.join("\n")); + return error_text; +} + +function checkResult(error_text, loadedFile, displaySuccess) { + if (error_text.length === 0 && loadedFile.should_fail === true) { + console.log("FAILED"); + console.log("==> Test was supposed to fail but all items were found..."); + } else if (error_text.length !== 0 && loadedFile.should_fail === false) { + console.log("FAILED"); + console.log(error_text.join("\n")); } else { - console.log("OK"); + if (displaySuccess) { + console.log("OK"); + } + return 0; } - return errors; + return 1; +} + +function runChecks(testFile, loaded, index) { + var loadedFile = loadContent( + readFile(testFile) + 'exports.QUERY = QUERY;exports.EXPECTED = EXPECTED;'); + + const expected = loadedFile.EXPECTED; + const query = loadedFile.QUERY; + + if (Array.isArray(query)) { + if (!Array.isArray(expected)) { + console.log("FAILED"); + console.log("==> If QUERY variable is an array, EXPECTED should be an array too"); + return 1; + } else if (query.length !== expected.length) { + console.log("FAILED"); + console.log("==> QUERY variable should have the same length as EXPECTED"); + return 1; + } + for (var i = 0; i < query.length; ++i) { + var error_text = runSearch(query[i], expected[i], index, loaded, loadedFile, + "[ query `" + query[i] + "`]"); + if (checkResult(error_text, loadedFile, false) !== 0) { + return 1; + } + } + console.log("OK"); + return 0; + } + var error_text = runSearch(query, expected, index, loaded, loadedFile, ""); + return checkResult(error_text, loadedFile, true); } function load_files(doc_folder, resource_suffix, crate) { @@ -349,7 +381,7 @@ function parseOptions(args) { || args[i] === "--crate-name") { i += 1; if (i >= args.length) { - console.error("Missing argument after `" + args[i - 1] + "` option."); + console.log("Missing argument after `" + args[i - 1] + "` option."); return null; } opts[correspondances[args[i - 1]]] = args[i]; @@ -357,17 +389,17 @@ function parseOptions(args) { showHelp(); process.exit(0); } else { - console.error("Unknown option `" + args[i] + "`."); - console.error("Use `--help` to see the list of options"); + console.log("Unknown option `" + args[i] + "`."); + console.log("Use `--help` to see the list of options"); return null; } } if (opts["doc_folder"].length < 1) { - console.error("Missing `--doc-folder` option."); + console.log("Missing `--doc-folder` option."); } else if (opts["crate_name"].length < 1) { - console.error("Missing `--crate-name` option."); + console.log("Missing `--crate-name` option."); } else if (opts["test_folder"].length < 1 && opts["test_file"].length < 1) { - console.error("At least one of `--test-folder` or `--test-file` option is required."); + console.log("At least one of `--test-folder` or `--test-file` option is required."); } else { return opts; } From 7590c393dee055e9ce97f8a5f993fa0cc7e56217 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 30 Apr 2020 20:53:40 +0200 Subject: [PATCH 051/203] Improve doc alias JS code --- src/librustdoc/html/static/main.js | 73 ++++++++++++++++++++---------- 1 file changed, 50 insertions(+), 23 deletions(-) diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js index a023d5a2d95f..411d2d44059b 100644 --- a/src/librustdoc/html/static/main.js +++ b/src/librustdoc/html/static/main.js @@ -963,6 +963,50 @@ function getSearchElement() { return itemTypes[ty.ty] + ty.path + ty.name; } + function handleAliases(ret, query, filterCrates) { + if (ALIASES) { + var aliases = []; + if (filterCrates !== undefined && + ALIASES[filterCrates] && + ALIASES[filterCrates][query.search]) { + aliases = ALIASES[filterCrates][query.search]; + } else { + Object.keys(ALIASES).forEach(function(crate) { + if (ALIASES[crate][query.search]) { + for (var i = 0; i < ALIASES[crate][query.search].length; ++i) { + aliases.push(ALIASES[crate][query.search][i]); + } + } + }); + } + aliases.sort(function(aaa, bbb) { + if (aaa.path < bbb.path) { + return 1; + } else if (aaa.path === bbb.path) { + return 0; + } + return -1; + }); + for (var i = 0; i < aliases.length; ++i) { + var alias = aliases[i]; + alias.is_alias = true; + if (typeof alias.parent === "number") { + alias.parent = rawSearchIndex[alias.crate].p[alias.parent]; + } + alias.alias = query.raw; + alias.path = alias.p || alias.crate; + var res = buildHrefAndPath(aliases[i]); + alias.displayPath = pathSplitter(res[0]); + alias.fullPath = alias.displayPath + alias.name; + alias.href = res[1]; + ret.others.unshift(alias); + if (ret.others.length > MAX_RESULTS) { + ret.others.pop(); + } + } + } + } + // quoted values mean literal search var nSearchWords = searchWords.length; var i; @@ -1190,23 +1234,7 @@ function getSearchElement() { "returned": sortResults(results_returned, true), "others": sortResults(results), }; - if (ALIASES && ALIASES[window.currentCrate] && - ALIASES[window.currentCrate][query.raw]) { - var aliases = ALIASES[window.currentCrate][query.raw]; - for (i = 0; i < aliases.length; ++i) { - aliases[i].is_alias = true; - aliases[i].alias = query.raw; - aliases[i].path = aliases[i].p; - var res = buildHrefAndPath(aliases[i]); - aliases[i].displayPath = pathSplitter(res[0]); - aliases[i].fullPath = aliases[i].displayPath + aliases[i].name; - aliases[i].href = res[1]; - ret.others.unshift(aliases[i]); - if (ret.others.length > MAX_RESULTS) { - ret.others.pop(); - } - } - } + handleAliases(ret, query, filterCrates); return ret; } @@ -1599,13 +1627,12 @@ function getSearchElement() { "returned": mergeArrays(results.returned), "others": mergeArrays(results.others), }; - } else { - return { - "in_args": results.in_args[0], - "returned": results.returned[0], - "others": results.others[0], - }; } + return { + "in_args": results.in_args[0], + "returned": results.returned[0], + "others": results.others[0], + }; } function getFilterCrates() { From cf41b1d3a5fc5e4c209ab101b159095178dea916 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 30 Apr 2020 20:54:06 +0200 Subject: [PATCH 052/203] Improve doc alias discovery --- src/librustdoc/html/render.rs | 11 +++- src/librustdoc/html/render/cache.rs | 89 +++++++++++++++++------------ 2 files changed, 61 insertions(+), 39 deletions(-) diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 666e59b9a045..4ed367a5c80d 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -278,7 +278,7 @@ pub struct RenderInfo { /// Struct representing one entry in the JS search index. These are all emitted /// by hand to a large JS file at the end of cache-creation. #[derive(Debug)] -struct IndexItem { +pub struct IndexItem { ty: ItemType, name: String, path: String, @@ -293,7 +293,12 @@ impl Serialize for IndexItem { where S: Serializer, { - assert_eq!(self.parent.is_some(), self.parent_idx.is_some()); + assert_eq!( + self.parent.is_some(), + self.parent_idx.is_some(), + "`{}` is missing idx", + self.name + ); (self.ty, &self.name, &self.path, &self.desc, self.parent_idx, &self.search_type) .serialize(serializer) @@ -836,7 +841,7 @@ themePicker.onblur = handleThemeButtonsBlur; { let (mut all_aliases, _) = try_err!(collect(&dst, &krate.name, "ALIASES"), &dst); let mut output = String::with_capacity(100); - for (alias, items) in &cx.cache.aliases { + for (alias, items) in cx.cache.get_aliases() { if items.is_empty() { continue; } diff --git a/src/librustdoc/html/render/cache.rs b/src/librustdoc/html/render/cache.rs index 5b0902912271..17003334bc85 100644 --- a/src/librustdoc/html/render/cache.rs +++ b/src/librustdoc/html/render/cache.rs @@ -120,7 +120,7 @@ crate struct Cache { /// Aliases added through `#[doc(alias = "...")]`. Since a few items can have the same alias, /// we need the alias element to have an array of items. - pub(super) aliases: FxHashMap>, + pub(super) aliases: FxHashMap>, } impl Cache { @@ -311,7 +311,7 @@ impl DocFolder for Cache { }; match parent { - (parent, Some(path)) if is_inherent_impl_item || (!self.stripped_mod) => { + (parent, Some(path)) if is_inherent_impl_item || !self.stripped_mod => { debug_assert!(!item.is_stripped()); // A crate has a module at its root, containing all items, @@ -327,6 +327,21 @@ impl DocFolder for Cache { parent_idx: None, search_type: get_index_search_type(&item), }); + + for alias in item + .attrs + .lists(sym::doc) + .filter(|a| a.check_name(sym::alias)) + .filter_map(|a| a.value_str().map(|s| s.to_string().replace("\"", ""))) + .filter(|v| !v.is_empty()) + .collect::>() + .into_iter() + { + self.aliases + .entry(alias.to_lowercase()) + .or_insert(Vec::with_capacity(1)) + .push(self.search_index.len() - 1); + } } } (Some(parent), None) if is_inherent_impl_item => { @@ -363,6 +378,9 @@ impl DocFolder for Cache { | clean::MacroItem(..) | clean::ProcMacroItem(..) | clean::VariantItem(..) + | clean::StructFieldItem(..) + | clean::TyMethodItem(..) + | clean::MethodItem(..) if !self.stripped_mod => { // Re-exported items mean that the same id can show up twice @@ -376,11 +394,8 @@ impl DocFolder for Cache { { self.paths.insert(item.def_id, (self.stack.clone(), item.type_())); } - self.add_aliases(&item); } - clean::PrimitiveItem(..) => { - self.add_aliases(&item); self.paths.insert(item.def_id, (self.stack.clone(), item.type_())); } @@ -489,36 +504,23 @@ impl DocFolder for Cache { } impl Cache { - fn add_aliases(&mut self, item: &clean::Item) { - if item.def_id.index == CRATE_DEF_INDEX { - return; - } - if let Some(ref item_name) = item.name { - let path = self - .paths - .get(&item.def_id) - .map(|p| p.0[..p.0.len() - 1].join("::")) - .unwrap_or("std".to_owned()); - for alias in item - .attrs - .lists(sym::doc) - .filter(|a| a.check_name(sym::alias)) - .filter_map(|a| a.value_str().map(|s| s.to_string().replace("\"", ""))) - .filter(|v| !v.is_empty()) - .collect::>() - .into_iter() - { - self.aliases.entry(alias).or_insert(Vec::with_capacity(1)).push(IndexItem { - ty: item.type_(), - name: item_name.to_string(), - path: path.clone(), - desc: shorten(plain_summary_line(item.doc_value())), - parent: None, - parent_idx: None, - search_type: get_index_search_type(&item), - }); - } - } + pub fn get_aliases<'a>(&'a self) -> FxHashMap> { + self.aliases + .iter() + .map(|(k, values)| { + ( + k.clone(), + values + .iter() + .filter(|v| { + let x = &self.search_index[**v]; + x.parent_idx.is_some() == x.parent.is_some() + }) + .map(|v| &self.search_index[*v]) + .collect::>(), + ) + }) + .collect() } } @@ -567,7 +569,8 @@ fn build_index(krate: &clean::Crate, cache: &mut Cache) -> String { let mut crate_items = Vec::with_capacity(cache.search_index.len()); let mut crate_paths = vec![]; - let Cache { ref mut search_index, ref orphan_impl_items, ref paths, .. } = *cache; + let Cache { ref mut search_index, ref orphan_impl_items, ref paths, ref mut aliases, .. } = + *cache; // Attach all orphan items to the type's definition if the type // has since been learned. @@ -582,6 +585,20 @@ fn build_index(krate: &clean::Crate, cache: &mut Cache) -> String { parent_idx: None, search_type: get_index_search_type(&item), }); + for alias in item + .attrs + .lists(sym::doc) + .filter(|a| a.check_name(sym::alias)) + .filter_map(|a| a.value_str().map(|s| s.to_string().replace("\"", ""))) + .filter(|v| !v.is_empty()) + .collect::>() + .into_iter() + { + aliases + .entry(alias.to_lowercase()) + .or_insert(Vec::with_capacity(1)) + .push(search_index.len() - 1); + } } } From 3a0727e84e29318ee41eb63bac27bfc1a379bfc5 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 1 May 2020 00:27:24 +0200 Subject: [PATCH 053/203] Add more tests for doc aliases --- src/test/rustdoc-js/doc-alias.js | 237 +++++++++++++++++++++++++++++++ src/test/rustdoc-js/doc-alias.rs | 80 +++++++++++ 2 files changed, 317 insertions(+) create mode 100644 src/test/rustdoc-js/doc-alias.js create mode 100644 src/test/rustdoc-js/doc-alias.rs diff --git a/src/test/rustdoc-js/doc-alias.js b/src/test/rustdoc-js/doc-alias.js new file mode 100644 index 000000000000..e6310b625e53 --- /dev/null +++ b/src/test/rustdoc-js/doc-alias.js @@ -0,0 +1,237 @@ +// exact-check + +const QUERY = [ + 'StructItem', + 'StructFieldItem', + 'StructMethodItem', + 'ImplTraitItem', + 'ImplAssociatedConstItem', + 'ImplTraitFunction', + 'EnumItem', + 'VariantItem', + 'EnumMethodItem', + 'TypedefItem', + 'TraitItem', + 'TraitTypeItem', + 'AssociatedConstItem', + 'TraitFunctionItem', + 'FunctionItem', + 'ModuleItem', + 'ConstItem', + 'StaticItem', + 'UnionItem', + 'UnionFieldItem', + 'UnionMethodItem', + 'MacroItem', +]; + +const EXPECTED = [ + { + 'others': [ + { + 'path': 'doc_alias', + 'name': 'Struct', + 'alias': 'StructItem', + 'href': '../doc_alias/struct.Struct.html' + }, + ], + }, + { + 'others': [ + { + 'path': 'doc_alias::Struct', + 'name': 'field', + 'alias': 'StructFieldItem', + 'href': '../doc_alias/struct.Struct.html#structfield.field' + }, + ], + }, + { + 'others': [ + { + 'path': 'doc_alias::Struct', + 'name': 'method', + 'alias': 'StructMethodItem', + 'href': '../doc_alias/struct.Struct.html#method.method' + }, + ], + }, + { + // ImplTraitItem + 'others': [], + }, + { + // ImplAssociatedConstItem + 'others': [], + }, + { + // ImplTraitFunction + 'others': [], + }, + { + 'others': [ + { + 'path': 'doc_alias', + 'name': 'Enum', + 'alias': 'EnumItem', + 'href': '../doc_alias/enum.Enum.html' + }, + ], + }, + { + 'others': [ + { + 'path': 'doc_alias::Enum', + 'name': 'Variant', + 'alias': 'VariantItem', + 'href': '../doc_alias/enum.Enum.html#variant.Variant' + }, + ], + }, + { + 'others': [ + { + 'path': 'doc_alias::Enum', + 'name': 'method', + 'alias': 'EnumMethodItem', + 'href': '../doc_alias/enum.Enum.html#method.method' + }, + ], + }, + { + 'others': [ + { + 'path': 'doc_alias', + 'name': 'Typedef', + 'alias': 'TypedefItem', + 'href': '../doc_alias/type.Typedef.html' + }, + ], + }, + { + 'others': [ + { + 'path': 'doc_alias', + 'name': 'Trait', + 'alias': 'TraitItem', + 'href': '../doc_alias/trait.Trait.html' + }, + ], + }, + { + 'others': [ + { + 'path': 'doc_alias::Trait', + 'name': 'Target', + 'alias': 'TraitTypeItem', + 'href': '../doc_alias/trait.Trait.html#associatedtype.Target' + }, + ], + }, + { + 'others': [ + { + 'path': 'doc_alias::Trait', + 'name': 'AssociatedConst', + 'alias': 'AssociatedConstItem', + 'href': '../doc_alias/trait.Trait.html#associatedconstant.AssociatedConst' + }, + ], + }, + { + 'others': [ + { + 'path': 'doc_alias::Trait', + 'name': 'function', + 'alias': 'TraitFunctionItem', + 'href': '../doc_alias/trait.Trait.html#tymethod.function' + }, + ], + }, + { + 'others': [ + { + 'path': 'doc_alias', + 'name': 'function', + 'alias': 'FunctionItem', + 'href': '../doc_alias/fn.function.html' + }, + ], + }, + { + 'others': [ + { + 'path': 'doc_alias', + 'name': 'Module', + 'alias': 'ModuleItem', + 'href': '../doc_alias/Module/index.html' + }, + ], + }, + { + 'others': [ + { + 'path': 'doc_alias', + 'name': 'Const', + 'alias': 'ConstItem', + 'href': '../doc_alias/constant.Const.html' + }, + ], + }, + { + 'others': [ + { + 'path': 'doc_alias', + 'name': 'Static', + 'alias': 'StaticItem', + 'href': '../doc_alias/static.Static.html' + }, + ], + }, + { + 'others': [ + { + 'path': 'doc_alias', + 'name': 'Union', + 'alias': 'UnionItem', + 'href': '../doc_alias/union.Union.html' + }, + // Not an alias! + { + 'path': 'doc_alias::Union', + 'name': 'union_item', + 'href': '../doc_alias/union.Union.html#structfield.union_item' + }, + ], + }, + { + 'others': [ + { + 'path': 'doc_alias::Union', + 'name': 'union_item', + 'alias': 'UnionFieldItem', + 'href': '../doc_alias/union.Union.html#structfield.union_item' + }, + ], + }, + { + 'others': [ + { + 'path': 'doc_alias::Union', + 'name': 'method', + 'alias': 'UnionMethodItem', + 'href': '../doc_alias/union.Union.html#method.method' + }, + ], + }, + { + 'others': [ + { + 'path': 'doc_alias', + 'name': 'Macro', + 'alias': 'MacroItem', + 'href': '../doc_alias/macro.Macro.html' + }, + ], + }, +]; diff --git a/src/test/rustdoc-js/doc-alias.rs b/src/test/rustdoc-js/doc-alias.rs new file mode 100644 index 000000000000..8cd0a8299741 --- /dev/null +++ b/src/test/rustdoc-js/doc-alias.rs @@ -0,0 +1,80 @@ +#![feature(doc_alias)] + +#[doc(alias = "StructItem")] +pub struct Struct { + #[doc(alias = "StructFieldItem")] + pub field: u32, +} + +impl Struct { + #[doc(alias = "StructMethodItem")] + pub fn method(&self) {} +} + +impl Trait for Struct { + // Shouldn't be listed in aliases! + #[doc(alias = "ImplTraitItem")] + type Target = u32; + // Shouldn't be listed in aliases! + #[doc(alias = "ImplAssociatedConstItem")] + const AssociatedConst: i32 = 12; + + // Shouldn't be listed in aliases! + #[doc(alias = "ImplTraitFunction")] + fn function() -> Self::Target { 0 } +} + +#[doc(alias = "EnumItem")] +pub enum Enum { + #[doc(alias = "VariantItem")] + Variant, +} + +impl Enum { + #[doc(alias = "EnumMethodItem")] + pub fn method(&self) {} +} + +#[doc(alias = "TypedefItem")] +pub type Typedef = i32; + +#[doc(alias = "TraitItem")] +pub trait Trait { + #[doc(alias = "TraitTypeItem")] + type Target; + #[doc(alias = "AssociatedConstItem")] + const AssociatedConst: i32; + + #[doc(alias = "TraitFunctionItem")] + fn function() -> Self::Target; +} + +#[doc(alias = "FunctionItem")] +pub fn function() {} + +#[doc(alias = "ModuleItem")] +pub mod Module {} + +#[doc(alias = "ConstItem")] +pub const Const: u32 = 0; + +#[doc(alias = "StaticItem")] +pub static Static: u32 = 0; + +#[doc(alias = "UnionItem")] +pub union Union { + #[doc(alias = "UnionFieldItem")] + pub union_item: u32, + pub y: f32, +} + +impl Union { + #[doc(alias = "UnionMethodItem")] + pub fn method(&self) {} +} + +#[doc(alias = "MacroItem")] +#[macro_export] +macro_rules! Macro { + () => {} +} From 9697c467aca28f40d8ef7c59b9f5bc670c1b85f8 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 1 May 2020 00:43:55 +0200 Subject: [PATCH 054/203] Update std tests --- src/test/rustdoc-js-std/alias-2.js | 4 +++- src/test/rustdoc-js-std/alias.js | 4 ++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/test/rustdoc-js-std/alias-2.js b/src/test/rustdoc-js-std/alias-2.js index f3c6713692b5..0ce1b87b7615 100644 --- a/src/test/rustdoc-js-std/alias-2.js +++ b/src/test/rustdoc-js-std/alias-2.js @@ -4,7 +4,9 @@ const QUERY = '+'; const EXPECTED = { 'others': [ - { 'path': 'std::ops', 'name': 'AddAssign' }, + { 'path': 'core', 'name': 'AddAssign' }, + { 'path': 'core', 'name': 'Add' }, + { 'path': 'std', 'name': 'AddAssign' }, { 'path': 'std::ops', 'name': 'Add' }, ], }; diff --git a/src/test/rustdoc-js-std/alias.js b/src/test/rustdoc-js-std/alias.js index 2b709c99119a..0b1e983117f2 100644 --- a/src/test/rustdoc-js-std/alias.js +++ b/src/test/rustdoc-js-std/alias.js @@ -5,7 +5,7 @@ const QUERY = '['; const EXPECTED = { 'others': [ { 'path': 'std', 'name': 'slice' }, - { 'path': 'std::ops', 'name': 'IndexMut' }, - { 'path': 'std::ops', 'name': 'Index' }, + { 'path': 'std', 'name': 'IndexMut' }, + { 'path': 'std', 'name': 'Index' }, ], }; From f581cf754492f9f122193b8d8a7750ab38a87485 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 4 May 2020 14:51:06 +0200 Subject: [PATCH 055/203] Merge aliases and search-index --- src/librustdoc/html/layout.rs | 1 - src/librustdoc/html/render.rs | 36 -------- src/librustdoc/html/render/cache.rs | 44 +++++----- src/librustdoc/html/static/main.js | 126 +++++++++++++++++++--------- src/test/rustdoc-js-std/alias-2.js | 6 +- src/test/rustdoc-js-std/alias.js | 4 +- src/tools/rustdoc-js/tester.js | 9 +- 7 files changed, 118 insertions(+), 108 deletions(-) diff --git a/src/librustdoc/html/layout.rs b/src/librustdoc/html/layout.rs index 0922c8cdd120..ea65b3905272 100644 --- a/src/librustdoc/html/layout.rs +++ b/src/librustdoc/html/layout.rs @@ -114,7 +114,6 @@ pub fn render( window.rootPath = \"{root_path}\";\ window.currentCrate = \"{krate}\";\ \ - \ \ {static_extra_scripts}\ {extra_scripts}\ diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 4ed367a5c80d..9454baf76409 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -825,42 +825,6 @@ themePicker.onblur = handleThemeButtonsBlur; Ok((ret, krates)) } - fn show_item(item: &IndexItem, krate: &str) -> String { - format!( - "{{'crate':'{}','ty':{},'name':'{}','desc':'{}','p':'{}'{}}}", - krate, - item.ty as usize, - item.name, - item.desc.replace("'", "\\'"), - item.path, - if let Some(p) = item.parent_idx { format!(",'parent':{}", p) } else { String::new() } - ) - } - - let dst = cx.dst.join(&format!("aliases{}.js", cx.shared.resource_suffix)); - { - let (mut all_aliases, _) = try_err!(collect(&dst, &krate.name, "ALIASES"), &dst); - let mut output = String::with_capacity(100); - for (alias, items) in cx.cache.get_aliases() { - if items.is_empty() { - continue; - } - output.push_str(&format!( - "\"{}\":[{}],", - alias, - items.iter().map(|v| show_item(v, &krate.name)).collect::>().join(",") - )); - } - all_aliases.push(format!("ALIASES[\"{}\"] = {{{}}};", krate.name, output)); - all_aliases.sort(); - let mut v = Buffer::html(); - writeln!(&mut v, "var ALIASES = {{}};"); - for aliases in &all_aliases { - writeln!(&mut v, "{}", aliases); - } - cx.shared.fs.write(&dst, v.into_inner().into_bytes())?; - } - use std::ffi::OsString; #[derive(Debug)] diff --git a/src/librustdoc/html/render/cache.rs b/src/librustdoc/html/render/cache.rs index 17003334bc85..53cf1abb16d5 100644 --- a/src/librustdoc/html/render/cache.rs +++ b/src/librustdoc/html/render/cache.rs @@ -503,27 +503,6 @@ impl DocFolder for Cache { } } -impl Cache { - pub fn get_aliases<'a>(&'a self) -> FxHashMap> { - self.aliases - .iter() - .map(|(k, values)| { - ( - k.clone(), - values - .iter() - .filter(|v| { - let x = &self.search_index[**v]; - x.parent_idx.is_some() == x.parent.is_some() - }) - .map(|v| &self.search_index[*v]) - .collect::>(), - ) - }) - .collect() - } -} - /// Attempts to find where an external crate is located, given that we're /// rendering in to the specified source destination. fn extern_location( @@ -640,6 +619,23 @@ fn build_index(krate: &clean::Crate, cache: &mut Cache) -> String { .map(|module| shorten(plain_summary_line(module.doc_value()))) .unwrap_or(String::new()); + let crate_aliases = aliases + .iter() + .map(|(k, values)| { + ( + k.clone(), + values + .iter() + .filter_map(|v| { + let x = &crate_items[*v]; + if x.parent_idx.is_some() == x.parent.is_some() { Some(*v) } else { None } + }) + .collect::>(), + ) + }) + .filter(|(_, values)| !values.is_empty()) + .collect::>(); + #[derive(Serialize)] struct CrateData<'a> { doc: String, @@ -647,6 +643,11 @@ fn build_index(krate: &clean::Crate, cache: &mut Cache) -> String { items: Vec<&'a IndexItem>, #[serde(rename = "p")] paths: Vec<(ItemType, String)>, + // The String is alias name and the vec is the list of the elements with this alias. + // + // To be noted: the `usize` elements are indexes to `items`. + #[serde(rename = "a")] + aliases: Option)>>, } // Collect the index into a string @@ -657,6 +658,7 @@ fn build_index(krate: &clean::Crate, cache: &mut Cache) -> String { doc: crate_doc, items: crate_items, paths: crate_paths, + aliases: if crate_aliases.is_empty() { None } else { Some(crate_aliases) }, }) .expect("failed serde conversion") // All these `replace` calls are because we have to go through JS string for JSON content. diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js index 411d2d44059b..94ae69fde57f 100644 --- a/src/librustdoc/html/static/main.js +++ b/src/librustdoc/html/static/main.js @@ -531,6 +531,7 @@ function getSearchElement() { var OUTPUT_DATA = 1; var NO_TYPE_FILTER = -1; var currentResults, index, searchIndex; + var ALIASES = {}; var params = getQueryStringParams(); // Populate search bar with query string search term when provided, @@ -963,46 +964,60 @@ function getSearchElement() { return itemTypes[ty.ty] + ty.path + ty.name; } + function createAliasFromItem(item) { + return { + crate: item.crate, + name: item.name, + path: item.path, + desc: item.desc, + ty: item.ty, + parent: item.parent, + type: item.parent, + is_alias: true, + }; + } + function handleAliases(ret, query, filterCrates) { - if (ALIASES) { - var aliases = []; - if (filterCrates !== undefined && - ALIASES[filterCrates] && - ALIASES[filterCrates][query.search]) { - aliases = ALIASES[filterCrates][query.search]; - } else { - Object.keys(ALIASES).forEach(function(crate) { - if (ALIASES[crate][query.search]) { - for (var i = 0; i < ALIASES[crate][query.search].length; ++i) { - aliases.push(ALIASES[crate][query.search][i]); - } - } - }); + var aliases = []; + var i; + if (filterCrates !== undefined && + ALIASES[filterCrates] && + ALIASES[filterCrates][query.search]) { + for (i = 0; i < ALIASES[crate][query.search].length; ++i) { + aliases.push( + createAliasFromItem(searchIndex[ALIASES[filterCrates][query.search]])); } - aliases.sort(function(aaa, bbb) { - if (aaa.path < bbb.path) { - return 1; - } else if (aaa.path === bbb.path) { - return 0; + } else { + Object.keys(ALIASES).forEach(function(crate) { + if (ALIASES[crate][query.search]) { + for (i = 0; i < ALIASES[crate][query.search].length; ++i) { + aliases.push( + createAliasFromItem( + searchIndex[ALIASES[crate][query.search][i]])); + } } - return -1; }); - for (var i = 0; i < aliases.length; ++i) { - var alias = aliases[i]; - alias.is_alias = true; - if (typeof alias.parent === "number") { - alias.parent = rawSearchIndex[alias.crate].p[alias.parent]; - } - alias.alias = query.raw; - alias.path = alias.p || alias.crate; - var res = buildHrefAndPath(aliases[i]); - alias.displayPath = pathSplitter(res[0]); - alias.fullPath = alias.displayPath + alias.name; - alias.href = res[1]; - ret.others.unshift(alias); - if (ret.others.length > MAX_RESULTS) { - ret.others.pop(); - } + } + aliases.sort(function(aaa, bbb) { + if (aaa.path < bbb.path) { + return 1; + } else if (aaa.path === bbb.path) { + return 0; + } + return -1; + }); + for (i = 0; i < aliases.length; ++i) { + var alias = aliases[i]; + + alias.alias = query.raw; + var res = buildHrefAndPath(alias); + alias.displayPath = pathSplitter(res[0]); + alias.fullPath = alias.displayPath + alias.name; + alias.href = res[1]; + + ret.others.unshift(alias); + if (ret.others.length > MAX_RESULTS) { + ret.others.pop(); } } } @@ -1683,10 +1698,13 @@ function getSearchElement() { searchIndex = []; var searchWords = []; var i; + var currentIndex = 0; for (var crate in rawSearchIndex) { if (!rawSearchIndex.hasOwnProperty(crate)) { continue; } + var crateSize = 0; + searchWords.push(crate); searchIndex.push({ crate: crate, @@ -1696,6 +1714,7 @@ function getSearchElement() { desc: rawSearchIndex[crate].doc, type: null, }); + currentIndex += 1; // an array of [(Number) item type, // (String) name, @@ -1707,6 +1726,9 @@ function getSearchElement() { // an array of [(Number) item type, // (String) name] var paths = rawSearchIndex[crate].p; + // a array of [(String) alias name + // [Number] index to items] + var aliases = rawSearchIndex[crate].a; // convert `rawPaths` entries into object form var len = paths.length; @@ -1725,9 +1747,18 @@ function getSearchElement() { var lastPath = ""; for (i = 0; i < len; ++i) { var rawRow = items[i]; - var row = {crate: crate, ty: rawRow[0], name: rawRow[1], - path: rawRow[2] || lastPath, desc: rawRow[3], - parent: paths[rawRow[4]], type: rawRow[5]}; + if (!rawRow[2]) { + rawRow[2] = lastPath; + } + var row = { + crate: crate, + ty: rawRow[0], + name: rawRow[1], + path: rawRow[2], + desc: rawRow[3], + parent: paths[rawRow[4]], + type: rawRow[5], + }; searchIndex.push(row); if (typeof row.name === "string") { var word = row.name.toLowerCase(); @@ -1736,7 +1767,24 @@ function getSearchElement() { searchWords.push(""); } lastPath = row.path; + crateSize += 1; } + + if (aliases) { + ALIASES[crate] = {}; + var j, local_aliases; + for (i = 0; i < aliases.length; ++i) { + var alias_name = aliases[i][0]; + if (!ALIASES[crate].hasOwnProperty(alias_name)) { + ALIASES[crate][alias_name] = []; + } + local_aliases = aliases[i][1]; + for (j = 0; j < local_aliases.length; ++j) { + ALIASES[crate][alias_name].push(local_aliases[j] + currentIndex); + } + } + } + currentIndex += crateSize; } return searchWords; } diff --git a/src/test/rustdoc-js-std/alias-2.js b/src/test/rustdoc-js-std/alias-2.js index 0ce1b87b7615..cb6ec4f8fed4 100644 --- a/src/test/rustdoc-js-std/alias-2.js +++ b/src/test/rustdoc-js-std/alias-2.js @@ -4,9 +4,9 @@ const QUERY = '+'; const EXPECTED = { 'others': [ - { 'path': 'core', 'name': 'AddAssign' }, - { 'path': 'core', 'name': 'Add' }, - { 'path': 'std', 'name': 'AddAssign' }, + { 'path': 'core::ops', 'name': 'AddAssign' }, + { 'path': 'core::ops', 'name': 'Add' }, + { 'path': 'std::ops', 'name': 'AddAssign' }, { 'path': 'std::ops', 'name': 'Add' }, ], }; diff --git a/src/test/rustdoc-js-std/alias.js b/src/test/rustdoc-js-std/alias.js index 0b1e983117f2..2b709c99119a 100644 --- a/src/test/rustdoc-js-std/alias.js +++ b/src/test/rustdoc-js-std/alias.js @@ -5,7 +5,7 @@ const QUERY = '['; const EXPECTED = { 'others': [ { 'path': 'std', 'name': 'slice' }, - { 'path': 'std', 'name': 'IndexMut' }, - { 'path': 'std', 'name': 'Index' }, + { 'path': 'std::ops', 'name': 'IndexMut' }, + { 'path': 'std::ops', 'name': 'Index' }, ], }; diff --git a/src/tools/rustdoc-js/tester.js b/src/tools/rustdoc-js/tester.js index 72bc496c5b5d..90315d6f6443 100644 --- a/src/tools/rustdoc-js/tester.js +++ b/src/tools/rustdoc-js/tester.js @@ -218,7 +218,7 @@ function lookForEntry(entry, data) { return null; } -function loadMainJsAndIndex(mainJs, aliases, searchIndex, crate) { +function loadMainJsAndIndex(mainJs, searchIndex, crate) { if (searchIndex[searchIndex.length - 1].length === 0) { searchIndex.pop(); } @@ -238,17 +238,15 @@ function loadMainJsAndIndex(mainJs, aliases, searchIndex, crate) { var functionsToLoad = ["buildHrefAndPath", "pathSplitter", "levenshtein", "validateResult", "handleAliases", "getQuery", "buildIndex", "execQuery", "execSearch"]; + ALIASES = {}; finalJS += 'window = { "currentCrate": "' + crate + '" };\n'; finalJS += 'var rootPath = "../";\n'; - finalJS += aliases; finalJS += loadThings(arraysToLoad, 'array', extractArrayVariable, mainJs); finalJS += loadThings(variablesToLoad, 'variable', extractVariable, mainJs); finalJS += loadThings(functionsToLoad, 'function', extractFunction, mainJs); var loaded = loadContent(finalJS); var index = loaded.buildIndex(searchIndex.rawSearchIndex); - // We make it "global" so that the "loaded.execSearch" function will find it. - rawSearchIndex = searchIndex.rawSearchIndex; return [loaded, index]; } @@ -340,11 +338,10 @@ function runChecks(testFile, loaded, index) { function load_files(doc_folder, resource_suffix, crate) { var mainJs = readFile(path.join(doc_folder, "main" + resource_suffix + ".js")); - var aliases = readFile(path.join(doc_folder, "aliases" + resource_suffix + ".js")); var searchIndex = readFile( path.join(doc_folder, "search-index" + resource_suffix + ".js")).split("\n"); - return loadMainJsAndIndex(mainJs, aliases, searchIndex, crate); + return loadMainJsAndIndex(mainJs, searchIndex, crate); } function showHelp() { From 3b58d66b22fe9107a78b99c267c71322276aa15a Mon Sep 17 00:00:00 2001 From: Eduardo Broto Date: Thu, 7 May 2020 21:41:23 +0200 Subject: [PATCH 056/203] Add the manual_async_fn lint --- CHANGELOG.md | 1 + clippy_lints/src/lib.rs | 5 + clippy_lints/src/manual_async_fn.rs | 160 ++++++++++++++++++++++++++++ clippy_lints/src/utils/paths.rs | 3 + src/lintlist/mod.rs | 7 ++ tests/ui/future_not_send.rs | 1 + tests/ui/future_not_send.stderr | 6 +- tests/ui/manual_async_fn.fixed | 55 ++++++++++ tests/ui/manual_async_fn.rs | 67 ++++++++++++ tests/ui/manual_async_fn.stderr | 93 ++++++++++++++++ 10 files changed, 395 insertions(+), 3 deletions(-) create mode 100644 clippy_lints/src/manual_async_fn.rs create mode 100644 tests/ui/manual_async_fn.fixed create mode 100644 tests/ui/manual_async_fn.rs create mode 100644 tests/ui/manual_async_fn.stderr diff --git a/CHANGELOG.md b/CHANGELOG.md index facf363e371e..8457d6ad05cf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1422,6 +1422,7 @@ Released 2018-09-13 [`lossy_float_literal`]: https://rust-lang.github.io/rust-clippy/master/index.html#lossy_float_literal [`macro_use_imports`]: https://rust-lang.github.io/rust-clippy/master/index.html#macro_use_imports [`main_recursion`]: https://rust-lang.github.io/rust-clippy/master/index.html#main_recursion +[`manual_async_fn`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_async_fn [`manual_memcpy`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_memcpy [`manual_non_exhaustive`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_non_exhaustive [`manual_saturating_arithmetic`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_saturating_arithmetic diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 97785cba8835..fb2e9932b8e4 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -247,6 +247,7 @@ mod literal_representation; mod loops; mod macro_use; mod main_recursion; +mod manual_async_fn; mod manual_non_exhaustive; mod map_clone; mod map_unit_fn; @@ -629,6 +630,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: &loops::WHILE_LET_ON_ITERATOR, ¯o_use::MACRO_USE_IMPORTS, &main_recursion::MAIN_RECURSION, + &manual_async_fn::MANUAL_ASYNC_FN, &manual_non_exhaustive::MANUAL_NON_EXHAUSTIVE, &map_clone::MAP_CLONE, &map_unit_fn::OPTION_MAP_UNIT_FN, @@ -1067,6 +1069,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(|| box if_let_mutex::IfLetMutex); store.register_late_pass(|| box match_on_vec_items::MatchOnVecItems); store.register_early_pass(|| box manual_non_exhaustive::ManualNonExhaustive); + store.register_late_pass(|| box manual_async_fn::ManualAsyncFn); store.register_group(true, "clippy::restriction", Some("clippy_restriction"), vec![ LintId::of(&arithmetic::FLOAT_ARITHMETIC), @@ -1284,6 +1287,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&loops::WHILE_LET_LOOP), LintId::of(&loops::WHILE_LET_ON_ITERATOR), LintId::of(&main_recursion::MAIN_RECURSION), + LintId::of(&manual_async_fn::MANUAL_ASYNC_FN), LintId::of(&manual_non_exhaustive::MANUAL_NON_EXHAUSTIVE), LintId::of(&map_clone::MAP_CLONE), LintId::of(&map_unit_fn::OPTION_MAP_UNIT_FN), @@ -1478,6 +1482,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&loops::NEEDLESS_RANGE_LOOP), LintId::of(&loops::WHILE_LET_ON_ITERATOR), LintId::of(&main_recursion::MAIN_RECURSION), + LintId::of(&manual_async_fn::MANUAL_ASYNC_FN), LintId::of(&manual_non_exhaustive::MANUAL_NON_EXHAUSTIVE), LintId::of(&map_clone::MAP_CLONE), LintId::of(&matches::INFALLIBLE_DESTRUCTURING_MATCH), diff --git a/clippy_lints/src/manual_async_fn.rs b/clippy_lints/src/manual_async_fn.rs new file mode 100644 index 000000000000..ab8829abbf2e --- /dev/null +++ b/clippy_lints/src/manual_async_fn.rs @@ -0,0 +1,160 @@ +use crate::utils::paths::{FUTURE_CORE, FUTURE_FROM_GENERATOR, FUTURE_STD}; +use crate::utils::{match_function_call, match_path, snippet_block, snippet_opt, span_lint_and_then}; +use if_chain::if_chain; +use rustc_errors::Applicability; +use rustc_hir::intravisit::FnKind; +use rustc_hir::{ + AsyncGeneratorKind, Block, Body, Expr, ExprKind, FnDecl, FnRetTy, GeneratorKind, GenericBound, HirId, IsAsync, + ItemKind, TraitRef, Ty, TyKind, TypeBindingKind, +}; +use rustc_lint::{LateContext, LateLintPass}; +use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_span::Span; + +declare_clippy_lint! { + /// **What it does:** It checks for manual implementations of `async` functions. + /// + /// **Why is this bad?** It's more idiomatic to use the dedicated syntax. + /// + /// **Known problems:** None. + /// + /// **Example:** + /// + /// ```rust + /// use std::future::Future; + /// + /// fn foo() -> Future { async { 42 } } + /// ``` + /// Use instead: + /// ```rust + /// use std::future::Future; + /// + /// async fn foo() -> i32 { 42 } + /// ``` + pub MANUAL_ASYNC_FN, + style, + "manual implementations of `async` functions can be simplified using the dedicated syntax" +} + +declare_lint_pass!(ManualAsyncFn => [MANUAL_ASYNC_FN]); + +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ManualAsyncFn { + fn check_fn( + &mut self, + cx: &LateContext<'a, 'tcx>, + kind: FnKind<'tcx>, + decl: &'tcx FnDecl<'_>, + body: &'tcx Body<'_>, + span: Span, + _: HirId, + ) { + if_chain! { + if let Some(header) = kind.header(); + if let IsAsync::NotAsync = header.asyncness; + // Check that this function returns `impl Future` + if let FnRetTy::Return(ret_ty) = decl.output; + if let Some(trait_ref) = future_trait_ref(cx, ret_ty); + if let Some(output) = future_output_ty(trait_ref); + // Check that the body of the function consists of one async block + if let ExprKind::Block(block, _) = body.value.kind; + if block.stmts.is_empty(); + if let Some(closure_body) = desugared_async_block(cx, block); + then { + let header_span = span.with_hi(ret_ty.span.hi()); + + span_lint_and_then( + cx, + MANUAL_ASYNC_FN, + header_span, + "this function can be simplified using async syntax", + |diag| { + if_chain! { + if let Some(header_snip) = snippet_opt(cx, header_span); + if let Some(ret_pos) = header_snip.rfind("->"); + if let Some((ret_sugg, ret_snip)) = suggested_ret(cx, output); + then { + let help = format!("make the function `async` and {}", ret_sugg); + diag.span_suggestion( + header_span, + &help, + format!("async {}{}", &header_snip[..ret_pos], ret_snip), + Applicability::MachineApplicable + ); + + let body_snip = snippet_block(cx, closure_body.value.span, "..", Some(block.span)); + diag.span_suggestion( + block.span, + "move the body of the async block to the enclosing function", + body_snip.to_string(), + Applicability::MachineApplicable + ); + } + } + }, + ); + } + } + } +} + +fn future_trait_ref<'tcx>(cx: &LateContext<'_, 'tcx>, ty: &'tcx Ty<'tcx>) -> Option<&'tcx TraitRef<'tcx>> { + if_chain! { + if let TyKind::Def(item_id, _) = ty.kind; + let item = cx.tcx.hir().item(item_id.id); + if let ItemKind::OpaqueTy(opaque) = &item.kind; + if opaque.bounds.len() == 1; + if let GenericBound::Trait(poly, _) = &opaque.bounds[0]; + let path = poly.trait_ref.path; + if match_path(&path, &FUTURE_CORE) || match_path(&path, &FUTURE_STD); + then { + return Some(&poly.trait_ref); + } + } + + None +} + +fn future_output_ty<'tcx>(trait_ref: &'tcx TraitRef<'tcx>) -> Option<&'tcx Ty<'tcx>> { + if_chain! { + if let Some(segment) = trait_ref.path.segments.last(); + if let Some(args) = segment.args; + if args.bindings.len() == 1; + let binding = &args.bindings[0]; + if binding.ident.as_str() == "Output"; + if let TypeBindingKind::Equality{ty: output} = binding.kind; + then { + return Some(output) + } + } + + None +} + +fn desugared_async_block<'tcx>(cx: &LateContext<'_, 'tcx>, block: &'tcx Block<'tcx>) -> Option<&'tcx Body<'tcx>> { + if_chain! { + if let Some(block_expr) = block.expr; + if let Some(args) = match_function_call(cx, block_expr, &FUTURE_FROM_GENERATOR); + if args.len() == 1; + if let Expr{kind: ExprKind::Closure(_, _, body_id, ..), ..} = args[0]; + let closure_body = cx.tcx.hir().body(body_id); + if let Some(GeneratorKind::Async(AsyncGeneratorKind::Block)) = closure_body.generator_kind; + then { + return Some(closure_body); + } + } + + None +} + +fn suggested_ret(cx: &LateContext<'_, '_>, output: &Ty<'_>) -> Option<(&'static str, String)> { + match output.kind { + TyKind::Tup(tys) if tys.is_empty() => { + let sugg = "remove the return type"; + Some((sugg, "".into())) + }, + _ => { + let sugg = "return the output of the future directly"; + snippet_opt(cx, output.span).map(|snip| (sugg, format!("-> {}", snip))) + }, + } +} diff --git a/clippy_lints/src/utils/paths.rs b/clippy_lints/src/utils/paths.rs index 79ca6845c6f2..74040a96c78a 100644 --- a/clippy_lints/src/utils/paths.rs +++ b/clippy_lints/src/utils/paths.rs @@ -42,6 +42,9 @@ pub const FMT_ARGUMENTS_NEW_V1_FORMATTED: [&str; 4] = ["core", "fmt", "Arguments pub const FMT_ARGUMENTV1_NEW: [&str; 4] = ["core", "fmt", "ArgumentV1", "new"]; pub const FROM_FROM: [&str; 4] = ["core", "convert", "From", "from"]; pub const FROM_TRAIT: [&str; 3] = ["core", "convert", "From"]; +pub const FUTURE_CORE: [&str; 3] = ["core", "future", "Future"]; +pub const FUTURE_FROM_GENERATOR: [&str; 3] = ["core", "future", "from_generator"]; +pub const FUTURE_STD: [&str; 3] = ["std", "future", "Future"]; pub const HASH: [&str; 2] = ["hash", "Hash"]; pub const HASHMAP: [&str; 5] = ["std", "collections", "hash", "map", "HashMap"]; pub const HASHMAP_ENTRY: [&str; 5] = ["std", "collections", "hash", "map", "Entry"]; diff --git a/src/lintlist/mod.rs b/src/lintlist/mod.rs index a7685f67211f..51d1cb2216a9 100644 --- a/src/lintlist/mod.rs +++ b/src/lintlist/mod.rs @@ -1081,6 +1081,13 @@ pub static ref ALL_LINTS: Vec = vec![ deprecation: None, module: "main_recursion", }, + Lint { + name: "manual_async_fn", + group: "style", + desc: "manual implementations of `async` functions can be simplified using the dedicated syntax", + deprecation: None, + module: "manual_async_fn", + }, Lint { name: "manual_memcpy", group: "perf", diff --git a/tests/ui/future_not_send.rs b/tests/ui/future_not_send.rs index 6d09d71a630a..d3a920de4b6a 100644 --- a/tests/ui/future_not_send.rs +++ b/tests/ui/future_not_send.rs @@ -41,6 +41,7 @@ impl Dummy { self.private_future().await; } + #[allow(clippy::manual_async_fn)] pub fn public_send(&self) -> impl std::future::Future { async { false } } diff --git a/tests/ui/future_not_send.stderr b/tests/ui/future_not_send.stderr index 3b4968ef0a63..d1863701bfe7 100644 --- a/tests/ui/future_not_send.stderr +++ b/tests/ui/future_not_send.stderr @@ -96,13 +96,13 @@ LL | } = note: `std::rc::Rc<[u8]>` doesn't implement `std::marker::Sync` error: future cannot be sent between threads safely - --> $DIR/future_not_send.rs:49:37 + --> $DIR/future_not_send.rs:50:37 | LL | async fn generic_future(t: T) -> T | ^ future returned by `generic_future` is not `Send` | note: future is not `Send` as this value is used across an await - --> $DIR/future_not_send.rs:54:5 + --> $DIR/future_not_send.rs:55:5 | LL | let rt = &t; | -- has type `&T` which is not `Send` @@ -114,7 +114,7 @@ LL | } = note: `T` doesn't implement `std::marker::Sync` error: future cannot be sent between threads safely - --> $DIR/future_not_send.rs:65:34 + --> $DIR/future_not_send.rs:66:34 | LL | async fn unclear_future(t: T) {} | ^ diff --git a/tests/ui/manual_async_fn.fixed b/tests/ui/manual_async_fn.fixed new file mode 100644 index 000000000000..84c02bba4dcb --- /dev/null +++ b/tests/ui/manual_async_fn.fixed @@ -0,0 +1,55 @@ +// run-rustfix +// edition:2018 +#![warn(clippy::manual_async_fn)] +#![allow(unused)] + +use std::future::Future; + +async fn fut() -> i32 { 42 } + +async fn empty_fut() {} + +async fn core_fut() -> i32 { 42 } + +// should be ignored +fn has_other_stmts() -> impl core::future::Future { + let _ = 42; + async move { 42 } +} + +// should be ignored +fn not_fut() -> i32 { + 42 +} + +// should be ignored +async fn already_async() -> impl Future { + async { 42 } +} + +struct S {} +impl S { + async fn inh_fut() -> i32 { 42 } + + async fn meth_fut(&self) -> i32 { 42 } + + async fn empty_fut(&self) {} + + // should be ignored + fn not_fut(&self) -> i32 { + 42 + } + + // should be ignored + fn has_other_stmts() -> impl core::future::Future { + let _ = 42; + async move { 42 } + } + + // should be ignored + async fn already_async(&self) -> impl Future { + async { 42 } + } +} + +fn main() {} diff --git a/tests/ui/manual_async_fn.rs b/tests/ui/manual_async_fn.rs new file mode 100644 index 000000000000..bd5f9d1cf5f2 --- /dev/null +++ b/tests/ui/manual_async_fn.rs @@ -0,0 +1,67 @@ +// run-rustfix +// edition:2018 +#![warn(clippy::manual_async_fn)] +#![allow(unused)] + +use std::future::Future; + +fn fut() -> impl Future { + async { 42 } +} + +fn empty_fut() -> impl Future { + async {} +} + +fn core_fut() -> impl core::future::Future { + async move { 42 } +} + +// should be ignored +fn has_other_stmts() -> impl core::future::Future { + let _ = 42; + async move { 42 } +} + +// should be ignored +fn not_fut() -> i32 { + 42 +} + +// should be ignored +async fn already_async() -> impl Future { + async { 42 } +} + +struct S {} +impl S { + fn inh_fut() -> impl Future { + async { 42 } + } + + fn meth_fut(&self) -> impl Future { + async { 42 } + } + + fn empty_fut(&self) -> impl Future { + async {} + } + + // should be ignored + fn not_fut(&self) -> i32 { + 42 + } + + // should be ignored + fn has_other_stmts() -> impl core::future::Future { + let _ = 42; + async move { 42 } + } + + // should be ignored + async fn already_async(&self) -> impl Future { + async { 42 } + } +} + +fn main() {} diff --git a/tests/ui/manual_async_fn.stderr b/tests/ui/manual_async_fn.stderr new file mode 100644 index 000000000000..016fdf959772 --- /dev/null +++ b/tests/ui/manual_async_fn.stderr @@ -0,0 +1,93 @@ +error: this function can be simplified using async syntax + --> $DIR/manual_async_fn.rs:8:1 + | +LL | fn fut() -> impl Future { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `-D clippy::manual-async-fn` implied by `-D warnings` +help: make the function `async` and return the output of the future directly + | +LL | async fn fut() -> i32 { + | ^^^^^^^^^^^^^^^^^^^^^ +help: move the body of the async block to the enclosing function + | +LL | fn fut() -> impl Future { 42 } + | ^^^^^^ + +error: this function can be simplified using async syntax + --> $DIR/manual_async_fn.rs:12:1 + | +LL | fn empty_fut() -> impl Future { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: make the function `async` and remove the return type + | +LL | async fn empty_fut() { + | ^^^^^^^^^^^^^^^^^^^^ +help: move the body of the async block to the enclosing function + | +LL | fn empty_fut() -> impl Future {} + | ^^ + +error: this function can be simplified using async syntax + --> $DIR/manual_async_fn.rs:16:1 + | +LL | fn core_fut() -> impl core::future::Future { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: make the function `async` and return the output of the future directly + | +LL | async fn core_fut() -> i32 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: move the body of the async block to the enclosing function + | +LL | fn core_fut() -> impl core::future::Future { 42 } + | ^^^^^^ + +error: this function can be simplified using async syntax + --> $DIR/manual_async_fn.rs:38:5 + | +LL | fn inh_fut() -> impl Future { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: make the function `async` and return the output of the future directly + | +LL | async fn inh_fut() -> i32 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +help: move the body of the async block to the enclosing function + | +LL | fn inh_fut() -> impl Future { 42 } + | ^^^^^^ + +error: this function can be simplified using async syntax + --> $DIR/manual_async_fn.rs:42:5 + | +LL | fn meth_fut(&self) -> impl Future { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: make the function `async` and return the output of the future directly + | +LL | async fn meth_fut(&self) -> i32 { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: move the body of the async block to the enclosing function + | +LL | fn meth_fut(&self) -> impl Future { 42 } + | ^^^^^^ + +error: this function can be simplified using async syntax + --> $DIR/manual_async_fn.rs:46:5 + | +LL | fn empty_fut(&self) -> impl Future { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: make the function `async` and remove the return type + | +LL | async fn empty_fut(&self) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +help: move the body of the async block to the enclosing function + | +LL | fn empty_fut(&self) -> impl Future {} + | ^^ + +error: aborting due to 6 previous errors + From 4ac348b30849ec472564a81797b7e9ae42985460 Mon Sep 17 00:00:00 2001 From: Eduardo Broto Date: Thu, 7 May 2020 22:03:38 +0200 Subject: [PATCH 057/203] Fix doc comment in lint declaration --- clippy_lints/src/manual_async_fn.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/manual_async_fn.rs b/clippy_lints/src/manual_async_fn.rs index ab8829abbf2e..b4be3ecfd162 100644 --- a/clippy_lints/src/manual_async_fn.rs +++ b/clippy_lints/src/manual_async_fn.rs @@ -23,7 +23,7 @@ declare_clippy_lint! { /// ```rust /// use std::future::Future; /// - /// fn foo() -> Future { async { 42 } } + /// fn foo() -> impl Future { async { 42 } } /// ``` /// Use instead: /// ```rust From 3e4bc026e2706b1cb21bad6d55726f8b5a1d4cf1 Mon Sep 17 00:00:00 2001 From: Eduardo Broto Date: Thu, 7 May 2020 22:40:28 +0200 Subject: [PATCH 058/203] Apply suggestions from PR review --- clippy_lints/src/manual_async_fn.rs | 9 ++++----- clippy_lints/src/utils/paths.rs | 2 -- tests/ui/manual_async_fn.fixed | 14 +++++++++++++- tests/ui/manual_async_fn.rs | 14 +++++++++++++- tests/ui/manual_async_fn.stderr | 25 +++++++++++++++---------- 5 files changed, 45 insertions(+), 19 deletions(-) diff --git a/clippy_lints/src/manual_async_fn.rs b/clippy_lints/src/manual_async_fn.rs index b4be3ecfd162..cb72a2405823 100644 --- a/clippy_lints/src/manual_async_fn.rs +++ b/clippy_lints/src/manual_async_fn.rs @@ -1,5 +1,5 @@ -use crate::utils::paths::{FUTURE_CORE, FUTURE_FROM_GENERATOR, FUTURE_STD}; -use crate::utils::{match_function_call, match_path, snippet_block, snippet_opt, span_lint_and_then}; +use crate::utils::paths::FUTURE_FROM_GENERATOR; +use crate::utils::{match_function_call, snippet_block, snippet_opt, span_lint_and_then}; use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::intravisit::FnKind; @@ -66,7 +66,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ManualAsyncFn { cx, MANUAL_ASYNC_FN, header_span, - "this function can be simplified using async syntax", + "this function can be simplified using the `async fn` syntax", |diag| { if_chain! { if let Some(header_snip) = snippet_opt(cx, header_span); @@ -104,8 +104,7 @@ fn future_trait_ref<'tcx>(cx: &LateContext<'_, 'tcx>, ty: &'tcx Ty<'tcx>) -> Opt if let ItemKind::OpaqueTy(opaque) = &item.kind; if opaque.bounds.len() == 1; if let GenericBound::Trait(poly, _) = &opaque.bounds[0]; - let path = poly.trait_ref.path; - if match_path(&path, &FUTURE_CORE) || match_path(&path, &FUTURE_STD); + if poly.trait_ref.trait_def_id() == cx.tcx.lang_items().future_trait(); then { return Some(&poly.trait_ref); } diff --git a/clippy_lints/src/utils/paths.rs b/clippy_lints/src/utils/paths.rs index 74040a96c78a..b3ad2ad9d998 100644 --- a/clippy_lints/src/utils/paths.rs +++ b/clippy_lints/src/utils/paths.rs @@ -42,9 +42,7 @@ pub const FMT_ARGUMENTS_NEW_V1_FORMATTED: [&str; 4] = ["core", "fmt", "Arguments pub const FMT_ARGUMENTV1_NEW: [&str; 4] = ["core", "fmt", "ArgumentV1", "new"]; pub const FROM_FROM: [&str; 4] = ["core", "convert", "From", "from"]; pub const FROM_TRAIT: [&str; 3] = ["core", "convert", "From"]; -pub const FUTURE_CORE: [&str; 3] = ["core", "future", "Future"]; pub const FUTURE_FROM_GENERATOR: [&str; 3] = ["core", "future", "from_generator"]; -pub const FUTURE_STD: [&str; 3] = ["std", "future", "Future"]; pub const HASH: [&str; 2] = ["hash", "Hash"]; pub const HASHMAP: [&str; 5] = ["std", "collections", "hash", "map", "HashMap"]; pub const HASHMAP_ENTRY: [&str; 5] = ["std", "collections", "hash", "map", "Entry"]; diff --git a/tests/ui/manual_async_fn.fixed b/tests/ui/manual_async_fn.fixed index 84c02bba4dcb..6bb1032a1729 100644 --- a/tests/ui/manual_async_fn.fixed +++ b/tests/ui/manual_async_fn.fixed @@ -29,7 +29,19 @@ async fn already_async() -> impl Future { struct S {} impl S { - async fn inh_fut() -> i32 { 42 } + async fn inh_fut() -> i32 { + // NOTE: this code is here just to check that the identation is correct in the suggested fix + let a = 42; + let b = 21; + if a < b { + let c = 21; + let d = 42; + if c < d { + let _ = 42; + } + } + 42 + } async fn meth_fut(&self) -> i32 { 42 } diff --git a/tests/ui/manual_async_fn.rs b/tests/ui/manual_async_fn.rs index bd5f9d1cf5f2..d50c919188be 100644 --- a/tests/ui/manual_async_fn.rs +++ b/tests/ui/manual_async_fn.rs @@ -36,7 +36,19 @@ async fn already_async() -> impl Future { struct S {} impl S { fn inh_fut() -> impl Future { - async { 42 } + async { + // NOTE: this code is here just to check that the identation is correct in the suggested fix + let a = 42; + let b = 21; + if a < b { + let c = 21; + let d = 42; + if c < d { + let _ = 42; + } + } + 42 + } } fn meth_fut(&self) -> impl Future { diff --git a/tests/ui/manual_async_fn.stderr b/tests/ui/manual_async_fn.stderr index 016fdf959772..f278ee41aa33 100644 --- a/tests/ui/manual_async_fn.stderr +++ b/tests/ui/manual_async_fn.stderr @@ -1,4 +1,4 @@ -error: this function can be simplified using async syntax +error: this function can be simplified using the `async fn` syntax --> $DIR/manual_async_fn.rs:8:1 | LL | fn fut() -> impl Future { @@ -14,7 +14,7 @@ help: move the body of the async block to the enclosing function LL | fn fut() -> impl Future { 42 } | ^^^^^^ -error: this function can be simplified using async syntax +error: this function can be simplified using the `async fn` syntax --> $DIR/manual_async_fn.rs:12:1 | LL | fn empty_fut() -> impl Future { @@ -29,7 +29,7 @@ help: move the body of the async block to the enclosing function LL | fn empty_fut() -> impl Future {} | ^^ -error: this function can be simplified using async syntax +error: this function can be simplified using the `async fn` syntax --> $DIR/manual_async_fn.rs:16:1 | LL | fn core_fut() -> impl core::future::Future { @@ -44,7 +44,7 @@ help: move the body of the async block to the enclosing function LL | fn core_fut() -> impl core::future::Future { 42 } | ^^^^^^ -error: this function can be simplified using async syntax +error: this function can be simplified using the `async fn` syntax --> $DIR/manual_async_fn.rs:38:5 | LL | fn inh_fut() -> impl Future { @@ -56,11 +56,16 @@ LL | async fn inh_fut() -> i32 { | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: move the body of the async block to the enclosing function | -LL | fn inh_fut() -> impl Future { 42 } - | ^^^^^^ +LL | fn inh_fut() -> impl Future { +LL | // NOTE: this code is here just to check that the identation is correct in the suggested fix +LL | let a = 42; +LL | let b = 21; +LL | if a < b { +LL | let c = 21; + ... -error: this function can be simplified using async syntax - --> $DIR/manual_async_fn.rs:42:5 +error: this function can be simplified using the `async fn` syntax + --> $DIR/manual_async_fn.rs:54:5 | LL | fn meth_fut(&self) -> impl Future { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -74,8 +79,8 @@ help: move the body of the async block to the enclosing function LL | fn meth_fut(&self) -> impl Future { 42 } | ^^^^^^ -error: this function can be simplified using async syntax - --> $DIR/manual_async_fn.rs:46:5 +error: this function can be simplified using the `async fn` syntax + --> $DIR/manual_async_fn.rs:58:5 | LL | fn empty_fut(&self) -> impl Future { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ From abbc7365a726269e13b7ee2864bb6086dfc41d69 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 8 May 2020 15:19:14 +0200 Subject: [PATCH 059/203] Add emoji for deprecated messages --- src/librustdoc/html/render.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 666e59b9a045..82f91e232df3 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -2281,7 +2281,10 @@ fn short_stability(item: &clean::Item, cx: &Context) -> Vec { ); message.push_str(&format!(": {}", html.to_string())); } - stability.push(format!("
{}
", message)); + stability.push(format!( + "
👎 {}
", + message, + )); } if let Some(stab) = item.stability.as_ref().filter(|stab| stab.level == stability::Unstable) { From 9d8310856b3a42aa99d6591244a6679284011dc9 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 8 May 2020 15:27:08 +0200 Subject: [PATCH 060/203] Add test for deprecated emoji --- src/test/rustdoc/issue-32374.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/rustdoc/issue-32374.rs b/src/test/rustdoc/issue-32374.rs index 7babfaf6060f..11caa34d4b11 100644 --- a/src/test/rustdoc/issue-32374.rs +++ b/src/test/rustdoc/issue-32374.rs @@ -10,7 +10,7 @@ // @matches issue_32374/index.html '//*[@class="docblock-short"]/text()' 'Docs' // @has issue_32374/struct.T.html '//*[@class="stab deprecated"]' \ -// 'Deprecated since 1.0.0: text' +// '👎 Deprecated since 1.0.0: text' // @has - 'test 
#32374' // @matches issue_32374/struct.T.html '//*[@class="stab unstable"]' \ // '🔬 This is a nightly-only experimental API. \(test\s#32374\)$' @@ -20,7 +20,7 @@ pub struct T; // @has issue_32374/struct.U.html '//*[@class="stab deprecated"]' \ -// 'Deprecated since 1.0.0: deprecated' +// '👎 Deprecated since 1.0.0: deprecated' // @has issue_32374/struct.U.html '//*[@class="stab unstable"]' \ // '🔬 This is a nightly-only experimental API. (test #32374)' // @has issue_32374/struct.U.html '//details' \ From bbda107436c01204614dce4cff70a0b475945a9d Mon Sep 17 00:00:00 2001 From: mibac138 <5672750+mibac138@users.noreply.github.com> Date: Fri, 8 May 2020 18:14:57 +0200 Subject: [PATCH 061/203] Add test for strikethrough in rustdoc --- src/test/rustdoc/test-strikethrough.rs | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 src/test/rustdoc/test-strikethrough.rs diff --git a/src/test/rustdoc/test-strikethrough.rs b/src/test/rustdoc/test-strikethrough.rs new file mode 100644 index 000000000000..c7855729a98e --- /dev/null +++ b/src/test/rustdoc/test-strikethrough.rs @@ -0,0 +1,6 @@ +#![crate_name = "foo"] + +// @has foo/fn.f.html +// @has - //del "Y" +/// ~~Y~~ +pub fn f() {} From 619c6055e71a5a202cba3f5cb979f17c3581faa3 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Fri, 8 May 2020 17:25:18 +0100 Subject: [PATCH 062/203] Fix debug assertion in error code --- .../traits/error_reporting/suggestions.rs | 9 +++++++++ ...m-ref-trait-object-literal-bound-regions.rs | 18 ++++++++++++++++++ ...f-trait-object-literal-bound-regions.stderr | 18 ++++++++++++++++++ 3 files changed, 45 insertions(+) create mode 100644 src/test/ui/suggestions/imm-ref-trait-object-literal-bound-regions.rs create mode 100644 src/test/ui/suggestions/imm-ref-trait-object-literal-bound-regions.stderr diff --git a/src/librustc_trait_selection/traits/error_reporting/suggestions.rs b/src/librustc_trait_selection/traits/error_reporting/suggestions.rs index ce7b1390d46b..3c8aa08bdca9 100644 --- a/src/librustc_trait_selection/traits/error_reporting/suggestions.rs +++ b/src/librustc_trait_selection/traits/error_reporting/suggestions.rs @@ -691,6 +691,15 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { } if let ty::Ref(region, t_type, mutability) = trait_ref.skip_binder().self_ty().kind { + if region.is_late_bound() || t_type.has_escaping_bound_vars() { + // Avoid debug assertion in `mk_obligation_for_def_id`. + // + // If the self type has escaping bound vars then it's not + // going to be the type of an expression, so the suggestion + // probably won't apply anyway. + return; + } + let trait_type = match mutability { hir::Mutability::Mut => self.tcx.mk_imm_ref(region, t_type), hir::Mutability::Not => self.tcx.mk_mut_ref(region, t_type), diff --git a/src/test/ui/suggestions/imm-ref-trait-object-literal-bound-regions.rs b/src/test/ui/suggestions/imm-ref-trait-object-literal-bound-regions.rs new file mode 100644 index 000000000000..319789c4ec28 --- /dev/null +++ b/src/test/ui/suggestions/imm-ref-trait-object-literal-bound-regions.rs @@ -0,0 +1,18 @@ +// Regression test for #70813 (this used to trigger a debug assertion) + +trait Trait {} + +struct S; + +impl<'a> Trait for &'a mut S {} + +fn foo(_: X) +where + for<'b> &'b X: Trait, +{ +} + +fn main() { + let s = S; + foo::(s); //~ ERROR the trait bound `for<'b> &'b S: Trait` is not satisfied +} diff --git a/src/test/ui/suggestions/imm-ref-trait-object-literal-bound-regions.stderr b/src/test/ui/suggestions/imm-ref-trait-object-literal-bound-regions.stderr new file mode 100644 index 000000000000..83de3c4cfe0a --- /dev/null +++ b/src/test/ui/suggestions/imm-ref-trait-object-literal-bound-regions.stderr @@ -0,0 +1,18 @@ +error[E0277]: the trait bound `for<'b> &'b S: Trait` is not satisfied + --> $DIR/imm-ref-trait-object-literal-bound-regions.rs:17:5 + | +LL | fn foo(_: X) + | --- required by a bound in this +LL | where +LL | for<'b> &'b X: Trait, + | ----- required by this bound in `foo` +... +LL | foo::(s); + | ^^^^^^^^ the trait `for<'b> Trait` is not implemented for `&'b S` + | + = help: the following implementations were found: + <&'a mut S as Trait> + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. From 54b7d45564e06a97ca30d9f8e64aa6cd007c2805 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Fri, 8 May 2020 17:34:39 -0400 Subject: [PATCH 063/203] Use CDN for ci-caches on download This will reduce costs, as well as lays the groundwork for developers to be able to locally pull the published docker images without needing AWS credentials. --- src/ci/docker/run.sh | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/ci/docker/run.sh b/src/ci/docker/run.sh index f29f9f3bf1c4..d891ad1b6680 100755 --- a/src/ci/docker/run.sh +++ b/src/ci/docker/run.sh @@ -17,6 +17,8 @@ dist=$objdir/build/dist source "$ci_dir/shared.sh" +CACHE_DOMAIN="${CACHE_DOMAIN:-ci-caches.rust-lang.org}" + if [ -f "$docker_dir/$image/Dockerfile" ]; then if [ "$CI" != "" ]; then hash_key=/tmp/.docker-hash-key.txt @@ -38,9 +40,7 @@ if [ -f "$docker_dir/$image/Dockerfile" ]; then cksum=$(sha512sum $hash_key | \ awk '{print $1}') - s3url="s3://$SCCACHE_BUCKET/docker/$cksum" - url="https://$SCCACHE_BUCKET.s3.amazonaws.com/docker/$cksum" - upload="aws s3 cp - $s3url" + url="https://$CACHE_DOMAIN/docker/$cksum" echo "Attempting to download $url" rm -f /tmp/rustci_docker_cache @@ -65,7 +65,9 @@ if [ -f "$docker_dir/$image/Dockerfile" ]; then -f "$dockerfile" \ "$context" - if [ "$upload" != "" ]; then + if [ "$CI" != "" ]; then + s3url="s3://$SCCACHE_BUCKET/docker/$cksum" + upload="aws s3 cp - $s3url" digest=$(docker inspect rust-ci --format '{{.Id}}') echo "Built container $digest" if ! grep -q "$digest" <(echo "$loaded_images"); then From 438877380a2bf591fc1294ab31bc7fb2598738ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Sat, 9 May 2020 01:27:30 +0200 Subject: [PATCH 064/203] deps: remove unused regex dependency from root crate --- Cargo.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 63ce2cd8cad7..6999b6bd7404 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -31,7 +31,6 @@ path = "src/driver.rs" # begin automatic update clippy_lints = { version = "0.0.212", path = "clippy_lints" } # end automatic update -regex = "1" semver = "0.9" rustc_tools_util = { version = "0.2.0", path = "rustc_tools_util"} tempfile = { version = "3.1.0", optional = true } From e734e31340586f14c29efa6396ae15ad37f84a96 Mon Sep 17 00:00:00 2001 From: Julian Wollersberger <24991778+Julian-Wollersberger@users.noreply.github.com> Date: Sat, 25 Apr 2020 20:19:54 +0200 Subject: [PATCH 065/203] Small doc improvements. The phrasing is from the commit description of 395ee0b79f23b90593b01dd0a78451b8c93b0aa6 by @Matklad. --- src/librustc_lexer/src/lib.rs | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/librustc_lexer/src/lib.rs b/src/librustc_lexer/src/lib.rs index 5ccfc1b276bf..e44feee96607 100644 --- a/src/librustc_lexer/src/lib.rs +++ b/src/librustc_lexer/src/lib.rs @@ -1,5 +1,11 @@ //! Low-level Rust lexer. //! +//! The idea with `librustc_lexer` is to make a reusable library, +//! by separating out pure lexing and rustc-specific concerns, like spans, +//! error reporting an interning. So, rustc_lexer operates directly on `&str`, +//! produces simple tokens which are a pair of type-tag and a bit of original text, +//! and does not report errors, instead storing them as flags on the token. +//! //! Tokens produced by this lexer are not yet ready for parsing the Rust syntax, //! for that see `librustc_parse::lexer`, which converts this basic token stream //! into wide tokens used by actual parser. @@ -719,6 +725,9 @@ impl Cursor<'_> { // Check that amount of closing '#' symbols // is equal to the amount of opening ones. + // Note that this will not consume extra trailing `#` characters: + // `r###"abcde"####` is lexed as a `LexedRawString { n_hashes: 3 }` + // followed by a `#` token. let mut hashes_left = n_start_hashes; let is_closing_hash = |c| { if c == '#' && hashes_left != 0 { @@ -739,8 +748,8 @@ impl Cursor<'_> { possible_terminator_offset: None, }; } else if n_end_hashes > max_hashes { - // Keep track of possible terminators to give a hint about where there might be - // a missing terminator + // Keep track of possible terminators to give a hint about + // where there might be a missing terminator possible_terminator_offset = Some(self.len_consumed() - start_pos - n_end_hashes + prefix_len); max_hashes = n_end_hashes; From 1fce20340a6422b5e1f9738b82a304c4c389171c Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 9 May 2020 14:04:32 +0200 Subject: [PATCH 066/203] expand "incomplete feature" message to include unsoundness and link to tracking issue --- src/librustc_lint/builtin.rs | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index cad6a312521e..201dfba91c92 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -28,8 +28,8 @@ use rustc_ast::visit::{FnCtxt, FnKind}; use rustc_ast_pretty::pprust::{self, expr_to_string}; use rustc_data_structures::fx::FxHashSet; use rustc_errors::{Applicability, DiagnosticBuilder}; -use rustc_feature::Stability; use rustc_feature::{deprecated_attributes, AttributeGate, AttributeTemplate, AttributeType}; +use rustc_feature::{GateIssue, Stability}; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::DefId; @@ -1817,13 +1817,21 @@ impl EarlyLintPass for IncompleteFeatures { .map(|(name, span, _)| (name, span)) .chain(features.declared_lib_features.iter().map(|(name, span)| (name, span))) .filter(|(name, _)| rustc_feature::INCOMPLETE_FEATURES.iter().any(|f| name == &f)) - .for_each(|(name, &span)| { + .for_each(|(&name, &span)| { cx.struct_span_lint(INCOMPLETE_FEATURES, span, |lint| { - lint.build(&format!( - "the feature `{}` is incomplete and may cause the compiler to crash", + let mut builder = lint.build(&format!( + "the feature `{}` is incomplete and may not be safe to use \ + and/or cause compiler crashes", name, - )) - .emit() + )); + if let Some(n) = rustc_feature::find_feature_issue(name, GateIssue::Language) { + builder.note(&format!( + "see issue #{} \ + for more information", + n, n, + )); + } + builder.emit(); }) }); } From 6a8cf4a17c2d2b3daca27e787f4154e233ab4545 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 22 Apr 2020 10:21:32 +0200 Subject: [PATCH 067/203] adjust tests --- src/test/incremental/const-generics/issue-62536.rs | 2 +- src/test/incremental/const-generics/issue-64087.rs | 2 +- src/test/ui/array-slice-vec/match_arr_unknown_len.rs | 2 +- src/test/ui/array-slice-vec/match_arr_unknown_len.stderr | 3 ++- src/test/ui/associated-type-bounds/duplicate.rs | 2 +- src/test/ui/associated-type-bounds/duplicate.stderr | 3 ++- src/test/ui/associated-type-bounds/dyn-lcsit.stderr | 3 ++- src/test/ui/associated-type-bounds/lcsit.stderr | 3 ++- src/test/ui/binding/const-param.stderr | 3 ++- src/test/ui/const-generics/apit-with-const-param.rs | 2 +- src/test/ui/const-generics/apit-with-const-param.stderr | 3 ++- src/test/ui/const-generics/argument_order.rs | 2 +- src/test/ui/const-generics/argument_order.stderr | 3 ++- .../const-generics/array-size-in-generic-struct-param.rs | 2 +- .../array-size-in-generic-struct-param.stderr | 3 ++- src/test/ui/const-generics/array-wrapper-struct-ctor.rs | 2 +- .../ui/const-generics/array-wrapper-struct-ctor.stderr | 3 ++- src/test/ui/const-generics/broken-mir-1.rs | 2 +- src/test/ui/const-generics/broken-mir-1.stderr | 3 ++- src/test/ui/const-generics/broken-mir-2.rs | 2 +- src/test/ui/const-generics/broken-mir-2.stderr | 3 ++- src/test/ui/const-generics/cannot-infer-const-args.rs | 2 +- src/test/ui/const-generics/cannot-infer-const-args.stderr | 3 ++- .../ui/const-generics/cannot-infer-type-for-const-param.rs | 2 +- .../cannot-infer-type-for-const-param.stderr | 3 ++- src/test/ui/const-generics/concrete-const-as-fn-arg.rs | 2 +- src/test/ui/const-generics/concrete-const-as-fn-arg.stderr | 3 ++- src/test/ui/const-generics/concrete-const-impl-method.rs | 2 +- .../ui/const-generics/concrete-const-impl-method.stderr | 3 ++- src/test/ui/const-generics/condition-in-trait-const-arg.rs | 2 +- .../ui/const-generics/condition-in-trait-const-arg.stderr | 3 ++- src/test/ui/const-generics/const-arg-in-fn.rs | 2 +- src/test/ui/const-generics/const-arg-in-fn.stderr | 3 ++- .../ui/const-generics/const-arg-type-arg-misordered.rs | 2 +- .../ui/const-generics/const-arg-type-arg-misordered.stderr | 3 ++- src/test/ui/const-generics/const-expression-parameter.rs | 2 +- .../ui/const-generics/const-expression-parameter.stderr | 3 ++- src/test/ui/const-generics/const-fn-with-const-param.rs | 2 +- .../ui/const-generics/const-fn-with-const-param.stderr | 3 ++- src/test/ui/const-generics/const-generic-array-wrapper.rs | 2 +- .../ui/const-generics/const-generic-array-wrapper.stderr | 3 ++- src/test/ui/const-generics/const-generic-type_name.rs | 2 +- src/test/ui/const-generics/const-generic-type_name.stderr | 3 ++- src/test/ui/const-generics/const-param-elided-lifetime.rs | 2 +- .../ui/const-generics/const-param-elided-lifetime.stderr | 3 ++- src/test/ui/const-generics/const-param-from-outer-fn.rs | 2 +- .../ui/const-generics/const-param-from-outer-fn.stderr | 3 ++- src/test/ui/const-generics/const-param-in-trait.rs | 2 +- src/test/ui/const-generics/const-param-in-trait.stderr | 3 ++- .../const-param-type-depends-on-type-param.rs | 2 +- .../const-param-type-depends-on-type-param.stderr | 3 ++- .../ui/const-generics/const-parameter-uppercase-lint.rs | 2 +- .../const-generics/const-parameter-uppercase-lint.stderr | 3 ++- src/test/ui/const-generics/const-types.rs | 2 +- src/test/ui/const-generics/const-types.stderr | 3 ++- src/test/ui/const-generics/derive-debug-array-wrapper.rs | 2 +- .../ui/const-generics/derive-debug-array-wrapper.stderr | 3 ++- src/test/ui/const-generics/different_byref.rs | 2 +- src/test/ui/const-generics/different_byref.stderr | 3 ++- src/test/ui/const-generics/fn-const-param-call.rs | 2 +- src/test/ui/const-generics/fn-const-param-call.stderr | 3 ++- src/test/ui/const-generics/fn-const-param-infer.rs | 2 +- src/test/ui/const-generics/fn-const-param-infer.stderr | 3 ++- .../ui/const-generics/fn-taking-const-generic-array.rs | 2 +- .../ui/const-generics/fn-taking-const-generic-array.stderr | 3 ++- .../ui/const-generics/forbid-non-structural_match-types.rs | 2 +- .../forbid-non-structural_match-types.stderr | 3 ++- src/test/ui/const-generics/foreign-item-const-parameter.rs | 2 +- .../ui/const-generics/foreign-item-const-parameter.stderr | 3 ++- src/test/ui/const-generics/impl-const-generic-struct.rs | 2 +- .../ui/const-generics/impl-const-generic-struct.stderr | 3 ++- .../ui/const-generics/incorrect-number-of-const-args.rs | 2 +- .../const-generics/incorrect-number-of-const-args.stderr | 3 ++- src/test/ui/const-generics/infer_arg_from_pat.rs | 2 +- src/test/ui/const-generics/infer_arg_from_pat.stderr | 3 ++- src/test/ui/const-generics/infer_arr_len_from_pat.rs | 2 +- src/test/ui/const-generics/infer_arr_len_from_pat.stderr | 3 ++- .../integer-literal-generic-arg-in-where-clause.rs | 2 +- .../integer-literal-generic-arg-in-where-clause.stderr | 3 ++- src/test/ui/const-generics/issue-61522-array-len-succ.rs | 2 +- .../ui/const-generics/issue-61522-array-len-succ.stderr | 3 ++- .../issue-66596-impl-trait-for-str-const-arg.rs | 2 +- .../issue-66596-impl-trait-for-str-const-arg.stderr | 3 ++- .../issues/issue-60818-struct-constructors.rs | 2 +- .../issues/issue-60818-struct-constructors.stderr | 3 ++- src/test/ui/const-generics/issues/issue-61336-1.rs | 2 +- src/test/ui/const-generics/issues/issue-61336-1.stderr | 3 ++- src/test/ui/const-generics/issues/issue-61336-2.rs | 2 +- src/test/ui/const-generics/issues/issue-61336-2.stderr | 3 ++- src/test/ui/const-generics/issues/issue-61336.rs | 2 +- src/test/ui/const-generics/issues/issue-61336.stderr | 3 ++- src/test/ui/const-generics/issues/issue-61422.rs | 2 +- src/test/ui/const-generics/issues/issue-61422.stderr | 3 ++- src/test/ui/const-generics/issues/issue-61432.rs | 2 +- src/test/ui/const-generics/issues/issue-61432.stderr | 3 ++- src/test/ui/const-generics/issues/issue-61747.rs | 2 +- src/test/ui/const-generics/issues/issue-61747.stderr | 3 ++- .../issues/issue-62187-encountered-polymorphic-const.rs | 2 +- .../issue-62187-encountered-polymorphic-const.stderr | 3 ++- src/test/ui/const-generics/issues/issue-62456.rs | 2 +- src/test/ui/const-generics/issues/issue-62456.stderr | 3 ++- src/test/ui/const-generics/issues/issue-62579-no-match.rs | 2 +- .../ui/const-generics/issues/issue-62579-no-match.stderr | 3 ++- .../ui/const-generics/issues/issue-63322-forbid-dyn.rs | 2 +- .../ui/const-generics/issues/issue-63322-forbid-dyn.stderr | 3 ++- src/test/ui/const-generics/issues/issue-64519.rs | 2 +- src/test/ui/const-generics/issues/issue-64519.stderr | 3 ++- src/test/ui/const-generics/issues/issue-66906.rs | 2 +- src/test/ui/const-generics/issues/issue-66906.stderr | 3 ++- src/test/ui/const-generics/issues/issue-70125-1.rs | 2 +- src/test/ui/const-generics/issues/issue-70125-1.stderr | 3 ++- src/test/ui/const-generics/issues/issue-70125-2.rs | 2 +- src/test/ui/const-generics/issues/issue-70125-2.stderr | 3 ++- src/test/ui/const-generics/issues/issue-70167.rs | 2 +- src/test/ui/const-generics/issues/issue-70167.stderr | 3 ++- src/test/ui/const-generics/issues/issue70273-assoc-fn.rs | 2 +- .../ui/const-generics/issues/issue70273-assoc-fn.stderr | 3 ++- src/test/ui/const-generics/mut-ref-const-param-array.rs | 2 +- .../ui/const-generics/mut-ref-const-param-array.stderr | 3 ++- src/test/ui/const-generics/raw-ptr-const-param-deref.rs | 2 +- .../ui/const-generics/raw-ptr-const-param-deref.stderr | 3 ++- src/test/ui/const-generics/raw-ptr-const-param.rs | 2 +- src/test/ui/const-generics/raw-ptr-const-param.stderr | 3 ++- src/test/ui/const-generics/slice-const-param-mismatch.rs | 2 +- .../ui/const-generics/slice-const-param-mismatch.stderr | 3 ++- src/test/ui/const-generics/slice-const-param.rs | 2 +- src/test/ui/const-generics/slice-const-param.stderr | 3 ++- .../ui/const-generics/struct-with-invalid-const-param.rs | 2 +- .../const-generics/struct-with-invalid-const-param.stderr | 3 ++- .../const-generics/transparent-maybeunit-array-wrapper.rs | 2 +- .../transparent-maybeunit-array-wrapper.stderr | 3 ++- src/test/ui/const-generics/type_of_anon_const.rs | 2 +- src/test/ui/const-generics/type_of_anon_const.stderr | 3 ++- src/test/ui/const-generics/types-mismatch-const-args.rs | 2 +- .../ui/const-generics/types-mismatch-const-args.stderr | 3 ++- .../const-generics/uninferred-consts-during-codegen-1.rs | 2 +- .../uninferred-consts-during-codegen-1.stderr | 3 ++- .../const-generics/uninferred-consts-during-codegen-2.rs | 2 +- .../uninferred-consts-during-codegen-2.stderr | 3 ++- src/test/ui/const-generics/unused-const-param.rs | 2 +- src/test/ui/const-generics/unused-const-param.stderr | 3 ++- src/test/ui/const-generics/unused_braces.rs | 2 +- src/test/ui/const-generics/unused_braces.stderr | 3 ++- src/test/ui/error-codes/E0730.rs | 2 +- src/test/ui/error-codes/E0730.stderr | 3 ++- .../generic-associated-types/gat-incomplete-warning.stderr | 3 ++- src/test/ui/hygiene/generic_params.stderr | 3 ++- src/test/ui/hygiene/issue-61574-const-parameters.stderr | 3 ++- src/test/ui/if-attrs/let-chains-attr.stderr | 3 ++- src/test/ui/impl-trait-in-bindings.rs | 2 +- src/test/ui/impl-trait-in-bindings.stderr | 3 ++- src/test/ui/impl-trait/bindings-opaque.rs | 2 +- src/test/ui/impl-trait/bindings-opaque.stderr | 3 ++- src/test/ui/impl-trait/bindings.rs | 2 +- src/test/ui/impl-trait/bindings.stderr | 3 ++- src/test/ui/impl-trait/bound-normalization-fail.stderr | 3 ++- src/test/ui/impl-trait/bound-normalization-pass.stderr | 3 ++- .../cannot-infer-async-enabled-impl-trait-bindings.rs | 2 +- .../cannot-infer-async-enabled-impl-trait-bindings.stderr | 3 ++- src/test/ui/issues/issue-59508-1.rs | 2 +- src/test/ui/issues/issue-59508-1.stderr | 3 ++- .../ui/parser/impl-item-type-no-body-semantic-fail.stderr | 3 ++- .../ui/resolve/issue-65035-static-with-parent-generics.rs | 2 +- .../resolve/issue-65035-static-with-parent-generics.stderr | 3 ++- .../ui/rfc-2497-if-let-chains/disallowed-positions.stderr | 7 +++++-- src/test/ui/rfc-2627-raw-dylib/link-ordinal-and-name.rs | 2 +- .../ui/rfc-2627-raw-dylib/link-ordinal-and-name.stderr | 3 ++- .../ui/rfc-2627-raw-dylib/link-ordinal-invalid-format.rs | 2 +- .../rfc-2627-raw-dylib/link-ordinal-invalid-format.stderr | 3 ++- src/test/ui/rfc-2627-raw-dylib/link-ordinal-too-large.rs | 2 +- .../ui/rfc-2627-raw-dylib/link-ordinal-too-large.stderr | 3 ++- src/test/ui/type-alias-impl-trait/assoc-type-const.rs | 2 +- src/test/ui/type-alias-impl-trait/assoc-type-const.stderr | 3 ++- .../type-alias-impl-trait/type-alias-impl-trait-const.rs | 2 +- .../type-alias-impl-trait-const.stderr | 3 ++- 175 files changed, 270 insertions(+), 176 deletions(-) diff --git a/src/test/incremental/const-generics/issue-62536.rs b/src/test/incremental/const-generics/issue-62536.rs index 90e279bfc743..0eaeb910be64 100644 --- a/src/test/incremental/const-generics/issue-62536.rs +++ b/src/test/incremental/const-generics/issue-62536.rs @@ -1,6 +1,6 @@ // revisions:cfail1 #![feature(const_generics)] -//[cfail1]~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash +//[cfail1]~^ WARN the feature `const_generics` is incomplete struct S([T; N]); diff --git a/src/test/incremental/const-generics/issue-64087.rs b/src/test/incremental/const-generics/issue-64087.rs index b3c12fbb6e81..6b10c5404944 100644 --- a/src/test/incremental/const-generics/issue-64087.rs +++ b/src/test/incremental/const-generics/issue-64087.rs @@ -1,6 +1,6 @@ // revisions:cfail1 #![feature(const_generics)] -//[cfail1]~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash +//[cfail1]~^ WARN the feature `const_generics` is incomplete fn combinator() -> [T; S] {} //[cfail1]~^ ERROR mismatched types diff --git a/src/test/ui/array-slice-vec/match_arr_unknown_len.rs b/src/test/ui/array-slice-vec/match_arr_unknown_len.rs index 7f3da75ddcbe..45b2889f1ca4 100644 --- a/src/test/ui/array-slice-vec/match_arr_unknown_len.rs +++ b/src/test/ui/array-slice-vec/match_arr_unknown_len.rs @@ -1,5 +1,5 @@ #![feature(const_generics)] -//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash +//~^ WARN the feature `const_generics` is incomplete fn is_123(x: [u32; N]) -> bool { match x { diff --git a/src/test/ui/array-slice-vec/match_arr_unknown_len.stderr b/src/test/ui/array-slice-vec/match_arr_unknown_len.stderr index 09f65f6acd06..c94d7d245a3d 100644 --- a/src/test/ui/array-slice-vec/match_arr_unknown_len.stderr +++ b/src/test/ui/array-slice-vec/match_arr_unknown_len.stderr @@ -1,10 +1,11 @@ -warning: the feature `const_generics` is incomplete and may cause the compiler to crash +warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes --> $DIR/match_arr_unknown_len.rs:1:12 | LL | #![feature(const_generics)] | ^^^^^^^^^^^^^^ | = note: `#[warn(incomplete_features)]` on by default + = note: see issue #44580 for more information error[E0308]: mismatched types --> $DIR/match_arr_unknown_len.rs:6:9 diff --git a/src/test/ui/associated-type-bounds/duplicate.rs b/src/test/ui/associated-type-bounds/duplicate.rs index f8d230da3652..8b396f23efd5 100644 --- a/src/test/ui/associated-type-bounds/duplicate.rs +++ b/src/test/ui/associated-type-bounds/duplicate.rs @@ -2,7 +2,7 @@ #![feature(associated_type_bounds)] #![feature(type_alias_impl_trait)] -#![feature(impl_trait_in_bindings)] //~ WARN the feature `impl_trait_in_bindings` is incomplete and may cause the compiler to crash [incomplete_features] +#![feature(impl_trait_in_bindings)] //~ WARN the feature `impl_trait_in_bindings` is incomplete #![feature(untagged_unions)] use std::iter; diff --git a/src/test/ui/associated-type-bounds/duplicate.stderr b/src/test/ui/associated-type-bounds/duplicate.stderr index 9f219fb7c53d..71f6e4ff8b62 100644 --- a/src/test/ui/associated-type-bounds/duplicate.stderr +++ b/src/test/ui/associated-type-bounds/duplicate.stderr @@ -1,10 +1,11 @@ -warning: the feature `impl_trait_in_bindings` is incomplete and may cause the compiler to crash +warning: the feature `impl_trait_in_bindings` is incomplete and may not be safe to use and/or cause compiler crashes --> $DIR/duplicate.rs:5:12 | LL | #![feature(impl_trait_in_bindings)] | ^^^^^^^^^^^^^^^^^^^^^^ | = note: `#[warn(incomplete_features)]` on by default + = note: see issue #63065 for more information error[E0719]: the value of the associated type `Item` (from trait `std::iter::Iterator`) is already specified --> $DIR/duplicate.rs:10:36 diff --git a/src/test/ui/associated-type-bounds/dyn-lcsit.stderr b/src/test/ui/associated-type-bounds/dyn-lcsit.stderr index 7414c148452a..3637f9558be7 100644 --- a/src/test/ui/associated-type-bounds/dyn-lcsit.stderr +++ b/src/test/ui/associated-type-bounds/dyn-lcsit.stderr @@ -1,10 +1,11 @@ -warning: the feature `impl_trait_in_bindings` is incomplete and may cause the compiler to crash +warning: the feature `impl_trait_in_bindings` is incomplete and may not be safe to use and/or cause compiler crashes --> $DIR/dyn-lcsit.rs:4:12 | LL | #![feature(impl_trait_in_bindings)] | ^^^^^^^^^^^^^^^^^^^^^^ | = note: `#[warn(incomplete_features)]` on by default + = note: see issue #63065 for more information warning: 1 warning emitted diff --git a/src/test/ui/associated-type-bounds/lcsit.stderr b/src/test/ui/associated-type-bounds/lcsit.stderr index 8c225a306384..11ff03db3614 100644 --- a/src/test/ui/associated-type-bounds/lcsit.stderr +++ b/src/test/ui/associated-type-bounds/lcsit.stderr @@ -1,10 +1,11 @@ -warning: the feature `impl_trait_in_bindings` is incomplete and may cause the compiler to crash +warning: the feature `impl_trait_in_bindings` is incomplete and may not be safe to use and/or cause compiler crashes --> $DIR/lcsit.rs:4:12 | LL | #![feature(impl_trait_in_bindings)] | ^^^^^^^^^^^^^^^^^^^^^^ | = note: `#[warn(incomplete_features)]` on by default + = note: see issue #63065 for more information warning: 1 warning emitted diff --git a/src/test/ui/binding/const-param.stderr b/src/test/ui/binding/const-param.stderr index f6a80c3c7d38..316fac623254 100644 --- a/src/test/ui/binding/const-param.stderr +++ b/src/test/ui/binding/const-param.stderr @@ -1,10 +1,11 @@ -warning: the feature `const_generics` is incomplete and may cause the compiler to crash +warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes --> $DIR/const-param.rs:3:12 | LL | #![feature(const_generics)] | ^^^^^^^^^^^^^^ | = note: `#[warn(incomplete_features)]` on by default + = note: see issue #44580 for more information error[E0158]: const parameters cannot be referenced in patterns --> $DIR/const-param.rs:7:9 diff --git a/src/test/ui/const-generics/apit-with-const-param.rs b/src/test/ui/const-generics/apit-with-const-param.rs index 7acc50819a6a..f9c6e201b176 100644 --- a/src/test/ui/const-generics/apit-with-const-param.rs +++ b/src/test/ui/const-generics/apit-with-const-param.rs @@ -1,7 +1,7 @@ // check-pass #![feature(const_generics)] -//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash +//~^ WARN the feature `const_generics` is incomplete trait Trait {} diff --git a/src/test/ui/const-generics/apit-with-const-param.stderr b/src/test/ui/const-generics/apit-with-const-param.stderr index b6b83b78d3be..4389e4738ead 100644 --- a/src/test/ui/const-generics/apit-with-const-param.stderr +++ b/src/test/ui/const-generics/apit-with-const-param.stderr @@ -1,10 +1,11 @@ -warning: the feature `const_generics` is incomplete and may cause the compiler to crash +warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes --> $DIR/apit-with-const-param.rs:3:12 | LL | #![feature(const_generics)] | ^^^^^^^^^^^^^^ | = note: `#[warn(incomplete_features)]` on by default + = note: see issue #44580 for more information warning: 1 warning emitted diff --git a/src/test/ui/const-generics/argument_order.rs b/src/test/ui/const-generics/argument_order.rs index 3446600d0495..6110d16c070d 100644 --- a/src/test/ui/const-generics/argument_order.rs +++ b/src/test/ui/const-generics/argument_order.rs @@ -1,5 +1,5 @@ #![feature(const_generics)] -//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash +//~^ WARN the feature `const_generics` is incomplete struct Bad { //~ ERROR type parameters must be declared prior arr: [u8; { N }], diff --git a/src/test/ui/const-generics/argument_order.stderr b/src/test/ui/const-generics/argument_order.stderr index 7c55cb59a225..f77ae49cf10b 100644 --- a/src/test/ui/const-generics/argument_order.stderr +++ b/src/test/ui/const-generics/argument_order.stderr @@ -4,13 +4,14 @@ error: type parameters must be declared prior to const parameters LL | struct Bad { | -----------------^- help: reorder the parameters: lifetimes, then types, then consts: `` -warning: the feature `const_generics` is incomplete and may cause the compiler to crash +warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes --> $DIR/argument_order.rs:1:12 | LL | #![feature(const_generics)] | ^^^^^^^^^^^^^^ | = note: `#[warn(incomplete_features)]` on by default + = note: see issue #44580 for more information error: aborting due to previous error; 1 warning emitted diff --git a/src/test/ui/const-generics/array-size-in-generic-struct-param.rs b/src/test/ui/const-generics/array-size-in-generic-struct-param.rs index d996bf56fcc1..5c02e585dc8b 100644 --- a/src/test/ui/const-generics/array-size-in-generic-struct-param.rs +++ b/src/test/ui/const-generics/array-size-in-generic-struct-param.rs @@ -1,5 +1,5 @@ #![feature(const_generics)] -//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash +//~^ WARN the feature `const_generics` is incomplete #[allow(dead_code)] struct ArithArrayLen([u32; 0 + N]); diff --git a/src/test/ui/const-generics/array-size-in-generic-struct-param.stderr b/src/test/ui/const-generics/array-size-in-generic-struct-param.stderr index 05f30a1cc5ed..14cf64eeb7ac 100644 --- a/src/test/ui/const-generics/array-size-in-generic-struct-param.stderr +++ b/src/test/ui/const-generics/array-size-in-generic-struct-param.stderr @@ -1,10 +1,11 @@ -warning: the feature `const_generics` is incomplete and may cause the compiler to crash +warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes --> $DIR/array-size-in-generic-struct-param.rs:1:12 | LL | #![feature(const_generics)] | ^^^^^^^^^^^^^^ | = note: `#[warn(incomplete_features)]` on by default + = note: see issue #44580 for more information error: constant expression depends on a generic parameter --> $DIR/array-size-in-generic-struct-param.rs:5:38 diff --git a/src/test/ui/const-generics/array-wrapper-struct-ctor.rs b/src/test/ui/const-generics/array-wrapper-struct-ctor.rs index 2d1a405ebdd8..49fc53b32bd9 100644 --- a/src/test/ui/const-generics/array-wrapper-struct-ctor.rs +++ b/src/test/ui/const-generics/array-wrapper-struct-ctor.rs @@ -1,7 +1,7 @@ // run-pass #![feature(const_generics)] -//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash +//~^ WARN the feature `const_generics` is incomplete #![allow(dead_code)] diff --git a/src/test/ui/const-generics/array-wrapper-struct-ctor.stderr b/src/test/ui/const-generics/array-wrapper-struct-ctor.stderr index e28f65a38275..e6eb2a0a7830 100644 --- a/src/test/ui/const-generics/array-wrapper-struct-ctor.stderr +++ b/src/test/ui/const-generics/array-wrapper-struct-ctor.stderr @@ -1,10 +1,11 @@ -warning: the feature `const_generics` is incomplete and may cause the compiler to crash +warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes --> $DIR/array-wrapper-struct-ctor.rs:3:12 | LL | #![feature(const_generics)] | ^^^^^^^^^^^^^^ | = note: `#[warn(incomplete_features)]` on by default + = note: see issue #44580 for more information warning: 1 warning emitted diff --git a/src/test/ui/const-generics/broken-mir-1.rs b/src/test/ui/const-generics/broken-mir-1.rs index 9a11bd3d0313..f137be2d6a6f 100644 --- a/src/test/ui/const-generics/broken-mir-1.rs +++ b/src/test/ui/const-generics/broken-mir-1.rs @@ -1,7 +1,7 @@ // run-pass #![feature(const_generics)] -//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash +//~^ WARN the feature `const_generics` is incomplete pub trait Foo { fn foo(&self); diff --git a/src/test/ui/const-generics/broken-mir-1.stderr b/src/test/ui/const-generics/broken-mir-1.stderr index 8b8e0fd1120a..a5532bde1f5e 100644 --- a/src/test/ui/const-generics/broken-mir-1.stderr +++ b/src/test/ui/const-generics/broken-mir-1.stderr @@ -1,10 +1,11 @@ -warning: the feature `const_generics` is incomplete and may cause the compiler to crash +warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes --> $DIR/broken-mir-1.rs:3:12 | LL | #![feature(const_generics)] | ^^^^^^^^^^^^^^ | = note: `#[warn(incomplete_features)]` on by default + = note: see issue #44580 for more information warning: 1 warning emitted diff --git a/src/test/ui/const-generics/broken-mir-2.rs b/src/test/ui/const-generics/broken-mir-2.rs index d9a4411b4f98..c2f9b786f8f8 100644 --- a/src/test/ui/const-generics/broken-mir-2.rs +++ b/src/test/ui/const-generics/broken-mir-2.rs @@ -1,5 +1,5 @@ #![feature(const_generics)] -//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash +//~^ WARN the feature `const_generics` is incomplete use std::fmt::Debug; diff --git a/src/test/ui/const-generics/broken-mir-2.stderr b/src/test/ui/const-generics/broken-mir-2.stderr index cbb8159e9b5d..e0bf039575be 100644 --- a/src/test/ui/const-generics/broken-mir-2.stderr +++ b/src/test/ui/const-generics/broken-mir-2.stderr @@ -1,10 +1,11 @@ -warning: the feature `const_generics` is incomplete and may cause the compiler to crash +warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes --> $DIR/broken-mir-2.rs:1:12 | LL | #![feature(const_generics)] | ^^^^^^^^^^^^^^ | = note: `#[warn(incomplete_features)]` on by default + = note: see issue #44580 for more information error[E0277]: arrays only have std trait implementations for lengths 0..=32 --> $DIR/broken-mir-2.rs:7:36 diff --git a/src/test/ui/const-generics/cannot-infer-const-args.rs b/src/test/ui/const-generics/cannot-infer-const-args.rs index e1061c6d1a33..2f6ad2654c12 100644 --- a/src/test/ui/const-generics/cannot-infer-const-args.rs +++ b/src/test/ui/const-generics/cannot-infer-const-args.rs @@ -1,5 +1,5 @@ #![feature(const_generics)] -//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash +//~^ WARN the feature `const_generics` is incomplete fn foo() -> usize { 0 diff --git a/src/test/ui/const-generics/cannot-infer-const-args.stderr b/src/test/ui/const-generics/cannot-infer-const-args.stderr index fc426bf4f488..6696b025855a 100644 --- a/src/test/ui/const-generics/cannot-infer-const-args.stderr +++ b/src/test/ui/const-generics/cannot-infer-const-args.stderr @@ -1,10 +1,11 @@ -warning: the feature `const_generics` is incomplete and may cause the compiler to crash +warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes --> $DIR/cannot-infer-const-args.rs:1:12 | LL | #![feature(const_generics)] | ^^^^^^^^^^^^^^ | = note: `#[warn(incomplete_features)]` on by default + = note: see issue #44580 for more information error[E0282]: type annotations needed --> $DIR/cannot-infer-const-args.rs:9:5 diff --git a/src/test/ui/const-generics/cannot-infer-type-for-const-param.rs b/src/test/ui/const-generics/cannot-infer-type-for-const-param.rs index 303bc8326fdb..aac5d195f76a 100644 --- a/src/test/ui/const-generics/cannot-infer-type-for-const-param.rs +++ b/src/test/ui/const-generics/cannot-infer-type-for-const-param.rs @@ -1,6 +1,6 @@ // check-pass #![feature(const_generics)] -//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash +//~^ WARN the feature `const_generics` is incomplete // This test confirms that the types can be inferred correctly for this example with const // generics. Previously this would ICE, and more recently error. diff --git a/src/test/ui/const-generics/cannot-infer-type-for-const-param.stderr b/src/test/ui/const-generics/cannot-infer-type-for-const-param.stderr index f273c4e93350..c5c48d7be468 100644 --- a/src/test/ui/const-generics/cannot-infer-type-for-const-param.stderr +++ b/src/test/ui/const-generics/cannot-infer-type-for-const-param.stderr @@ -1,10 +1,11 @@ -warning: the feature `const_generics` is incomplete and may cause the compiler to crash +warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes --> $DIR/cannot-infer-type-for-const-param.rs:2:12 | LL | #![feature(const_generics)] | ^^^^^^^^^^^^^^ | = note: `#[warn(incomplete_features)]` on by default + = note: see issue #44580 for more information warning: 1 warning emitted diff --git a/src/test/ui/const-generics/concrete-const-as-fn-arg.rs b/src/test/ui/const-generics/concrete-const-as-fn-arg.rs index 54981b77a2b8..18ebba49f6f9 100644 --- a/src/test/ui/const-generics/concrete-const-as-fn-arg.rs +++ b/src/test/ui/const-generics/concrete-const-as-fn-arg.rs @@ -2,7 +2,7 @@ // run-pass #![feature(const_generics)] -//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash +//~^ WARN the feature `const_generics` is incomplete struct A; // ok diff --git a/src/test/ui/const-generics/concrete-const-as-fn-arg.stderr b/src/test/ui/const-generics/concrete-const-as-fn-arg.stderr index e83ccf9adb72..c8f3a8beaf83 100644 --- a/src/test/ui/const-generics/concrete-const-as-fn-arg.stderr +++ b/src/test/ui/const-generics/concrete-const-as-fn-arg.stderr @@ -1,10 +1,11 @@ -warning: the feature `const_generics` is incomplete and may cause the compiler to crash +warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes --> $DIR/concrete-const-as-fn-arg.rs:4:12 | LL | #![feature(const_generics)] | ^^^^^^^^^^^^^^ | = note: `#[warn(incomplete_features)]` on by default + = note: see issue #44580 for more information warning: 1 warning emitted diff --git a/src/test/ui/const-generics/concrete-const-impl-method.rs b/src/test/ui/const-generics/concrete-const-impl-method.rs index 226ea4151806..c1ddf9a33140 100644 --- a/src/test/ui/const-generics/concrete-const-impl-method.rs +++ b/src/test/ui/const-generics/concrete-const-impl-method.rs @@ -3,7 +3,7 @@ // run-pass #![feature(const_generics)] -//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash +//~^ WARN the feature `const_generics` is incomplete pub struct A; diff --git a/src/test/ui/const-generics/concrete-const-impl-method.stderr b/src/test/ui/const-generics/concrete-const-impl-method.stderr index c9145837ea44..5edb4f4f6cda 100644 --- a/src/test/ui/const-generics/concrete-const-impl-method.stderr +++ b/src/test/ui/const-generics/concrete-const-impl-method.stderr @@ -1,10 +1,11 @@ -warning: the feature `const_generics` is incomplete and may cause the compiler to crash +warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes --> $DIR/concrete-const-impl-method.rs:5:12 | LL | #![feature(const_generics)] | ^^^^^^^^^^^^^^ | = note: `#[warn(incomplete_features)]` on by default + = note: see issue #44580 for more information warning: 1 warning emitted diff --git a/src/test/ui/const-generics/condition-in-trait-const-arg.rs b/src/test/ui/const-generics/condition-in-trait-const-arg.rs index 091fe904826d..9d8aaed54bd7 100644 --- a/src/test/ui/const-generics/condition-in-trait-const-arg.rs +++ b/src/test/ui/const-generics/condition-in-trait-const-arg.rs @@ -1,7 +1,7 @@ // run-pass #![feature(const_generics)] -//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash +//~^ WARN the feature `const_generics` is incomplete trait IsZeroTrait{} diff --git a/src/test/ui/const-generics/condition-in-trait-const-arg.stderr b/src/test/ui/const-generics/condition-in-trait-const-arg.stderr index 12a51d05f46e..9ac33454128b 100644 --- a/src/test/ui/const-generics/condition-in-trait-const-arg.stderr +++ b/src/test/ui/const-generics/condition-in-trait-const-arg.stderr @@ -1,10 +1,11 @@ -warning: the feature `const_generics` is incomplete and may cause the compiler to crash +warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes --> $DIR/condition-in-trait-const-arg.rs:3:12 | LL | #![feature(const_generics)] | ^^^^^^^^^^^^^^ | = note: `#[warn(incomplete_features)]` on by default + = note: see issue #44580 for more information warning: 1 warning emitted diff --git a/src/test/ui/const-generics/const-arg-in-fn.rs b/src/test/ui/const-generics/const-arg-in-fn.rs index 3f86782838ca..5ea2cf92fdc6 100644 --- a/src/test/ui/const-generics/const-arg-in-fn.rs +++ b/src/test/ui/const-generics/const-arg-in-fn.rs @@ -1,7 +1,7 @@ // run-pass #![feature(const_generics)] -//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash +//~^ WARN the feature `const_generics` is incomplete fn const_u32_identity() -> u32 { X diff --git a/src/test/ui/const-generics/const-arg-in-fn.stderr b/src/test/ui/const-generics/const-arg-in-fn.stderr index 74919ba0ae77..bb66849c7fe6 100644 --- a/src/test/ui/const-generics/const-arg-in-fn.stderr +++ b/src/test/ui/const-generics/const-arg-in-fn.stderr @@ -1,10 +1,11 @@ -warning: the feature `const_generics` is incomplete and may cause the compiler to crash +warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes --> $DIR/const-arg-in-fn.rs:3:12 | LL | #![feature(const_generics)] | ^^^^^^^^^^^^^^ | = note: `#[warn(incomplete_features)]` on by default + = note: see issue #44580 for more information warning: 1 warning emitted diff --git a/src/test/ui/const-generics/const-arg-type-arg-misordered.rs b/src/test/ui/const-generics/const-arg-type-arg-misordered.rs index f024eb6a957e..9f989ee20a56 100644 --- a/src/test/ui/const-generics/const-arg-type-arg-misordered.rs +++ b/src/test/ui/const-generics/const-arg-type-arg-misordered.rs @@ -1,5 +1,5 @@ #![feature(const_generics)] -//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash +//~^ WARN the feature `const_generics` is incomplete type Array = [T; N]; diff --git a/src/test/ui/const-generics/const-arg-type-arg-misordered.stderr b/src/test/ui/const-generics/const-arg-type-arg-misordered.stderr index 5795a492c225..ad38b632b75f 100644 --- a/src/test/ui/const-generics/const-arg-type-arg-misordered.stderr +++ b/src/test/ui/const-generics/const-arg-type-arg-misordered.stderr @@ -1,10 +1,11 @@ -warning: the feature `const_generics` is incomplete and may cause the compiler to crash +warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes --> $DIR/const-arg-type-arg-misordered.rs:1:12 | LL | #![feature(const_generics)] | ^^^^^^^^^^^^^^ | = note: `#[warn(incomplete_features)]` on by default + = note: see issue #44580 for more information error[E0747]: constant provided when a type was expected --> $DIR/const-arg-type-arg-misordered.rs:6:35 diff --git a/src/test/ui/const-generics/const-expression-parameter.rs b/src/test/ui/const-generics/const-expression-parameter.rs index 22c6c3516228..e0b66a7c14c3 100644 --- a/src/test/ui/const-generics/const-expression-parameter.rs +++ b/src/test/ui/const-generics/const-expression-parameter.rs @@ -1,5 +1,5 @@ #![feature(const_generics)] -//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash +//~^ WARN the feature `const_generics` is incomplete fn i32_identity() -> i32 { 5 diff --git a/src/test/ui/const-generics/const-expression-parameter.stderr b/src/test/ui/const-generics/const-expression-parameter.stderr index 6784aeebf0fe..e421c22be01a 100644 --- a/src/test/ui/const-generics/const-expression-parameter.stderr +++ b/src/test/ui/const-generics/const-expression-parameter.stderr @@ -4,13 +4,14 @@ error: expected one of `,` or `>`, found `+` LL | i32_identity::<1 + 2>(); | ^ expected one of `,` or `>` -warning: the feature `const_generics` is incomplete and may cause the compiler to crash +warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes --> $DIR/const-expression-parameter.rs:1:12 | LL | #![feature(const_generics)] | ^^^^^^^^^^^^^^ | = note: `#[warn(incomplete_features)]` on by default + = note: see issue #44580 for more information error: aborting due to previous error; 1 warning emitted diff --git a/src/test/ui/const-generics/const-fn-with-const-param.rs b/src/test/ui/const-generics/const-fn-with-const-param.rs index 3d8b77bcf7b4..bbc55815e9a2 100644 --- a/src/test/ui/const-generics/const-fn-with-const-param.rs +++ b/src/test/ui/const-generics/const-fn-with-const-param.rs @@ -1,6 +1,6 @@ // run-pass #![feature(const_generics)] -//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash +//~^ WARN the feature `const_generics` is incomplete const fn const_u32_identity() -> u32 { X diff --git a/src/test/ui/const-generics/const-fn-with-const-param.stderr b/src/test/ui/const-generics/const-fn-with-const-param.stderr index 64b9c18a8f52..109b50028480 100644 --- a/src/test/ui/const-generics/const-fn-with-const-param.stderr +++ b/src/test/ui/const-generics/const-fn-with-const-param.stderr @@ -1,10 +1,11 @@ -warning: the feature `const_generics` is incomplete and may cause the compiler to crash +warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes --> $DIR/const-fn-with-const-param.rs:2:12 | LL | #![feature(const_generics)] | ^^^^^^^^^^^^^^ | = note: `#[warn(incomplete_features)]` on by default + = note: see issue #44580 for more information warning: 1 warning emitted diff --git a/src/test/ui/const-generics/const-generic-array-wrapper.rs b/src/test/ui/const-generics/const-generic-array-wrapper.rs index 56a58c582f64..3e43387163b6 100644 --- a/src/test/ui/const-generics/const-generic-array-wrapper.rs +++ b/src/test/ui/const-generics/const-generic-array-wrapper.rs @@ -1,7 +1,7 @@ // run-pass #![feature(const_generics)] -//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash +//~^ WARN the feature `const_generics` is incomplete struct Foo([T; N]); diff --git a/src/test/ui/const-generics/const-generic-array-wrapper.stderr b/src/test/ui/const-generics/const-generic-array-wrapper.stderr index 1d05381b59b2..47448bbd19d6 100644 --- a/src/test/ui/const-generics/const-generic-array-wrapper.stderr +++ b/src/test/ui/const-generics/const-generic-array-wrapper.stderr @@ -1,10 +1,11 @@ -warning: the feature `const_generics` is incomplete and may cause the compiler to crash +warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes --> $DIR/const-generic-array-wrapper.rs:3:12 | LL | #![feature(const_generics)] | ^^^^^^^^^^^^^^ | = note: `#[warn(incomplete_features)]` on by default + = note: see issue #44580 for more information warning: 1 warning emitted diff --git a/src/test/ui/const-generics/const-generic-type_name.rs b/src/test/ui/const-generics/const-generic-type_name.rs index 469843d6aae1..22f9bd2a0f0b 100644 --- a/src/test/ui/const-generics/const-generic-type_name.rs +++ b/src/test/ui/const-generics/const-generic-type_name.rs @@ -1,7 +1,7 @@ // run-pass #![feature(const_generics)] -//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash +//~^ WARN the feature `const_generics` is incomplete #[derive(Debug)] struct S; diff --git a/src/test/ui/const-generics/const-generic-type_name.stderr b/src/test/ui/const-generics/const-generic-type_name.stderr index 641b868dcb2e..f161739c9c8a 100644 --- a/src/test/ui/const-generics/const-generic-type_name.stderr +++ b/src/test/ui/const-generics/const-generic-type_name.stderr @@ -1,10 +1,11 @@ -warning: the feature `const_generics` is incomplete and may cause the compiler to crash +warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes --> $DIR/const-generic-type_name.rs:3:12 | LL | #![feature(const_generics)] | ^^^^^^^^^^^^^^ | = note: `#[warn(incomplete_features)]` on by default + = note: see issue #44580 for more information warning: 1 warning emitted diff --git a/src/test/ui/const-generics/const-param-elided-lifetime.rs b/src/test/ui/const-generics/const-param-elided-lifetime.rs index 5679dd35c307..5e6b6c4dabe0 100644 --- a/src/test/ui/const-generics/const-param-elided-lifetime.rs +++ b/src/test/ui/const-generics/const-param-elided-lifetime.rs @@ -4,7 +4,7 @@ // lifetimes within const/static items. #![feature(const_generics)] -//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash +//~^ WARN the feature `const_generics` is incomplete struct A; //~^ ERROR `&` without an explicit lifetime name cannot be used here diff --git a/src/test/ui/const-generics/const-param-elided-lifetime.stderr b/src/test/ui/const-generics/const-param-elided-lifetime.stderr index edc26d6348c7..8c50fb73679a 100644 --- a/src/test/ui/const-generics/const-param-elided-lifetime.stderr +++ b/src/test/ui/const-generics/const-param-elided-lifetime.stderr @@ -28,13 +28,14 @@ error[E0637]: `&` without an explicit lifetime name cannot be used here LL | fn bar() {} | ^ explicit lifetime name needed here -warning: the feature `const_generics` is incomplete and may cause the compiler to crash +warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes --> $DIR/const-param-elided-lifetime.rs:6:12 | LL | #![feature(const_generics)] | ^^^^^^^^^^^^^^ | = note: `#[warn(incomplete_features)]` on by default + = note: see issue #44580 for more information error: aborting due to 5 previous errors; 1 warning emitted diff --git a/src/test/ui/const-generics/const-param-from-outer-fn.rs b/src/test/ui/const-generics/const-param-from-outer-fn.rs index 6534bcf5ce64..4b8e2db7233e 100644 --- a/src/test/ui/const-generics/const-param-from-outer-fn.rs +++ b/src/test/ui/const-generics/const-param-from-outer-fn.rs @@ -1,5 +1,5 @@ #![feature(const_generics)] -//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash +//~^ WARN the feature `const_generics` is incomplete fn foo() { fn bar() -> u32 { diff --git a/src/test/ui/const-generics/const-param-from-outer-fn.stderr b/src/test/ui/const-generics/const-param-from-outer-fn.stderr index a03ba0809007..30bd1d729145 100644 --- a/src/test/ui/const-generics/const-param-from-outer-fn.stderr +++ b/src/test/ui/const-generics/const-param-from-outer-fn.stderr @@ -8,13 +8,14 @@ LL | fn bar() -> u32 { LL | X | ^ use of generic parameter from outer function -warning: the feature `const_generics` is incomplete and may cause the compiler to crash +warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes --> $DIR/const-param-from-outer-fn.rs:1:12 | LL | #![feature(const_generics)] | ^^^^^^^^^^^^^^ | = note: `#[warn(incomplete_features)]` on by default + = note: see issue #44580 for more information error: aborting due to previous error; 1 warning emitted diff --git a/src/test/ui/const-generics/const-param-in-trait.rs b/src/test/ui/const-generics/const-param-in-trait.rs index 6e4f65fe6cac..687407257110 100644 --- a/src/test/ui/const-generics/const-param-in-trait.rs +++ b/src/test/ui/const-generics/const-param-in-trait.rs @@ -1,7 +1,7 @@ // run-pass #![feature(const_generics)] -//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash +//~^ WARN the feature `const_generics` is incomplete trait Trait {} diff --git a/src/test/ui/const-generics/const-param-in-trait.stderr b/src/test/ui/const-generics/const-param-in-trait.stderr index 6afbce67e334..a2e367b25ade 100644 --- a/src/test/ui/const-generics/const-param-in-trait.stderr +++ b/src/test/ui/const-generics/const-param-in-trait.stderr @@ -1,10 +1,11 @@ -warning: the feature `const_generics` is incomplete and may cause the compiler to crash +warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes --> $DIR/const-param-in-trait.rs:3:12 | LL | #![feature(const_generics)] | ^^^^^^^^^^^^^^ | = note: `#[warn(incomplete_features)]` on by default + = note: see issue #44580 for more information warning: 1 warning emitted diff --git a/src/test/ui/const-generics/const-param-type-depends-on-type-param.rs b/src/test/ui/const-generics/const-param-type-depends-on-type-param.rs index 7468020366ce..654e36df37e9 100644 --- a/src/test/ui/const-generics/const-param-type-depends-on-type-param.rs +++ b/src/test/ui/const-generics/const-param-type-depends-on-type-param.rs @@ -1,5 +1,5 @@ #![feature(const_generics)] -//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash +//~^ WARN the feature `const_generics` is incomplete // Currently, const parameters cannot depend on type parameters, because there is no way to // enforce the structural-match property on an arbitrary type parameter. This restriction diff --git a/src/test/ui/const-generics/const-param-type-depends-on-type-param.stderr b/src/test/ui/const-generics/const-param-type-depends-on-type-param.stderr index 9f20b06813e3..ed05264161e5 100644 --- a/src/test/ui/const-generics/const-param-type-depends-on-type-param.stderr +++ b/src/test/ui/const-generics/const-param-type-depends-on-type-param.stderr @@ -1,10 +1,11 @@ -warning: the feature `const_generics` is incomplete and may cause the compiler to crash +warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes --> $DIR/const-param-type-depends-on-type-param.rs:1:12 | LL | #![feature(const_generics)] | ^^^^^^^^^^^^^^ | = note: `#[warn(incomplete_features)]` on by default + = note: see issue #44580 for more information error[E0741]: `T` is not guaranteed to `#[derive(PartialEq, Eq)]`, so may not be used as the type of a const parameter --> $DIR/const-param-type-depends-on-type-param.rs:9:34 diff --git a/src/test/ui/const-generics/const-parameter-uppercase-lint.rs b/src/test/ui/const-generics/const-parameter-uppercase-lint.rs index 164205dd75cb..54a33e218128 100644 --- a/src/test/ui/const-generics/const-parameter-uppercase-lint.rs +++ b/src/test/ui/const-generics/const-parameter-uppercase-lint.rs @@ -1,5 +1,5 @@ #![feature(const_generics)] -//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash +//~^ WARN the feature `const_generics` is incomplete #![deny(non_upper_case_globals)] diff --git a/src/test/ui/const-generics/const-parameter-uppercase-lint.stderr b/src/test/ui/const-generics/const-parameter-uppercase-lint.stderr index 826dc702c0dc..b7febed7bdd2 100644 --- a/src/test/ui/const-generics/const-parameter-uppercase-lint.stderr +++ b/src/test/ui/const-generics/const-parameter-uppercase-lint.stderr @@ -1,10 +1,11 @@ -warning: the feature `const_generics` is incomplete and may cause the compiler to crash +warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes --> $DIR/const-parameter-uppercase-lint.rs:1:12 | LL | #![feature(const_generics)] | ^^^^^^^^^^^^^^ | = note: `#[warn(incomplete_features)]` on by default + = note: see issue #44580 for more information error: const parameter `x` should have an upper case name --> $DIR/const-parameter-uppercase-lint.rs:6:15 diff --git a/src/test/ui/const-generics/const-types.rs b/src/test/ui/const-generics/const-types.rs index bc5188133d7f..bde80f4a1ed0 100644 --- a/src/test/ui/const-generics/const-types.rs +++ b/src/test/ui/const-generics/const-types.rs @@ -1,7 +1,7 @@ // run-pass #![feature(const_generics)] -//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash +//~^ WARN the feature `const_generics` is incomplete #![allow(dead_code, unused_variables)] diff --git a/src/test/ui/const-generics/const-types.stderr b/src/test/ui/const-generics/const-types.stderr index 935baf1a63a2..4628c9003188 100644 --- a/src/test/ui/const-generics/const-types.stderr +++ b/src/test/ui/const-generics/const-types.stderr @@ -1,10 +1,11 @@ -warning: the feature `const_generics` is incomplete and may cause the compiler to crash +warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes --> $DIR/const-types.rs:3:12 | LL | #![feature(const_generics)] | ^^^^^^^^^^^^^^ | = note: `#[warn(incomplete_features)]` on by default + = note: see issue #44580 for more information warning: 1 warning emitted diff --git a/src/test/ui/const-generics/derive-debug-array-wrapper.rs b/src/test/ui/const-generics/derive-debug-array-wrapper.rs index eee634c15644..c6d8b32f276f 100644 --- a/src/test/ui/const-generics/derive-debug-array-wrapper.rs +++ b/src/test/ui/const-generics/derive-debug-array-wrapper.rs @@ -1,5 +1,5 @@ #![feature(const_generics)] -//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash +//~^ WARN the feature `const_generics` is incomplete #[derive(Debug)] struct X { diff --git a/src/test/ui/const-generics/derive-debug-array-wrapper.stderr b/src/test/ui/const-generics/derive-debug-array-wrapper.stderr index 672586fd3fe0..8fbe6d3e9a42 100644 --- a/src/test/ui/const-generics/derive-debug-array-wrapper.stderr +++ b/src/test/ui/const-generics/derive-debug-array-wrapper.stderr @@ -1,10 +1,11 @@ -warning: the feature `const_generics` is incomplete and may cause the compiler to crash +warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes --> $DIR/derive-debug-array-wrapper.rs:1:12 | LL | #![feature(const_generics)] | ^^^^^^^^^^^^^^ | = note: `#[warn(incomplete_features)]` on by default + = note: see issue #44580 for more information error[E0277]: arrays only have std trait implementations for lengths 0..=32 --> $DIR/derive-debug-array-wrapper.rs:6:5 diff --git a/src/test/ui/const-generics/different_byref.rs b/src/test/ui/const-generics/different_byref.rs index c52a5b8061db..78964eb3dee6 100644 --- a/src/test/ui/const-generics/different_byref.rs +++ b/src/test/ui/const-generics/different_byref.rs @@ -1,5 +1,5 @@ #![feature(const_generics)] -//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash +//~^ WARN the feature `const_generics` is incomplete struct Const {} diff --git a/src/test/ui/const-generics/different_byref.stderr b/src/test/ui/const-generics/different_byref.stderr index 9ea2aace89aa..001d9852a69f 100644 --- a/src/test/ui/const-generics/different_byref.stderr +++ b/src/test/ui/const-generics/different_byref.stderr @@ -1,10 +1,11 @@ -warning: the feature `const_generics` is incomplete and may cause the compiler to crash +warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes --> $DIR/different_byref.rs:1:12 | LL | #![feature(const_generics)] | ^^^^^^^^^^^^^^ | = note: `#[warn(incomplete_features)]` on by default + = note: see issue #44580 for more information error[E0308]: mismatched types --> $DIR/different_byref.rs:8:9 diff --git a/src/test/ui/const-generics/fn-const-param-call.rs b/src/test/ui/const-generics/fn-const-param-call.rs index cd4b19db3533..afa577fa67ff 100644 --- a/src/test/ui/const-generics/fn-const-param-call.rs +++ b/src/test/ui/const-generics/fn-const-param-call.rs @@ -1,7 +1,7 @@ // run-pass #![feature(const_generics, const_compare_raw_pointers)] -//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash +//~^ WARN the feature `const_generics` is incomplete fn function() -> u32 { 17 diff --git a/src/test/ui/const-generics/fn-const-param-call.stderr b/src/test/ui/const-generics/fn-const-param-call.stderr index 872ec11ad1bf..9c0f7e3ab9b8 100644 --- a/src/test/ui/const-generics/fn-const-param-call.stderr +++ b/src/test/ui/const-generics/fn-const-param-call.stderr @@ -1,10 +1,11 @@ -warning: the feature `const_generics` is incomplete and may cause the compiler to crash +warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes --> $DIR/fn-const-param-call.rs:3:12 | LL | #![feature(const_generics, const_compare_raw_pointers)] | ^^^^^^^^^^^^^^ | = note: `#[warn(incomplete_features)]` on by default + = note: see issue #44580 for more information warning: 1 warning emitted diff --git a/src/test/ui/const-generics/fn-const-param-infer.rs b/src/test/ui/const-generics/fn-const-param-infer.rs index dc69fa9eea58..08f6e0db31ca 100644 --- a/src/test/ui/const-generics/fn-const-param-infer.rs +++ b/src/test/ui/const-generics/fn-const-param-infer.rs @@ -1,5 +1,5 @@ #![feature(const_generics, const_compare_raw_pointers)] -//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash +//~^ WARN the feature `const_generics` is incomplete struct Checked bool>; diff --git a/src/test/ui/const-generics/fn-const-param-infer.stderr b/src/test/ui/const-generics/fn-const-param-infer.stderr index 7bfb0873a102..3e07393b9aa8 100644 --- a/src/test/ui/const-generics/fn-const-param-infer.stderr +++ b/src/test/ui/const-generics/fn-const-param-infer.stderr @@ -1,10 +1,11 @@ -warning: the feature `const_generics` is incomplete and may cause the compiler to crash +warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes --> $DIR/fn-const-param-infer.rs:1:12 | LL | #![feature(const_generics, const_compare_raw_pointers)] | ^^^^^^^^^^^^^^ | = note: `#[warn(incomplete_features)]` on by default + = note: see issue #44580 for more information error[E0308]: mismatched types --> $DIR/fn-const-param-infer.rs:16:31 diff --git a/src/test/ui/const-generics/fn-taking-const-generic-array.rs b/src/test/ui/const-generics/fn-taking-const-generic-array.rs index d3d17cca4da2..8e16221ed4bd 100644 --- a/src/test/ui/const-generics/fn-taking-const-generic-array.rs +++ b/src/test/ui/const-generics/fn-taking-const-generic-array.rs @@ -1,7 +1,7 @@ // run-pass #![feature(const_generics)] -//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash +//~^ WARN the feature `const_generics` is incomplete use std::fmt::Display; diff --git a/src/test/ui/const-generics/fn-taking-const-generic-array.stderr b/src/test/ui/const-generics/fn-taking-const-generic-array.stderr index 5a2ef780e142..52fd0a8fec03 100644 --- a/src/test/ui/const-generics/fn-taking-const-generic-array.stderr +++ b/src/test/ui/const-generics/fn-taking-const-generic-array.stderr @@ -1,10 +1,11 @@ -warning: the feature `const_generics` is incomplete and may cause the compiler to crash +warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes --> $DIR/fn-taking-const-generic-array.rs:3:12 | LL | #![feature(const_generics)] | ^^^^^^^^^^^^^^ | = note: `#[warn(incomplete_features)]` on by default + = note: see issue #44580 for more information warning: 1 warning emitted diff --git a/src/test/ui/const-generics/forbid-non-structural_match-types.rs b/src/test/ui/const-generics/forbid-non-structural_match-types.rs index a30cdc3efdf4..514e215ba1aa 100644 --- a/src/test/ui/const-generics/forbid-non-structural_match-types.rs +++ b/src/test/ui/const-generics/forbid-non-structural_match-types.rs @@ -1,5 +1,5 @@ #![feature(const_generics)] -//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash +//~^ WARN the feature `const_generics` is incomplete #[derive(PartialEq, Eq)] struct A; diff --git a/src/test/ui/const-generics/forbid-non-structural_match-types.stderr b/src/test/ui/const-generics/forbid-non-structural_match-types.stderr index 4f343146263b..600be64b1e1b 100644 --- a/src/test/ui/const-generics/forbid-non-structural_match-types.stderr +++ b/src/test/ui/const-generics/forbid-non-structural_match-types.stderr @@ -1,10 +1,11 @@ -warning: the feature `const_generics` is incomplete and may cause the compiler to crash +warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes --> $DIR/forbid-non-structural_match-types.rs:1:12 | LL | #![feature(const_generics)] | ^^^^^^^^^^^^^^ | = note: `#[warn(incomplete_features)]` on by default + = note: see issue #44580 for more information error[E0741]: `C` must be annotated with `#[derive(PartialEq, Eq)]` to be used as the type of a const parameter --> $DIR/forbid-non-structural_match-types.rs:11:19 diff --git a/src/test/ui/const-generics/foreign-item-const-parameter.rs b/src/test/ui/const-generics/foreign-item-const-parameter.rs index 4673c8606c39..41113780de32 100644 --- a/src/test/ui/const-generics/foreign-item-const-parameter.rs +++ b/src/test/ui/const-generics/foreign-item-const-parameter.rs @@ -1,5 +1,5 @@ #![feature(const_generics)] -//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash +//~^ WARN the feature `const_generics` is incomplete extern "C" { fn foo(); //~ ERROR foreign items may not have const parameters diff --git a/src/test/ui/const-generics/foreign-item-const-parameter.stderr b/src/test/ui/const-generics/foreign-item-const-parameter.stderr index b8fd9854ff60..ee947943af13 100644 --- a/src/test/ui/const-generics/foreign-item-const-parameter.stderr +++ b/src/test/ui/const-generics/foreign-item-const-parameter.stderr @@ -1,10 +1,11 @@ -warning: the feature `const_generics` is incomplete and may cause the compiler to crash +warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes --> $DIR/foreign-item-const-parameter.rs:1:12 | LL | #![feature(const_generics)] | ^^^^^^^^^^^^^^ | = note: `#[warn(incomplete_features)]` on by default + = note: see issue #44580 for more information error[E0044]: foreign items may not have const parameters --> $DIR/foreign-item-const-parameter.rs:5:5 diff --git a/src/test/ui/const-generics/impl-const-generic-struct.rs b/src/test/ui/const-generics/impl-const-generic-struct.rs index 87572e51e814..4c2aee59ffeb 100644 --- a/src/test/ui/const-generics/impl-const-generic-struct.rs +++ b/src/test/ui/const-generics/impl-const-generic-struct.rs @@ -1,7 +1,7 @@ // run-pass #![feature(const_generics)] -//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash +//~^ WARN the feature `const_generics` is incomplete struct S; diff --git a/src/test/ui/const-generics/impl-const-generic-struct.stderr b/src/test/ui/const-generics/impl-const-generic-struct.stderr index 64dbc210d92f..9d68df07ce67 100644 --- a/src/test/ui/const-generics/impl-const-generic-struct.stderr +++ b/src/test/ui/const-generics/impl-const-generic-struct.stderr @@ -1,10 +1,11 @@ -warning: the feature `const_generics` is incomplete and may cause the compiler to crash +warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes --> $DIR/impl-const-generic-struct.rs:3:12 | LL | #![feature(const_generics)] | ^^^^^^^^^^^^^^ | = note: `#[warn(incomplete_features)]` on by default + = note: see issue #44580 for more information warning: 1 warning emitted diff --git a/src/test/ui/const-generics/incorrect-number-of-const-args.rs b/src/test/ui/const-generics/incorrect-number-of-const-args.rs index 7059e9d8348e..cea64654e11a 100644 --- a/src/test/ui/const-generics/incorrect-number-of-const-args.rs +++ b/src/test/ui/const-generics/incorrect-number-of-const-args.rs @@ -1,5 +1,5 @@ #![feature(const_generics)] -//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash +//~^ WARN the feature `const_generics` is incomplete fn foo() -> usize { 0 diff --git a/src/test/ui/const-generics/incorrect-number-of-const-args.stderr b/src/test/ui/const-generics/incorrect-number-of-const-args.stderr index a2492e27e208..51064d7f90fb 100644 --- a/src/test/ui/const-generics/incorrect-number-of-const-args.stderr +++ b/src/test/ui/const-generics/incorrect-number-of-const-args.stderr @@ -1,10 +1,11 @@ -warning: the feature `const_generics` is incomplete and may cause the compiler to crash +warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes --> $DIR/incorrect-number-of-const-args.rs:1:12 | LL | #![feature(const_generics)] | ^^^^^^^^^^^^^^ | = note: `#[warn(incomplete_features)]` on by default + = note: see issue #44580 for more information error[E0107]: wrong number of const arguments: expected 2, found 1 --> $DIR/incorrect-number-of-const-args.rs:9:5 diff --git a/src/test/ui/const-generics/infer_arg_from_pat.rs b/src/test/ui/const-generics/infer_arg_from_pat.rs index a4e3d3dee4a8..7e8152dacc46 100644 --- a/src/test/ui/const-generics/infer_arg_from_pat.rs +++ b/src/test/ui/const-generics/infer_arg_from_pat.rs @@ -2,7 +2,7 @@ // // see issue #70529 #![feature(const_generics)] -//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash +//~^ WARN the feature `const_generics` is incomplete struct A { arr: [u8; N], diff --git a/src/test/ui/const-generics/infer_arg_from_pat.stderr b/src/test/ui/const-generics/infer_arg_from_pat.stderr index 7a6da2582a82..f52e5e49a3bd 100644 --- a/src/test/ui/const-generics/infer_arg_from_pat.stderr +++ b/src/test/ui/const-generics/infer_arg_from_pat.stderr @@ -1,10 +1,11 @@ -warning: the feature `const_generics` is incomplete and may cause the compiler to crash +warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes --> $DIR/infer_arg_from_pat.rs:4:12 | LL | #![feature(const_generics)] | ^^^^^^^^^^^^^^ | = note: `#[warn(incomplete_features)]` on by default + = note: see issue #44580 for more information warning: 1 warning emitted diff --git a/src/test/ui/const-generics/infer_arr_len_from_pat.rs b/src/test/ui/const-generics/infer_arr_len_from_pat.rs index 70633bbb141d..cede9ea045d4 100644 --- a/src/test/ui/const-generics/infer_arr_len_from_pat.rs +++ b/src/test/ui/const-generics/infer_arr_len_from_pat.rs @@ -2,7 +2,7 @@ // // see issue #70529 #![feature(const_generics)] -//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash +//~^ WARN the feature `const_generics` is incomplete fn as_chunks() -> [u8; N] { loop {} diff --git a/src/test/ui/const-generics/infer_arr_len_from_pat.stderr b/src/test/ui/const-generics/infer_arr_len_from_pat.stderr index d698abd2bae6..dfadfbb16637 100644 --- a/src/test/ui/const-generics/infer_arr_len_from_pat.stderr +++ b/src/test/ui/const-generics/infer_arr_len_from_pat.stderr @@ -1,10 +1,11 @@ -warning: the feature `const_generics` is incomplete and may cause the compiler to crash +warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes --> $DIR/infer_arr_len_from_pat.rs:4:12 | LL | #![feature(const_generics)] | ^^^^^^^^^^^^^^ | = note: `#[warn(incomplete_features)]` on by default + = note: see issue #44580 for more information warning: 1 warning emitted diff --git a/src/test/ui/const-generics/integer-literal-generic-arg-in-where-clause.rs b/src/test/ui/const-generics/integer-literal-generic-arg-in-where-clause.rs index 30fbfda112c5..952e05bac30f 100644 --- a/src/test/ui/const-generics/integer-literal-generic-arg-in-where-clause.rs +++ b/src/test/ui/const-generics/integer-literal-generic-arg-in-where-clause.rs @@ -1,7 +1,7 @@ // check-pass #![feature(const_generics)] -//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash +//~^ WARN the feature `const_generics` is incomplete fn takes_closure_of_array_3(f: F) where F: Fn([i32; 3]) { f([1, 2, 3]); diff --git a/src/test/ui/const-generics/integer-literal-generic-arg-in-where-clause.stderr b/src/test/ui/const-generics/integer-literal-generic-arg-in-where-clause.stderr index 0924f8da25f6..aadd10e5ccab 100644 --- a/src/test/ui/const-generics/integer-literal-generic-arg-in-where-clause.stderr +++ b/src/test/ui/const-generics/integer-literal-generic-arg-in-where-clause.stderr @@ -1,10 +1,11 @@ -warning: the feature `const_generics` is incomplete and may cause the compiler to crash +warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes --> $DIR/integer-literal-generic-arg-in-where-clause.rs:3:12 | LL | #![feature(const_generics)] | ^^^^^^^^^^^^^^ | = note: `#[warn(incomplete_features)]` on by default + = note: see issue #44580 for more information warning: 1 warning emitted diff --git a/src/test/ui/const-generics/issue-61522-array-len-succ.rs b/src/test/ui/const-generics/issue-61522-array-len-succ.rs index 3b627a5e5301..7c8cdeece871 100644 --- a/src/test/ui/const-generics/issue-61522-array-len-succ.rs +++ b/src/test/ui/const-generics/issue-61522-array-len-succ.rs @@ -1,5 +1,5 @@ #![feature(const_generics)] -//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash +//~^ WARN the feature `const_generics` is incomplete pub struct MyArray([u8; COUNT + 1]); //~^ ERROR constant expression depends on a generic parameter diff --git a/src/test/ui/const-generics/issue-61522-array-len-succ.stderr b/src/test/ui/const-generics/issue-61522-array-len-succ.stderr index d52ae10ee07b..a1fbd5f2025b 100644 --- a/src/test/ui/const-generics/issue-61522-array-len-succ.stderr +++ b/src/test/ui/const-generics/issue-61522-array-len-succ.stderr @@ -1,10 +1,11 @@ -warning: the feature `const_generics` is incomplete and may cause the compiler to crash +warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes --> $DIR/issue-61522-array-len-succ.rs:1:12 | LL | #![feature(const_generics)] | ^^^^^^^^^^^^^^ | = note: `#[warn(incomplete_features)]` on by default + = note: see issue #44580 for more information error: constant expression depends on a generic parameter --> $DIR/issue-61522-array-len-succ.rs:4:40 diff --git a/src/test/ui/const-generics/issue-66596-impl-trait-for-str-const-arg.rs b/src/test/ui/const-generics/issue-66596-impl-trait-for-str-const-arg.rs index b677dcc4af4b..74f036e6d89b 100644 --- a/src/test/ui/const-generics/issue-66596-impl-trait-for-str-const-arg.rs +++ b/src/test/ui/const-generics/issue-66596-impl-trait-for-str-const-arg.rs @@ -1,7 +1,7 @@ // check-pass #![feature(const_generics)] -//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash +//~^ WARN the feature `const_generics` is incomplete trait Trait { type Assoc; diff --git a/src/test/ui/const-generics/issue-66596-impl-trait-for-str-const-arg.stderr b/src/test/ui/const-generics/issue-66596-impl-trait-for-str-const-arg.stderr index edaa59bbdc71..720420d9cd68 100644 --- a/src/test/ui/const-generics/issue-66596-impl-trait-for-str-const-arg.stderr +++ b/src/test/ui/const-generics/issue-66596-impl-trait-for-str-const-arg.stderr @@ -1,10 +1,11 @@ -warning: the feature `const_generics` is incomplete and may cause the compiler to crash +warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes --> $DIR/issue-66596-impl-trait-for-str-const-arg.rs:3:12 | LL | #![feature(const_generics)] | ^^^^^^^^^^^^^^ | = note: `#[warn(incomplete_features)]` on by default + = note: see issue #44580 for more information warning: 1 warning emitted diff --git a/src/test/ui/const-generics/issues/issue-60818-struct-constructors.rs b/src/test/ui/const-generics/issues/issue-60818-struct-constructors.rs index fb234eb08275..26d74ffb254c 100644 --- a/src/test/ui/const-generics/issues/issue-60818-struct-constructors.rs +++ b/src/test/ui/const-generics/issues/issue-60818-struct-constructors.rs @@ -1,7 +1,7 @@ // check-pass #![feature(const_generics)] -//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash +//~^ WARN the feature `const_generics` is incomplete struct Generic; diff --git a/src/test/ui/const-generics/issues/issue-60818-struct-constructors.stderr b/src/test/ui/const-generics/issues/issue-60818-struct-constructors.stderr index 887d4547933b..94a2b673a51e 100644 --- a/src/test/ui/const-generics/issues/issue-60818-struct-constructors.stderr +++ b/src/test/ui/const-generics/issues/issue-60818-struct-constructors.stderr @@ -1,10 +1,11 @@ -warning: the feature `const_generics` is incomplete and may cause the compiler to crash +warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes --> $DIR/issue-60818-struct-constructors.rs:3:12 | LL | #![feature(const_generics)] | ^^^^^^^^^^^^^^ | = note: `#[warn(incomplete_features)]` on by default + = note: see issue #44580 for more information warning: 1 warning emitted diff --git a/src/test/ui/const-generics/issues/issue-61336-1.rs b/src/test/ui/const-generics/issues/issue-61336-1.rs index 165d3e1c2e60..2135c868bbc7 100644 --- a/src/test/ui/const-generics/issues/issue-61336-1.rs +++ b/src/test/ui/const-generics/issues/issue-61336-1.rs @@ -1,5 +1,5 @@ #![feature(const_generics)] -//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash +//~^ WARN the feature `const_generics` is incomplete // build-pass diff --git a/src/test/ui/const-generics/issues/issue-61336-1.stderr b/src/test/ui/const-generics/issues/issue-61336-1.stderr index 34920d8907fc..b2c69d57c40b 100644 --- a/src/test/ui/const-generics/issues/issue-61336-1.stderr +++ b/src/test/ui/const-generics/issues/issue-61336-1.stderr @@ -1,10 +1,11 @@ -warning: the feature `const_generics` is incomplete and may cause the compiler to crash +warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes --> $DIR/issue-61336-1.rs:1:12 | LL | #![feature(const_generics)] | ^^^^^^^^^^^^^^ | = note: `#[warn(incomplete_features)]` on by default + = note: see issue #44580 for more information warning: 1 warning emitted diff --git a/src/test/ui/const-generics/issues/issue-61336-2.rs b/src/test/ui/const-generics/issues/issue-61336-2.rs index c5bf6b6ce94a..52969056f00a 100644 --- a/src/test/ui/const-generics/issues/issue-61336-2.rs +++ b/src/test/ui/const-generics/issues/issue-61336-2.rs @@ -1,5 +1,5 @@ #![feature(const_generics)] -//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash +//~^ WARN the feature `const_generics` is incomplete fn f(x: T) -> [T; N] { [x; { N }] diff --git a/src/test/ui/const-generics/issues/issue-61336-2.stderr b/src/test/ui/const-generics/issues/issue-61336-2.stderr index 27ee4f88870b..5f3395223f95 100644 --- a/src/test/ui/const-generics/issues/issue-61336-2.stderr +++ b/src/test/ui/const-generics/issues/issue-61336-2.stderr @@ -1,10 +1,11 @@ -warning: the feature `const_generics` is incomplete and may cause the compiler to crash +warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes --> $DIR/issue-61336-2.rs:1:12 | LL | #![feature(const_generics)] | ^^^^^^^^^^^^^^ | = note: `#[warn(incomplete_features)]` on by default + = note: see issue #44580 for more information error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied --> $DIR/issue-61336-2.rs:9:5 diff --git a/src/test/ui/const-generics/issues/issue-61336.rs b/src/test/ui/const-generics/issues/issue-61336.rs index 7e84e62d8be4..eb0f30976276 100644 --- a/src/test/ui/const-generics/issues/issue-61336.rs +++ b/src/test/ui/const-generics/issues/issue-61336.rs @@ -1,5 +1,5 @@ #![feature(const_generics)] -//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash +//~^ WARN the feature `const_generics` is incomplete fn f(x: T) -> [T; N] { [x; N] diff --git a/src/test/ui/const-generics/issues/issue-61336.stderr b/src/test/ui/const-generics/issues/issue-61336.stderr index 772a07cccf88..0eee37df3dd5 100644 --- a/src/test/ui/const-generics/issues/issue-61336.stderr +++ b/src/test/ui/const-generics/issues/issue-61336.stderr @@ -1,10 +1,11 @@ -warning: the feature `const_generics` is incomplete and may cause the compiler to crash +warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes --> $DIR/issue-61336.rs:1:12 | LL | #![feature(const_generics)] | ^^^^^^^^^^^^^^ | = note: `#[warn(incomplete_features)]` on by default + = note: see issue #44580 for more information error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied --> $DIR/issue-61336.rs:9:5 diff --git a/src/test/ui/const-generics/issues/issue-61422.rs b/src/test/ui/const-generics/issues/issue-61422.rs index 4fa150ffef09..7e7ef6867ed0 100644 --- a/src/test/ui/const-generics/issues/issue-61422.rs +++ b/src/test/ui/const-generics/issues/issue-61422.rs @@ -1,7 +1,7 @@ // check-pass #![feature(const_generics)] -//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash +//~^ WARN the feature `const_generics` is incomplete use std::mem; diff --git a/src/test/ui/const-generics/issues/issue-61422.stderr b/src/test/ui/const-generics/issues/issue-61422.stderr index a66224b6d170..69bbaada6918 100644 --- a/src/test/ui/const-generics/issues/issue-61422.stderr +++ b/src/test/ui/const-generics/issues/issue-61422.stderr @@ -1,10 +1,11 @@ -warning: the feature `const_generics` is incomplete and may cause the compiler to crash +warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes --> $DIR/issue-61422.rs:3:12 | LL | #![feature(const_generics)] | ^^^^^^^^^^^^^^ | = note: `#[warn(incomplete_features)]` on by default + = note: see issue #44580 for more information warning: 1 warning emitted diff --git a/src/test/ui/const-generics/issues/issue-61432.rs b/src/test/ui/const-generics/issues/issue-61432.rs index 832095ce5420..0440468e9e62 100644 --- a/src/test/ui/const-generics/issues/issue-61432.rs +++ b/src/test/ui/const-generics/issues/issue-61432.rs @@ -1,7 +1,7 @@ // run-pass #![feature(const_generics)] -//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash +//~^ WARN the feature `const_generics` is incomplete fn promote() { // works: diff --git a/src/test/ui/const-generics/issues/issue-61432.stderr b/src/test/ui/const-generics/issues/issue-61432.stderr index cb2fa99f6d88..1d547b1b6c98 100644 --- a/src/test/ui/const-generics/issues/issue-61432.stderr +++ b/src/test/ui/const-generics/issues/issue-61432.stderr @@ -1,10 +1,11 @@ -warning: the feature `const_generics` is incomplete and may cause the compiler to crash +warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes --> $DIR/issue-61432.rs:3:12 | LL | #![feature(const_generics)] | ^^^^^^^^^^^^^^ | = note: `#[warn(incomplete_features)]` on by default + = note: see issue #44580 for more information warning: 1 warning emitted diff --git a/src/test/ui/const-generics/issues/issue-61747.rs b/src/test/ui/const-generics/issues/issue-61747.rs index 64674bb894e1..9e0572d3568c 100644 --- a/src/test/ui/const-generics/issues/issue-61747.rs +++ b/src/test/ui/const-generics/issues/issue-61747.rs @@ -1,7 +1,7 @@ // check-pass #![feature(const_generics)] -//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash +//~^ WARN the feature `const_generics` is incomplete struct Const; diff --git a/src/test/ui/const-generics/issues/issue-61747.stderr b/src/test/ui/const-generics/issues/issue-61747.stderr index 3465db152084..2e405370dc0d 100644 --- a/src/test/ui/const-generics/issues/issue-61747.stderr +++ b/src/test/ui/const-generics/issues/issue-61747.stderr @@ -1,10 +1,11 @@ -warning: the feature `const_generics` is incomplete and may cause the compiler to crash +warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes --> $DIR/issue-61747.rs:3:12 | LL | #![feature(const_generics)] | ^^^^^^^^^^^^^^ | = note: `#[warn(incomplete_features)]` on by default + = note: see issue #44580 for more information warning: 1 warning emitted diff --git a/src/test/ui/const-generics/issues/issue-62187-encountered-polymorphic-const.rs b/src/test/ui/const-generics/issues/issue-62187-encountered-polymorphic-const.rs index 4e5e4d045c8f..2f3b5c5dc5b8 100644 --- a/src/test/ui/const-generics/issues/issue-62187-encountered-polymorphic-const.rs +++ b/src/test/ui/const-generics/issues/issue-62187-encountered-polymorphic-const.rs @@ -1,7 +1,7 @@ // run-pass #![feature(const_generics)] -//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash +//~^ WARN the feature `const_generics` is incomplete pub trait BitLen: Sized { const BIT_LEN: usize; diff --git a/src/test/ui/const-generics/issues/issue-62187-encountered-polymorphic-const.stderr b/src/test/ui/const-generics/issues/issue-62187-encountered-polymorphic-const.stderr index 70d0b61cc26e..a9abb877c094 100644 --- a/src/test/ui/const-generics/issues/issue-62187-encountered-polymorphic-const.stderr +++ b/src/test/ui/const-generics/issues/issue-62187-encountered-polymorphic-const.stderr @@ -1,10 +1,11 @@ -warning: the feature `const_generics` is incomplete and may cause the compiler to crash +warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes --> $DIR/issue-62187-encountered-polymorphic-const.rs:3:12 | LL | #![feature(const_generics)] | ^^^^^^^^^^^^^^ | = note: `#[warn(incomplete_features)]` on by default + = note: see issue #44580 for more information warning: unused variable: `foo` --> $DIR/issue-62187-encountered-polymorphic-const.rs:15:9 diff --git a/src/test/ui/const-generics/issues/issue-62456.rs b/src/test/ui/const-generics/issues/issue-62456.rs index 5d068eb7fc83..37947ad1b331 100644 --- a/src/test/ui/const-generics/issues/issue-62456.rs +++ b/src/test/ui/const-generics/issues/issue-62456.rs @@ -1,5 +1,5 @@ #![feature(const_generics)] -//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash +//~^ WARN the feature `const_generics` is incomplete fn foo() { let _ = [0u64; N + 1]; diff --git a/src/test/ui/const-generics/issues/issue-62456.stderr b/src/test/ui/const-generics/issues/issue-62456.stderr index 96a07110e73c..0454fed67059 100644 --- a/src/test/ui/const-generics/issues/issue-62456.stderr +++ b/src/test/ui/const-generics/issues/issue-62456.stderr @@ -1,10 +1,11 @@ -warning: the feature `const_generics` is incomplete and may cause the compiler to crash +warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes --> $DIR/issue-62456.rs:1:12 | LL | #![feature(const_generics)] | ^^^^^^^^^^^^^^ | = note: `#[warn(incomplete_features)]` on by default + = note: see issue #44580 for more information error: constant expression depends on a generic parameter --> $DIR/issue-62456.rs:5:20 diff --git a/src/test/ui/const-generics/issues/issue-62579-no-match.rs b/src/test/ui/const-generics/issues/issue-62579-no-match.rs index 0ff7ddc41fe4..7eaf5eea0787 100644 --- a/src/test/ui/const-generics/issues/issue-62579-no-match.rs +++ b/src/test/ui/const-generics/issues/issue-62579-no-match.rs @@ -1,7 +1,7 @@ // run-pass #![feature(const_generics)] -//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash +//~^ WARN the feature `const_generics` is incomplete #[derive(PartialEq, Eq)] struct NoMatch; diff --git a/src/test/ui/const-generics/issues/issue-62579-no-match.stderr b/src/test/ui/const-generics/issues/issue-62579-no-match.stderr index 31f8d230935a..9fb9b5b13d8d 100644 --- a/src/test/ui/const-generics/issues/issue-62579-no-match.stderr +++ b/src/test/ui/const-generics/issues/issue-62579-no-match.stderr @@ -1,10 +1,11 @@ -warning: the feature `const_generics` is incomplete and may cause the compiler to crash +warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes --> $DIR/issue-62579-no-match.rs:3:12 | LL | #![feature(const_generics)] | ^^^^^^^^^^^^^^ | = note: `#[warn(incomplete_features)]` on by default + = note: see issue #44580 for more information warning: 1 warning emitted diff --git a/src/test/ui/const-generics/issues/issue-63322-forbid-dyn.rs b/src/test/ui/const-generics/issues/issue-63322-forbid-dyn.rs index 2bacd6c9a9c5..2bcaa27b4d27 100644 --- a/src/test/ui/const-generics/issues/issue-63322-forbid-dyn.rs +++ b/src/test/ui/const-generics/issues/issue-63322-forbid-dyn.rs @@ -1,5 +1,5 @@ #![feature(const_generics)] -//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash +//~^ WARN the feature `const_generics` is incomplete trait A {} struct B; diff --git a/src/test/ui/const-generics/issues/issue-63322-forbid-dyn.stderr b/src/test/ui/const-generics/issues/issue-63322-forbid-dyn.stderr index c3db6c65a8f4..32054e43716c 100644 --- a/src/test/ui/const-generics/issues/issue-63322-forbid-dyn.stderr +++ b/src/test/ui/const-generics/issues/issue-63322-forbid-dyn.stderr @@ -1,10 +1,11 @@ -warning: the feature `const_generics` is incomplete and may cause the compiler to crash +warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes --> $DIR/issue-63322-forbid-dyn.rs:1:12 | LL | #![feature(const_generics)] | ^^^^^^^^^^^^^^ | = note: `#[warn(incomplete_features)]` on by default + = note: see issue #44580 for more information error[E0741]: `&'static (dyn A + 'static)` must be annotated with `#[derive(PartialEq, Eq)]` to be used as the type of a const parameter --> $DIR/issue-63322-forbid-dyn.rs:8:18 diff --git a/src/test/ui/const-generics/issues/issue-64519.rs b/src/test/ui/const-generics/issues/issue-64519.rs index 72cce9b4843d..e9391096b04d 100644 --- a/src/test/ui/const-generics/issues/issue-64519.rs +++ b/src/test/ui/const-generics/issues/issue-64519.rs @@ -1,7 +1,7 @@ // check-pass #![feature(const_generics)] -//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash +//~^ WARN the feature `const_generics` is incomplete struct Foo { state: Option<[u8; D]>, diff --git a/src/test/ui/const-generics/issues/issue-64519.stderr b/src/test/ui/const-generics/issues/issue-64519.stderr index 94c010ba2609..6552aea4ad1f 100644 --- a/src/test/ui/const-generics/issues/issue-64519.stderr +++ b/src/test/ui/const-generics/issues/issue-64519.stderr @@ -1,10 +1,11 @@ -warning: the feature `const_generics` is incomplete and may cause the compiler to crash +warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes --> $DIR/issue-64519.rs:3:12 | LL | #![feature(const_generics)] | ^^^^^^^^^^^^^^ | = note: `#[warn(incomplete_features)]` on by default + = note: see issue #44580 for more information warning: 1 warning emitted diff --git a/src/test/ui/const-generics/issues/issue-66906.rs b/src/test/ui/const-generics/issues/issue-66906.rs index 461fe837dac4..486c72d8a349 100644 --- a/src/test/ui/const-generics/issues/issue-66906.rs +++ b/src/test/ui/const-generics/issues/issue-66906.rs @@ -1,7 +1,7 @@ // check-pass #![feature(const_generics)] -//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash +//~^ WARN the feature `const_generics` is incomplete pub struct Tuple; diff --git a/src/test/ui/const-generics/issues/issue-66906.stderr b/src/test/ui/const-generics/issues/issue-66906.stderr index 6730c97604cf..8e8b552f90eb 100644 --- a/src/test/ui/const-generics/issues/issue-66906.stderr +++ b/src/test/ui/const-generics/issues/issue-66906.stderr @@ -1,10 +1,11 @@ -warning: the feature `const_generics` is incomplete and may cause the compiler to crash +warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes --> $DIR/issue-66906.rs:3:12 | LL | #![feature(const_generics)] | ^^^^^^^^^^^^^^ | = note: `#[warn(incomplete_features)]` on by default + = note: see issue #44580 for more information warning: 1 warning emitted diff --git a/src/test/ui/const-generics/issues/issue-70125-1.rs b/src/test/ui/const-generics/issues/issue-70125-1.rs index 8b933c078ff2..08a8309d4319 100644 --- a/src/test/ui/const-generics/issues/issue-70125-1.rs +++ b/src/test/ui/const-generics/issues/issue-70125-1.rs @@ -1,6 +1,6 @@ // run-pass #![feature(const_generics)] -//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash +//~^ WARN the feature `const_generics` is incomplete const L: usize = 4; diff --git a/src/test/ui/const-generics/issues/issue-70125-1.stderr b/src/test/ui/const-generics/issues/issue-70125-1.stderr index b095d577fb7c..8ad4b25ae5bc 100644 --- a/src/test/ui/const-generics/issues/issue-70125-1.stderr +++ b/src/test/ui/const-generics/issues/issue-70125-1.stderr @@ -1,10 +1,11 @@ -warning: the feature `const_generics` is incomplete and may cause the compiler to crash +warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes --> $DIR/issue-70125-1.rs:2:12 | LL | #![feature(const_generics)] | ^^^^^^^^^^^^^^ | = note: `#[warn(incomplete_features)]` on by default + = note: see issue #44580 for more information warning: 1 warning emitted diff --git a/src/test/ui/const-generics/issues/issue-70125-2.rs b/src/test/ui/const-generics/issues/issue-70125-2.rs index a3eca0dd7d96..fb7d4886a7c1 100644 --- a/src/test/ui/const-generics/issues/issue-70125-2.rs +++ b/src/test/ui/const-generics/issues/issue-70125-2.rs @@ -1,7 +1,7 @@ // run-pass #![feature(const_generics)] -//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash +//~^ WARN the feature `const_generics` is incomplete fn main() { <()>::foo(); diff --git a/src/test/ui/const-generics/issues/issue-70125-2.stderr b/src/test/ui/const-generics/issues/issue-70125-2.stderr index 6a30e5e783e3..c1f9634810e4 100644 --- a/src/test/ui/const-generics/issues/issue-70125-2.stderr +++ b/src/test/ui/const-generics/issues/issue-70125-2.stderr @@ -1,10 +1,11 @@ -warning: the feature `const_generics` is incomplete and may cause the compiler to crash +warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes --> $DIR/issue-70125-2.rs:3:12 | LL | #![feature(const_generics)] | ^^^^^^^^^^^^^^ | = note: `#[warn(incomplete_features)]` on by default + = note: see issue #44580 for more information warning: 1 warning emitted diff --git a/src/test/ui/const-generics/issues/issue-70167.rs b/src/test/ui/const-generics/issues/issue-70167.rs index 58fac8e05114..b53cec80071f 100644 --- a/src/test/ui/const-generics/issues/issue-70167.rs +++ b/src/test/ui/const-generics/issues/issue-70167.rs @@ -1,7 +1,7 @@ // check-pass #![feature(const_generics)] -//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash +//~^ WARN the feature `const_generics` is incomplete pub trait Trait: From<>::Item> { type Item; diff --git a/src/test/ui/const-generics/issues/issue-70167.stderr b/src/test/ui/const-generics/issues/issue-70167.stderr index 2b56ed977ee9..5d647e933c4c 100644 --- a/src/test/ui/const-generics/issues/issue-70167.stderr +++ b/src/test/ui/const-generics/issues/issue-70167.stderr @@ -1,10 +1,11 @@ -warning: the feature `const_generics` is incomplete and may cause the compiler to crash +warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes --> $DIR/issue-70167.rs:3:12 | LL | #![feature(const_generics)] | ^^^^^^^^^^^^^^ | = note: `#[warn(incomplete_features)]` on by default + = note: see issue #44580 for more information warning: 1 warning emitted diff --git a/src/test/ui/const-generics/issues/issue70273-assoc-fn.rs b/src/test/ui/const-generics/issues/issue70273-assoc-fn.rs index a192ddea9c6a..c22e61d0ce33 100644 --- a/src/test/ui/const-generics/issues/issue70273-assoc-fn.rs +++ b/src/test/ui/const-generics/issues/issue70273-assoc-fn.rs @@ -1,7 +1,7 @@ // check-pass #![feature(const_generics)] -//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash +//~^ WARN the feature `const_generics` is incomplete trait T { fn f(); diff --git a/src/test/ui/const-generics/issues/issue70273-assoc-fn.stderr b/src/test/ui/const-generics/issues/issue70273-assoc-fn.stderr index afd2a50242f9..931701b64b48 100644 --- a/src/test/ui/const-generics/issues/issue70273-assoc-fn.stderr +++ b/src/test/ui/const-generics/issues/issue70273-assoc-fn.stderr @@ -1,10 +1,11 @@ -warning: the feature `const_generics` is incomplete and may cause the compiler to crash +warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes --> $DIR/issue70273-assoc-fn.rs:3:12 | LL | #![feature(const_generics)] | ^^^^^^^^^^^^^^ | = note: `#[warn(incomplete_features)]` on by default + = note: see issue #44580 for more information warning: 1 warning emitted diff --git a/src/test/ui/const-generics/mut-ref-const-param-array.rs b/src/test/ui/const-generics/mut-ref-const-param-array.rs index f930fb879632..9ca1f4552f59 100644 --- a/src/test/ui/const-generics/mut-ref-const-param-array.rs +++ b/src/test/ui/const-generics/mut-ref-const-param-array.rs @@ -1,7 +1,7 @@ // run-pass #![feature(const_generics)] -//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash +//~^ WARN the feature `const_generics` is incomplete use std::ops::AddAssign; diff --git a/src/test/ui/const-generics/mut-ref-const-param-array.stderr b/src/test/ui/const-generics/mut-ref-const-param-array.stderr index 336364e5aeaf..acbc2df1d740 100644 --- a/src/test/ui/const-generics/mut-ref-const-param-array.stderr +++ b/src/test/ui/const-generics/mut-ref-const-param-array.stderr @@ -1,10 +1,11 @@ -warning: the feature `const_generics` is incomplete and may cause the compiler to crash +warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes --> $DIR/mut-ref-const-param-array.rs:3:12 | LL | #![feature(const_generics)] | ^^^^^^^^^^^^^^ | = note: `#[warn(incomplete_features)]` on by default + = note: see issue #44580 for more information warning: 1 warning emitted diff --git a/src/test/ui/const-generics/raw-ptr-const-param-deref.rs b/src/test/ui/const-generics/raw-ptr-const-param-deref.rs index 745dde3c2876..c498bfe2e978 100644 --- a/src/test/ui/const-generics/raw-ptr-const-param-deref.rs +++ b/src/test/ui/const-generics/raw-ptr-const-param-deref.rs @@ -1,6 +1,6 @@ // run-pass #![feature(const_generics, const_compare_raw_pointers)] -//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash +//~^ WARN the feature `const_generics` is incomplete const A: u32 = 3; diff --git a/src/test/ui/const-generics/raw-ptr-const-param-deref.stderr b/src/test/ui/const-generics/raw-ptr-const-param-deref.stderr index 736c9b497250..1ffc63ffdac0 100644 --- a/src/test/ui/const-generics/raw-ptr-const-param-deref.stderr +++ b/src/test/ui/const-generics/raw-ptr-const-param-deref.stderr @@ -1,10 +1,11 @@ -warning: the feature `const_generics` is incomplete and may cause the compiler to crash +warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes --> $DIR/raw-ptr-const-param-deref.rs:2:12 | LL | #![feature(const_generics, const_compare_raw_pointers)] | ^^^^^^^^^^^^^^ | = note: `#[warn(incomplete_features)]` on by default + = note: see issue #44580 for more information warning: 1 warning emitted diff --git a/src/test/ui/const-generics/raw-ptr-const-param.rs b/src/test/ui/const-generics/raw-ptr-const-param.rs index f0349f469626..d7d970e952b6 100644 --- a/src/test/ui/const-generics/raw-ptr-const-param.rs +++ b/src/test/ui/const-generics/raw-ptr-const-param.rs @@ -1,5 +1,5 @@ #![feature(const_generics, const_compare_raw_pointers)] -//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash +//~^ WARN the feature `const_generics` is incomplete struct Const; diff --git a/src/test/ui/const-generics/raw-ptr-const-param.stderr b/src/test/ui/const-generics/raw-ptr-const-param.stderr index a2496a6558de..6644c72236b8 100644 --- a/src/test/ui/const-generics/raw-ptr-const-param.stderr +++ b/src/test/ui/const-generics/raw-ptr-const-param.stderr @@ -1,10 +1,11 @@ -warning: the feature `const_generics` is incomplete and may cause the compiler to crash +warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes --> $DIR/raw-ptr-const-param.rs:1:12 | LL | #![feature(const_generics, const_compare_raw_pointers)] | ^^^^^^^^^^^^^^ | = note: `#[warn(incomplete_features)]` on by default + = note: see issue #44580 for more information error[E0308]: mismatched types --> $DIR/raw-ptr-const-param.rs:7:40 diff --git a/src/test/ui/const-generics/slice-const-param-mismatch.rs b/src/test/ui/const-generics/slice-const-param-mismatch.rs index 73c75ae66680..4f321b02b827 100644 --- a/src/test/ui/const-generics/slice-const-param-mismatch.rs +++ b/src/test/ui/const-generics/slice-const-param-mismatch.rs @@ -1,5 +1,5 @@ #![feature(const_generics)] -//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash +//~^ WARN the feature `const_generics` is incomplete struct ConstString; struct ConstBytes; diff --git a/src/test/ui/const-generics/slice-const-param-mismatch.stderr b/src/test/ui/const-generics/slice-const-param-mismatch.stderr index e497cc3220d5..cc21f197e08b 100644 --- a/src/test/ui/const-generics/slice-const-param-mismatch.stderr +++ b/src/test/ui/const-generics/slice-const-param-mismatch.stderr @@ -1,10 +1,11 @@ -warning: the feature `const_generics` is incomplete and may cause the compiler to crash +warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes --> $DIR/slice-const-param-mismatch.rs:1:12 | LL | #![feature(const_generics)] | ^^^^^^^^^^^^^^ | = note: `#[warn(incomplete_features)]` on by default + = note: see issue #44580 for more information error[E0308]: mismatched types --> $DIR/slice-const-param-mismatch.rs:9:35 diff --git a/src/test/ui/const-generics/slice-const-param.rs b/src/test/ui/const-generics/slice-const-param.rs index 2629caa39210..9668f7ddabb3 100644 --- a/src/test/ui/const-generics/slice-const-param.rs +++ b/src/test/ui/const-generics/slice-const-param.rs @@ -1,7 +1,7 @@ // run-pass #![feature(const_generics)] -//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash +//~^ WARN the feature `const_generics` is incomplete pub fn function_with_str() -> &'static str { STRING diff --git a/src/test/ui/const-generics/slice-const-param.stderr b/src/test/ui/const-generics/slice-const-param.stderr index 80fdf3296bc8..524bd41a669b 100644 --- a/src/test/ui/const-generics/slice-const-param.stderr +++ b/src/test/ui/const-generics/slice-const-param.stderr @@ -1,10 +1,11 @@ -warning: the feature `const_generics` is incomplete and may cause the compiler to crash +warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes --> $DIR/slice-const-param.rs:3:12 | LL | #![feature(const_generics)] | ^^^^^^^^^^^^^^ | = note: `#[warn(incomplete_features)]` on by default + = note: see issue #44580 for more information warning: 1 warning emitted diff --git a/src/test/ui/const-generics/struct-with-invalid-const-param.rs b/src/test/ui/const-generics/struct-with-invalid-const-param.rs index 207b07bf6951..0b00481d903e 100644 --- a/src/test/ui/const-generics/struct-with-invalid-const-param.rs +++ b/src/test/ui/const-generics/struct-with-invalid-const-param.rs @@ -1,5 +1,5 @@ #![feature(const_generics)] -//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash +//~^ WARN the feature `const_generics` is incomplete struct S(C); //~ ERROR expected type, found const parameter diff --git a/src/test/ui/const-generics/struct-with-invalid-const-param.stderr b/src/test/ui/const-generics/struct-with-invalid-const-param.stderr index 7472793f8096..a968b26bc261 100644 --- a/src/test/ui/const-generics/struct-with-invalid-const-param.stderr +++ b/src/test/ui/const-generics/struct-with-invalid-const-param.stderr @@ -7,13 +7,14 @@ LL | struct S(C); | | help: a struct with a similar name exists: `S` | similarly named struct `S` defined here -warning: the feature `const_generics` is incomplete and may cause the compiler to crash +warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes --> $DIR/struct-with-invalid-const-param.rs:1:12 | LL | #![feature(const_generics)] | ^^^^^^^^^^^^^^ | = note: `#[warn(incomplete_features)]` on by default + = note: see issue #44580 for more information error: aborting due to previous error; 1 warning emitted diff --git a/src/test/ui/const-generics/transparent-maybeunit-array-wrapper.rs b/src/test/ui/const-generics/transparent-maybeunit-array-wrapper.rs index 794048174f90..1aed9cfe9273 100644 --- a/src/test/ui/const-generics/transparent-maybeunit-array-wrapper.rs +++ b/src/test/ui/const-generics/transparent-maybeunit-array-wrapper.rs @@ -1,7 +1,7 @@ // run-pass #![feature(const_generics)] -//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash +//~^ WARN the feature `const_generics` is incomplete use std::mem::MaybeUninit; diff --git a/src/test/ui/const-generics/transparent-maybeunit-array-wrapper.stderr b/src/test/ui/const-generics/transparent-maybeunit-array-wrapper.stderr index 0bf408398135..6077fe5b1ed3 100644 --- a/src/test/ui/const-generics/transparent-maybeunit-array-wrapper.stderr +++ b/src/test/ui/const-generics/transparent-maybeunit-array-wrapper.stderr @@ -1,10 +1,11 @@ -warning: the feature `const_generics` is incomplete and may cause the compiler to crash +warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes --> $DIR/transparent-maybeunit-array-wrapper.rs:3:12 | LL | #![feature(const_generics)] | ^^^^^^^^^^^^^^ | = note: `#[warn(incomplete_features)]` on by default + = note: see issue #44580 for more information warning: 1 warning emitted diff --git a/src/test/ui/const-generics/type_of_anon_const.rs b/src/test/ui/const-generics/type_of_anon_const.rs index 776084b77a57..588c7b9523aa 100644 --- a/src/test/ui/const-generics/type_of_anon_const.rs +++ b/src/test/ui/const-generics/type_of_anon_const.rs @@ -1,7 +1,7 @@ // run-pass #![feature(const_generics)] -//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash +//~^ WARN the feature `const_generics` is incomplete trait T { fn l() -> usize; diff --git a/src/test/ui/const-generics/type_of_anon_const.stderr b/src/test/ui/const-generics/type_of_anon_const.stderr index 5f848c3ec524..8afed0d39866 100644 --- a/src/test/ui/const-generics/type_of_anon_const.stderr +++ b/src/test/ui/const-generics/type_of_anon_const.stderr @@ -1,10 +1,11 @@ -warning: the feature `const_generics` is incomplete and may cause the compiler to crash +warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes --> $DIR/type_of_anon_const.rs:3:12 | LL | #![feature(const_generics)] | ^^^^^^^^^^^^^^ | = note: `#[warn(incomplete_features)]` on by default + = note: see issue #44580 for more information warning: 1 warning emitted diff --git a/src/test/ui/const-generics/types-mismatch-const-args.rs b/src/test/ui/const-generics/types-mismatch-const-args.rs index b25b7331017e..bf517c11262f 100644 --- a/src/test/ui/const-generics/types-mismatch-const-args.rs +++ b/src/test/ui/const-generics/types-mismatch-const-args.rs @@ -1,5 +1,5 @@ #![feature(const_generics)] -//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash +//~^ WARN the feature `const_generics` is incomplete // tests the diagnostic output of type mismatches for types that have const generics arguments. diff --git a/src/test/ui/const-generics/types-mismatch-const-args.stderr b/src/test/ui/const-generics/types-mismatch-const-args.stderr index a76bbd177fbf..2131738554f8 100644 --- a/src/test/ui/const-generics/types-mismatch-const-args.stderr +++ b/src/test/ui/const-generics/types-mismatch-const-args.stderr @@ -1,10 +1,11 @@ -warning: the feature `const_generics` is incomplete and may cause the compiler to crash +warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes --> $DIR/types-mismatch-const-args.rs:1:12 | LL | #![feature(const_generics)] | ^^^^^^^^^^^^^^ | = note: `#[warn(incomplete_features)]` on by default + = note: see issue #44580 for more information error[E0308]: mismatched types --> $DIR/types-mismatch-const-args.rs:13:41 diff --git a/src/test/ui/const-generics/uninferred-consts-during-codegen-1.rs b/src/test/ui/const-generics/uninferred-consts-during-codegen-1.rs index 7942631bb70b..7473718351e9 100644 --- a/src/test/ui/const-generics/uninferred-consts-during-codegen-1.rs +++ b/src/test/ui/const-generics/uninferred-consts-during-codegen-1.rs @@ -1,7 +1,7 @@ // run-pass #![feature(const_generics)] -//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash +//~^ WARN the feature `const_generics` is incomplete use std::fmt; diff --git a/src/test/ui/const-generics/uninferred-consts-during-codegen-1.stderr b/src/test/ui/const-generics/uninferred-consts-during-codegen-1.stderr index c1d115b4f1da..f41628d5d8ee 100644 --- a/src/test/ui/const-generics/uninferred-consts-during-codegen-1.stderr +++ b/src/test/ui/const-generics/uninferred-consts-during-codegen-1.stderr @@ -1,10 +1,11 @@ -warning: the feature `const_generics` is incomplete and may cause the compiler to crash +warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes --> $DIR/uninferred-consts-during-codegen-1.rs:3:12 | LL | #![feature(const_generics)] | ^^^^^^^^^^^^^^ | = note: `#[warn(incomplete_features)]` on by default + = note: see issue #44580 for more information warning: 1 warning emitted diff --git a/src/test/ui/const-generics/uninferred-consts-during-codegen-2.rs b/src/test/ui/const-generics/uninferred-consts-during-codegen-2.rs index 0cf505906f62..8b95a010473e 100644 --- a/src/test/ui/const-generics/uninferred-consts-during-codegen-2.rs +++ b/src/test/ui/const-generics/uninferred-consts-during-codegen-2.rs @@ -1,7 +1,7 @@ // run-pass #![feature(const_generics)] -//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash +//~^ WARN the feature `const_generics` is incomplete use std::fmt; diff --git a/src/test/ui/const-generics/uninferred-consts-during-codegen-2.stderr b/src/test/ui/const-generics/uninferred-consts-during-codegen-2.stderr index 2738f37b21e0..f1703bc3a2f8 100644 --- a/src/test/ui/const-generics/uninferred-consts-during-codegen-2.stderr +++ b/src/test/ui/const-generics/uninferred-consts-during-codegen-2.stderr @@ -1,10 +1,11 @@ -warning: the feature `const_generics` is incomplete and may cause the compiler to crash +warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes --> $DIR/uninferred-consts-during-codegen-2.rs:3:12 | LL | #![feature(const_generics)] | ^^^^^^^^^^^^^^ | = note: `#[warn(incomplete_features)]` on by default + = note: see issue #44580 for more information warning: 1 warning emitted diff --git a/src/test/ui/const-generics/unused-const-param.rs b/src/test/ui/const-generics/unused-const-param.rs index 8025b3af8f1b..d9292efc21b7 100644 --- a/src/test/ui/const-generics/unused-const-param.rs +++ b/src/test/ui/const-generics/unused-const-param.rs @@ -1,7 +1,7 @@ // check-pass #![feature(const_generics)] -//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash +//~^ WARN the feature `const_generics` is incomplete struct A; // ok diff --git a/src/test/ui/const-generics/unused-const-param.stderr b/src/test/ui/const-generics/unused-const-param.stderr index 6d3d1a612b8f..be015a689ae1 100644 --- a/src/test/ui/const-generics/unused-const-param.stderr +++ b/src/test/ui/const-generics/unused-const-param.stderr @@ -1,10 +1,11 @@ -warning: the feature `const_generics` is incomplete and may cause the compiler to crash +warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes --> $DIR/unused-const-param.rs:3:12 | LL | #![feature(const_generics)] | ^^^^^^^^^^^^^^ | = note: `#[warn(incomplete_features)]` on by default + = note: see issue #44580 for more information warning: 1 warning emitted diff --git a/src/test/ui/const-generics/unused_braces.rs b/src/test/ui/const-generics/unused_braces.rs index 05234faf7142..2c3ce7c9eab4 100644 --- a/src/test/ui/const-generics/unused_braces.rs +++ b/src/test/ui/const-generics/unused_braces.rs @@ -2,7 +2,7 @@ #![warn(unused_braces)] #![feature(const_generics)] -//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash +//~^ WARN the feature `const_generics` is incomplete struct A; diff --git a/src/test/ui/const-generics/unused_braces.stderr b/src/test/ui/const-generics/unused_braces.stderr index 2cc4070f76e0..e14958ee566e 100644 --- a/src/test/ui/const-generics/unused_braces.stderr +++ b/src/test/ui/const-generics/unused_braces.stderr @@ -1,10 +1,11 @@ -warning: the feature `const_generics` is incomplete and may cause the compiler to crash +warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes --> $DIR/unused_braces.rs:4:12 | LL | #![feature(const_generics)] | ^^^^^^^^^^^^^^ | = note: `#[warn(incomplete_features)]` on by default + = note: see issue #44580 for more information warning: unnecessary braces around const expression --> $DIR/unused_braces.rs:11:14 diff --git a/src/test/ui/error-codes/E0730.rs b/src/test/ui/error-codes/E0730.rs index 66a6e1c817a3..30745814b4a7 100644 --- a/src/test/ui/error-codes/E0730.rs +++ b/src/test/ui/error-codes/E0730.rs @@ -1,5 +1,5 @@ #![feature(const_generics)] -//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash +//~^ WARN the feature `const_generics` is incomplete fn is_123(x: [u32; N]) -> bool { match x { diff --git a/src/test/ui/error-codes/E0730.stderr b/src/test/ui/error-codes/E0730.stderr index b0d43225be6b..f915f6edef52 100644 --- a/src/test/ui/error-codes/E0730.stderr +++ b/src/test/ui/error-codes/E0730.stderr @@ -1,10 +1,11 @@ -warning: the feature `const_generics` is incomplete and may cause the compiler to crash +warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes --> $DIR/E0730.rs:1:12 | LL | #![feature(const_generics)] | ^^^^^^^^^^^^^^ | = note: `#[warn(incomplete_features)]` on by default + = note: see issue #44580 for more information error[E0730]: cannot pattern-match on an array without a fixed length --> $DIR/E0730.rs:6:9 diff --git a/src/test/ui/generic-associated-types/gat-incomplete-warning.stderr b/src/test/ui/generic-associated-types/gat-incomplete-warning.stderr index 50f3c1e0d5ab..0215ff395df7 100644 --- a/src/test/ui/generic-associated-types/gat-incomplete-warning.stderr +++ b/src/test/ui/generic-associated-types/gat-incomplete-warning.stderr @@ -1,10 +1,11 @@ -warning: the feature `generic_associated_types` is incomplete and may cause the compiler to crash +warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes --> $DIR/gat-incomplete-warning.rs:3:12 | LL | #![feature(generic_associated_types)] | ^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `#[warn(incomplete_features)]` on by default + = note: see issue #44265 for more information warning: 1 warning emitted diff --git a/src/test/ui/hygiene/generic_params.stderr b/src/test/ui/hygiene/generic_params.stderr index 94a1eca4953d..4ca6d1998353 100644 --- a/src/test/ui/hygiene/generic_params.stderr +++ b/src/test/ui/hygiene/generic_params.stderr @@ -1,10 +1,11 @@ -warning: the feature `const_generics` is incomplete and may cause the compiler to crash +warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes --> $DIR/generic_params.rs:6:37 | LL | #![feature(decl_macro, rustc_attrs, const_generics)] | ^^^^^^^^^^^^^^ | = note: `#[warn(incomplete_features)]` on by default + = note: see issue #44580 for more information warning: 1 warning emitted diff --git a/src/test/ui/hygiene/issue-61574-const-parameters.stderr b/src/test/ui/hygiene/issue-61574-const-parameters.stderr index 11dba87d97b9..b351b8b73a0e 100644 --- a/src/test/ui/hygiene/issue-61574-const-parameters.stderr +++ b/src/test/ui/hygiene/issue-61574-const-parameters.stderr @@ -1,10 +1,11 @@ -warning: the feature `const_generics` is incomplete and may cause the compiler to crash +warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes --> $DIR/issue-61574-const-parameters.rs:6:12 | LL | #![feature(const_generics)] | ^^^^^^^^^^^^^^ | = note: `#[warn(incomplete_features)]` on by default + = note: see issue #44580 for more information warning: 1 warning emitted diff --git a/src/test/ui/if-attrs/let-chains-attr.stderr b/src/test/ui/if-attrs/let-chains-attr.stderr index 1a48fc12b8f5..8b9874715342 100644 --- a/src/test/ui/if-attrs/let-chains-attr.stderr +++ b/src/test/ui/if-attrs/let-chains-attr.stderr @@ -1,10 +1,11 @@ -warning: the feature `let_chains` is incomplete and may cause the compiler to crash +warning: the feature `let_chains` is incomplete and may not be safe to use and/or cause compiler crashes --> $DIR/let-chains-attr.rs:3:12 | LL | #![feature(let_chains)] | ^^^^^^^^^^ | = note: `#[warn(incomplete_features)]` on by default + = note: see issue #53667 for more information warning: 1 warning emitted diff --git a/src/test/ui/impl-trait-in-bindings.rs b/src/test/ui/impl-trait-in-bindings.rs index 2e9b6cd5c78d..c7fae45d5ca2 100644 --- a/src/test/ui/impl-trait-in-bindings.rs +++ b/src/test/ui/impl-trait-in-bindings.rs @@ -1,7 +1,7 @@ // run-pass #![feature(impl_trait_in_bindings)] -//~^ WARN the feature `impl_trait_in_bindings` is incomplete and may cause the compiler to crash +//~^ WARN the feature `impl_trait_in_bindings` is incomplete use std::fmt::Debug; diff --git a/src/test/ui/impl-trait-in-bindings.stderr b/src/test/ui/impl-trait-in-bindings.stderr index 2623d8e2d025..bf739d4722f6 100644 --- a/src/test/ui/impl-trait-in-bindings.stderr +++ b/src/test/ui/impl-trait-in-bindings.stderr @@ -1,10 +1,11 @@ -warning: the feature `impl_trait_in_bindings` is incomplete and may cause the compiler to crash +warning: the feature `impl_trait_in_bindings` is incomplete and may not be safe to use and/or cause compiler crashes --> $DIR/impl-trait-in-bindings.rs:3:12 | LL | #![feature(impl_trait_in_bindings)] | ^^^^^^^^^^^^^^^^^^^^^^ | = note: `#[warn(incomplete_features)]` on by default + = note: see issue #63065 for more information warning: 1 warning emitted diff --git a/src/test/ui/impl-trait/bindings-opaque.rs b/src/test/ui/impl-trait/bindings-opaque.rs index d4eef29ed320..d1f42be077dc 100644 --- a/src/test/ui/impl-trait/bindings-opaque.rs +++ b/src/test/ui/impl-trait/bindings-opaque.rs @@ -1,5 +1,5 @@ #![feature(impl_trait_in_bindings)] -//~^ WARN the feature `impl_trait_in_bindings` is incomplete and may cause the compiler to crash +//~^ WARN the feature `impl_trait_in_bindings` is incomplete const FOO: impl Copy = 42; diff --git a/src/test/ui/impl-trait/bindings-opaque.stderr b/src/test/ui/impl-trait/bindings-opaque.stderr index 14d33270ca50..6656968d79ae 100644 --- a/src/test/ui/impl-trait/bindings-opaque.stderr +++ b/src/test/ui/impl-trait/bindings-opaque.stderr @@ -1,10 +1,11 @@ -warning: the feature `impl_trait_in_bindings` is incomplete and may cause the compiler to crash +warning: the feature `impl_trait_in_bindings` is incomplete and may not be safe to use and/or cause compiler crashes --> $DIR/bindings-opaque.rs:1:12 | LL | #![feature(impl_trait_in_bindings)] | ^^^^^^^^^^^^^^^^^^^^^^ | = note: `#[warn(incomplete_features)]` on by default + = note: see issue #63065 for more information error[E0599]: no method named `count_ones` found for opaque type `impl std::marker::Copy` in the current scope --> $DIR/bindings-opaque.rs:11:17 diff --git a/src/test/ui/impl-trait/bindings.rs b/src/test/ui/impl-trait/bindings.rs index 104a44d65662..fd79ba68fbdd 100644 --- a/src/test/ui/impl-trait/bindings.rs +++ b/src/test/ui/impl-trait/bindings.rs @@ -1,5 +1,5 @@ #![feature(impl_trait_in_bindings)] -//~^ WARN the feature `impl_trait_in_bindings` is incomplete and may cause the compiler to crash +//~^ WARN the feature `impl_trait_in_bindings` is incomplete fn a(x: T) { const foo: impl Clone = x; diff --git a/src/test/ui/impl-trait/bindings.stderr b/src/test/ui/impl-trait/bindings.stderr index 7d64980074a8..e983fdecdba7 100644 --- a/src/test/ui/impl-trait/bindings.stderr +++ b/src/test/ui/impl-trait/bindings.stderr @@ -22,13 +22,14 @@ error[E0435]: attempt to use a non-constant value in a constant LL | const foo: impl Clone = x; | ^ non-constant value -warning: the feature `impl_trait_in_bindings` is incomplete and may cause the compiler to crash +warning: the feature `impl_trait_in_bindings` is incomplete and may not be safe to use and/or cause compiler crashes --> $DIR/bindings.rs:1:12 | LL | #![feature(impl_trait_in_bindings)] | ^^^^^^^^^^^^^^^^^^^^^^ | = note: `#[warn(incomplete_features)]` on by default + = note: see issue #63065 for more information error: aborting due to 4 previous errors; 1 warning emitted diff --git a/src/test/ui/impl-trait/bound-normalization-fail.stderr b/src/test/ui/impl-trait/bound-normalization-fail.stderr index f5092044627f..36b4ebca4dfc 100644 --- a/src/test/ui/impl-trait/bound-normalization-fail.stderr +++ b/src/test/ui/impl-trait/bound-normalization-fail.stderr @@ -1,10 +1,11 @@ -warning: the feature `impl_trait_in_bindings` is incomplete and may cause the compiler to crash +warning: the feature `impl_trait_in_bindings` is incomplete and may not be safe to use and/or cause compiler crashes --> $DIR/bound-normalization-fail.rs:4:12 | LL | #![feature(impl_trait_in_bindings)] | ^^^^^^^^^^^^^^^^^^^^^^ | = note: `#[warn(incomplete_features)]` on by default + = note: see issue #63065 for more information error[E0271]: type mismatch resolving ` as FooLike>::Output == ::Assoc` --> $DIR/bound-normalization-fail.rs:27:32 diff --git a/src/test/ui/impl-trait/bound-normalization-pass.stderr b/src/test/ui/impl-trait/bound-normalization-pass.stderr index fcc3cc512362..afc181a906ac 100644 --- a/src/test/ui/impl-trait/bound-normalization-pass.stderr +++ b/src/test/ui/impl-trait/bound-normalization-pass.stderr @@ -1,10 +1,11 @@ -warning: the feature `impl_trait_in_bindings` is incomplete and may cause the compiler to crash +warning: the feature `impl_trait_in_bindings` is incomplete and may not be safe to use and/or cause compiler crashes --> $DIR/bound-normalization-pass.rs:5:12 | LL | #![feature(impl_trait_in_bindings)] | ^^^^^^^^^^^^^^^^^^^^^^ | = note: `#[warn(incomplete_features)]` on by default + = note: see issue #63065 for more information warning: 1 warning emitted diff --git a/src/test/ui/inference/cannot-infer-async-enabled-impl-trait-bindings.rs b/src/test/ui/inference/cannot-infer-async-enabled-impl-trait-bindings.rs index 7d75f254bfe7..2e96022318b4 100644 --- a/src/test/ui/inference/cannot-infer-async-enabled-impl-trait-bindings.rs +++ b/src/test/ui/inference/cannot-infer-async-enabled-impl-trait-bindings.rs @@ -1,6 +1,6 @@ // edition:2018 #![feature(impl_trait_in_bindings)] -//~^ WARN the feature `impl_trait_in_bindings` is incomplete and may cause the compiler to crash +//~^ WARN the feature `impl_trait_in_bindings` is incomplete use std::io::Error; diff --git a/src/test/ui/inference/cannot-infer-async-enabled-impl-trait-bindings.stderr b/src/test/ui/inference/cannot-infer-async-enabled-impl-trait-bindings.stderr index 39f5d3c6d8c8..89a22f5e5d63 100644 --- a/src/test/ui/inference/cannot-infer-async-enabled-impl-trait-bindings.stderr +++ b/src/test/ui/inference/cannot-infer-async-enabled-impl-trait-bindings.stderr @@ -1,10 +1,11 @@ -warning: the feature `impl_trait_in_bindings` is incomplete and may cause the compiler to crash +warning: the feature `impl_trait_in_bindings` is incomplete and may not be safe to use and/or cause compiler crashes --> $DIR/cannot-infer-async-enabled-impl-trait-bindings.rs:2:12 | LL | #![feature(impl_trait_in_bindings)] | ^^^^^^^^^^^^^^^^^^^^^^ | = note: `#[warn(incomplete_features)]` on by default + = note: see issue #63065 for more information error[E0282]: type annotations needed for `impl std::future::Future` --> $DIR/cannot-infer-async-enabled-impl-trait-bindings.rs:13:9 diff --git a/src/test/ui/issues/issue-59508-1.rs b/src/test/ui/issues/issue-59508-1.rs index 4fbed9b08f21..a687a9e3be12 100644 --- a/src/test/ui/issues/issue-59508-1.rs +++ b/src/test/ui/issues/issue-59508-1.rs @@ -1,6 +1,6 @@ #![allow(dead_code)] #![feature(const_generics)] -//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash +//~^ WARN the feature `const_generics` is incomplete // This test checks that generic parameter re-ordering diagnostic suggestions mention that // consts come after types and lifetimes when the `const_generics` feature is enabled. diff --git a/src/test/ui/issues/issue-59508-1.stderr b/src/test/ui/issues/issue-59508-1.stderr index 25efbb10529f..85db20b13fb4 100644 --- a/src/test/ui/issues/issue-59508-1.stderr +++ b/src/test/ui/issues/issue-59508-1.stderr @@ -4,13 +4,14 @@ error: lifetime parameters must be declared prior to type parameters LL | pub fn do_things() { | ----^^--^^----- help: reorder the parameters: lifetimes, then types, then consts: `<'a, 'b: 'a, T>` -warning: the feature `const_generics` is incomplete and may cause the compiler to crash +warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes --> $DIR/issue-59508-1.rs:2:12 | LL | #![feature(const_generics)] | ^^^^^^^^^^^^^^ | = note: `#[warn(incomplete_features)]` on by default + = note: see issue #44580 for more information error: aborting due to previous error; 1 warning emitted diff --git a/src/test/ui/parser/impl-item-type-no-body-semantic-fail.stderr b/src/test/ui/parser/impl-item-type-no-body-semantic-fail.stderr index 7678ee6c821f..214467793bce 100644 --- a/src/test/ui/parser/impl-item-type-no-body-semantic-fail.stderr +++ b/src/test/ui/parser/impl-item-type-no-body-semantic-fail.stderr @@ -42,13 +42,14 @@ LL | type W where Self: Eq; | | | help: provide a definition for the type: `= ;` -warning: the feature `generic_associated_types` is incomplete and may cause the compiler to crash +warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes --> $DIR/impl-item-type-no-body-semantic-fail.rs:1:12 | LL | #![feature(generic_associated_types)] | ^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `#[warn(incomplete_features)]` on by default + = note: see issue #44265 for more information error[E0202]: associated types are not yet supported in inherent impls (see #8995) --> $DIR/impl-item-type-no-body-semantic-fail.rs:9:5 diff --git a/src/test/ui/resolve/issue-65035-static-with-parent-generics.rs b/src/test/ui/resolve/issue-65035-static-with-parent-generics.rs index b6a083516093..f09ab3bf9198 100644 --- a/src/test/ui/resolve/issue-65035-static-with-parent-generics.rs +++ b/src/test/ui/resolve/issue-65035-static-with-parent-generics.rs @@ -1,5 +1,5 @@ #![feature(const_generics)] -//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash +//~^ WARN the feature `const_generics` is incomplete fn f() { extern "C" { diff --git a/src/test/ui/resolve/issue-65035-static-with-parent-generics.stderr b/src/test/ui/resolve/issue-65035-static-with-parent-generics.stderr index 6076328b12f7..7f8151db06f5 100644 --- a/src/test/ui/resolve/issue-65035-static-with-parent-generics.stderr +++ b/src/test/ui/resolve/issue-65035-static-with-parent-generics.stderr @@ -40,13 +40,14 @@ LL | fn i() { LL | static a: [u8; N] = [0; N]; | ^ use of generic parameter from outer function -warning: the feature `const_generics` is incomplete and may cause the compiler to crash +warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes --> $DIR/issue-65035-static-with-parent-generics.rs:1:12 | LL | #![feature(const_generics)] | ^^^^^^^^^^^^^^ | = note: `#[warn(incomplete_features)]` on by default + = note: see issue #44580 for more information error: aborting due to 5 previous errors; 1 warning emitted diff --git a/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.stderr b/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.stderr index 4f11c306f503..4c3a00e5f358 100644 --- a/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.stderr +++ b/src/test/ui/rfc-2497-if-let-chains/disallowed-positions.stderr @@ -499,19 +499,22 @@ LL | true && let 1 = 1 = note: only supported directly in conditions of `if`- and `while`-expressions = note: as well as when nested within `&&` and parenthesis in those conditions -warning: the feature `const_generics` is incomplete and may cause the compiler to crash +warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes --> $DIR/disallowed-positions.rs:20:12 | LL | #![feature(const_generics)] | ^^^^^^^^^^^^^^ | = note: `#[warn(incomplete_features)]` on by default + = note: see issue #44580 for more information -warning: the feature `let_chains` is incomplete and may cause the compiler to crash +warning: the feature `let_chains` is incomplete and may not be safe to use and/or cause compiler crashes --> $DIR/disallowed-positions.rs:22:12 | LL | #![feature(let_chains)] // Avoid inflating `.stderr` with overzealous gates in this test. | ^^^^^^^^^^ + | + = note: see issue #53667 for more information error[E0658]: `match` is not allowed in a `const` --> $DIR/disallowed-positions.rs:218:17 diff --git a/src/test/ui/rfc-2627-raw-dylib/link-ordinal-and-name.rs b/src/test/ui/rfc-2627-raw-dylib/link-ordinal-and-name.rs index 5769366fb45a..bf082932bd6c 100644 --- a/src/test/ui/rfc-2627-raw-dylib/link-ordinal-and-name.rs +++ b/src/test/ui/rfc-2627-raw-dylib/link-ordinal-and-name.rs @@ -1,5 +1,5 @@ #![feature(raw_dylib)] -//~^ WARN the feature `raw_dylib` is incomplete and may cause the compiler to crash +//~^ WARN the feature `raw_dylib` is incomplete #[link(name="foo")] extern { diff --git a/src/test/ui/rfc-2627-raw-dylib/link-ordinal-and-name.stderr b/src/test/ui/rfc-2627-raw-dylib/link-ordinal-and-name.stderr index c7765a453c4b..5d8545b50620 100644 --- a/src/test/ui/rfc-2627-raw-dylib/link-ordinal-and-name.stderr +++ b/src/test/ui/rfc-2627-raw-dylib/link-ordinal-and-name.stderr @@ -1,10 +1,11 @@ -warning: the feature `raw_dylib` is incomplete and may cause the compiler to crash +warning: the feature `raw_dylib` is incomplete and may not be safe to use and/or cause compiler crashes --> $DIR/link-ordinal-and-name.rs:1:12 | LL | #![feature(raw_dylib)] | ^^^^^^^^^ | = note: `#[warn(incomplete_features)]` on by default + = note: see issue #58713 for more information error: cannot use `#[link_name]` with `#[link_ordinal]` --> $DIR/link-ordinal-and-name.rs:7:5 diff --git a/src/test/ui/rfc-2627-raw-dylib/link-ordinal-invalid-format.rs b/src/test/ui/rfc-2627-raw-dylib/link-ordinal-invalid-format.rs index 82fb1151c23d..ea633c5bcce2 100644 --- a/src/test/ui/rfc-2627-raw-dylib/link-ordinal-invalid-format.rs +++ b/src/test/ui/rfc-2627-raw-dylib/link-ordinal-invalid-format.rs @@ -1,5 +1,5 @@ #![feature(raw_dylib)] -//~^ WARN the feature `raw_dylib` is incomplete and may cause the compiler to crash +//~^ WARN the feature `raw_dylib` is incomplete #[link(name="foo")] extern { diff --git a/src/test/ui/rfc-2627-raw-dylib/link-ordinal-invalid-format.stderr b/src/test/ui/rfc-2627-raw-dylib/link-ordinal-invalid-format.stderr index 4826c46e90cf..8453a3966bee 100644 --- a/src/test/ui/rfc-2627-raw-dylib/link-ordinal-invalid-format.stderr +++ b/src/test/ui/rfc-2627-raw-dylib/link-ordinal-invalid-format.stderr @@ -1,10 +1,11 @@ -warning: the feature `raw_dylib` is incomplete and may cause the compiler to crash +warning: the feature `raw_dylib` is incomplete and may not be safe to use and/or cause compiler crashes --> $DIR/link-ordinal-invalid-format.rs:1:12 | LL | #![feature(raw_dylib)] | ^^^^^^^^^ | = note: `#[warn(incomplete_features)]` on by default + = note: see issue #58713 for more information error: illegal ordinal format in `link_ordinal` --> $DIR/link-ordinal-invalid-format.rs:6:5 diff --git a/src/test/ui/rfc-2627-raw-dylib/link-ordinal-too-large.rs b/src/test/ui/rfc-2627-raw-dylib/link-ordinal-too-large.rs index 69596ad04fff..55cc329dc594 100644 --- a/src/test/ui/rfc-2627-raw-dylib/link-ordinal-too-large.rs +++ b/src/test/ui/rfc-2627-raw-dylib/link-ordinal-too-large.rs @@ -1,5 +1,5 @@ #![feature(raw_dylib)] -//~^ WARN the feature `raw_dylib` is incomplete and may cause the compiler to crash +//~^ WARN the feature `raw_dylib` is incomplete #[link(name="foo")] extern { diff --git a/src/test/ui/rfc-2627-raw-dylib/link-ordinal-too-large.stderr b/src/test/ui/rfc-2627-raw-dylib/link-ordinal-too-large.stderr index f8bfe5a62b86..35f9b53fdf72 100644 --- a/src/test/ui/rfc-2627-raw-dylib/link-ordinal-too-large.stderr +++ b/src/test/ui/rfc-2627-raw-dylib/link-ordinal-too-large.stderr @@ -1,10 +1,11 @@ -warning: the feature `raw_dylib` is incomplete and may cause the compiler to crash +warning: the feature `raw_dylib` is incomplete and may not be safe to use and/or cause compiler crashes --> $DIR/link-ordinal-too-large.rs:1:12 | LL | #![feature(raw_dylib)] | ^^^^^^^^^ | = note: `#[warn(incomplete_features)]` on by default + = note: see issue #58713 for more information error: ordinal value in `link_ordinal` is too large: `18446744073709551616` --> $DIR/link-ordinal-too-large.rs:6:5 diff --git a/src/test/ui/type-alias-impl-trait/assoc-type-const.rs b/src/test/ui/type-alias-impl-trait/assoc-type-const.rs index 7f3f86e4df00..d53f562e99f4 100644 --- a/src/test/ui/type-alias-impl-trait/assoc-type-const.rs +++ b/src/test/ui/type-alias-impl-trait/assoc-type-const.rs @@ -4,7 +4,7 @@ #![feature(type_alias_impl_trait)] #![feature(const_generics)] -//~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash +//~^ WARN the feature `const_generics` is incomplete trait UnwrapItemsExt<'a, const C: usize> { type Iter; diff --git a/src/test/ui/type-alias-impl-trait/assoc-type-const.stderr b/src/test/ui/type-alias-impl-trait/assoc-type-const.stderr index 77cd7f4b93ab..e0c1b0238612 100644 --- a/src/test/ui/type-alias-impl-trait/assoc-type-const.stderr +++ b/src/test/ui/type-alias-impl-trait/assoc-type-const.stderr @@ -1,10 +1,11 @@ -warning: the feature `const_generics` is incomplete and may cause the compiler to crash +warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes --> $DIR/assoc-type-const.rs:6:12 | LL | #![feature(const_generics)] | ^^^^^^^^^^^^^^ | = note: `#[warn(incomplete_features)]` on by default + = note: see issue #44580 for more information warning: 1 warning emitted diff --git a/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-const.rs b/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-const.rs index 0fd4d26ef60b..bc2bf9eca93b 100644 --- a/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-const.rs +++ b/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-const.rs @@ -6,7 +6,7 @@ // Specifically, this line requires `impl_trait_in_bindings` to be enabled: // https://github.com/rust-lang/rust/blob/481068a707679257e2a738b40987246e0420e787/src/librustc_typeck/check/mod.rs#L856 #![feature(impl_trait_in_bindings)] -//~^ WARN the feature `impl_trait_in_bindings` is incomplete and may cause the compiler to crash +//~^ WARN the feature `impl_trait_in_bindings` is incomplete // Ensures that `const` items can constrain an opaque `impl Trait`. diff --git a/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-const.stderr b/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-const.stderr index 5efb992a2109..b0593d51a250 100644 --- a/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-const.stderr +++ b/src/test/ui/type-alias-impl-trait/type-alias-impl-trait-const.stderr @@ -1,10 +1,11 @@ -warning: the feature `impl_trait_in_bindings` is incomplete and may cause the compiler to crash +warning: the feature `impl_trait_in_bindings` is incomplete and may not be safe to use and/or cause compiler crashes --> $DIR/type-alias-impl-trait-const.rs:8:12 | LL | #![feature(impl_trait_in_bindings)] | ^^^^^^^^^^^^^^^^^^^^^^ | = note: `#[warn(incomplete_features)]` on by default + = note: see issue #63065 for more information warning: 1 warning emitted From e22cc993fbf9918784ec38a25e04564e7b1973ee Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Sat, 9 May 2020 16:08:04 +0200 Subject: [PATCH 068/203] Visit move out of `_0` when visiting `return` --- src/librustc_middle/mir/visit.rs | 18 +++++++++++++++++- src/librustc_mir/transform/copy_prop.rs | 7 ++++++- src/librustc_mir/transform/generator.rs | 10 ++++++++++ src/librustc_mir/transform/inline.rs | 6 +++++- 4 files changed, 38 insertions(+), 3 deletions(-) diff --git a/src/librustc_middle/mir/visit.rs b/src/librustc_middle/mir/visit.rs index 2f3d89dc0298..1f097f24942d 100644 --- a/src/librustc_middle/mir/visit.rs +++ b/src/librustc_middle/mir/visit.rs @@ -427,13 +427,29 @@ macro_rules! make_mir_visitor { TerminatorKind::Goto { .. } | TerminatorKind::Resume | TerminatorKind::Abort | - TerminatorKind::Return | TerminatorKind::GeneratorDrop | TerminatorKind::Unreachable | TerminatorKind::FalseEdges { .. } | TerminatorKind::FalseUnwind { .. } => { } + TerminatorKind::Return => { + // `return` logically moves from the return place `_0`. Note that the place + // cannot be changed by any visitor, though. + let $($mutability)? local = RETURN_PLACE; + self.visit_local( + & $($mutability)? local, + PlaceContext::NonMutatingUse(NonMutatingUseContext::Move), + source_location, + ); + + assert_eq!( + local, + RETURN_PLACE, + "`MutVisitor` tried to mutate return place of `return` terminator" + ); + } + TerminatorKind::SwitchInt { discr, switch_ty, diff --git a/src/librustc_mir/transform/copy_prop.rs b/src/librustc_mir/transform/copy_prop.rs index b9eb58f800e5..ba406c72df84 100644 --- a/src/librustc_mir/transform/copy_prop.rs +++ b/src/librustc_mir/transform/copy_prop.rs @@ -73,7 +73,12 @@ impl<'tcx> MirPass<'tcx> for CopyPropagation { } // Conservatively gives up if the dest is an argument, // because there may be uses of the original argument value. - if body.local_kind(dest_local) == LocalKind::Arg { + // Also gives up on the return place, as we cannot propagate into its implicit + // use by `return`. + if matches!( + body.local_kind(dest_local), + LocalKind::Arg | LocalKind::ReturnPointer + ) { debug!(" Can't copy-propagate local: dest {:?} (argument)", dest_local); continue; } diff --git a/src/librustc_mir/transform/generator.rs b/src/librustc_mir/transform/generator.rs index d334006d7b52..bfc872be653a 100644 --- a/src/librustc_mir/transform/generator.rs +++ b/src/librustc_mir/transform/generator.rs @@ -91,6 +91,16 @@ impl<'tcx> MutVisitor<'tcx> for RenameLocalVisitor<'tcx> { *local = self.to; } } + + fn visit_terminator_kind(&mut self, kind: &mut TerminatorKind<'tcx>, location: Location) { + match kind { + TerminatorKind::Return => { + // Do not replace the implicit `_0` access here, as that's not possible. The + // transform already handles `return` correctly. + } + _ => self.super_terminator_kind(kind, location), + } + } } struct DerefArgVisitor<'tcx> { diff --git a/src/librustc_mir/transform/inline.rs b/src/librustc_mir/transform/inline.rs index a8e949ecb314..632408fde749 100644 --- a/src/librustc_mir/transform/inline.rs +++ b/src/librustc_mir/transform/inline.rs @@ -732,7 +732,11 @@ impl<'a, 'tcx> MutVisitor<'tcx> for Integrator<'a, 'tcx> { } fn visit_terminator_kind(&mut self, kind: &mut TerminatorKind<'tcx>, loc: Location) { - self.super_terminator_kind(kind, loc); + // Don't try to modify the implicit `_0` access on return (`return` terminators are + // replaced down below anyways). + if !matches!(kind, TerminatorKind::Return) { + self.super_terminator_kind(kind, loc); + } match *kind { TerminatorKind::GeneratorDrop | TerminatorKind::Yield { .. } => bug!(), From 0db2aec14a93fd9c5b084aa5f973d3609e625bf6 Mon Sep 17 00:00:00 2001 From: Bastian Kauschke Date: Sat, 9 May 2020 17:10:40 +0200 Subject: [PATCH 069/203] display `ConstKind::Param` --- src/librustc_middle/ty/print/pretty.rs | 4 +++- src/test/ui/array-slice-vec/match_arr_unknown_len.stderr | 2 +- .../array-impls/alloc-types-no-impls-length-33.stderr | 6 +++--- .../array-impls/core-traits-no-impls-length-33.stderr | 4 ++-- src/test/ui/const-generics/broken-mir-2.stderr | 6 +++--- .../ui/const-generics/derive-debug-array-wrapper.stderr | 6 +++--- src/test/ui/const-generics/issues/issue-62504.stderr | 2 +- 7 files changed, 16 insertions(+), 14 deletions(-) diff --git a/src/librustc_middle/ty/print/pretty.rs b/src/librustc_middle/ty/print/pretty.rs index 2d2704fc2bd8..8ec81fb3c570 100644 --- a/src/librustc_middle/ty/print/pretty.rs +++ b/src/librustc_middle/ty/print/pretty.rs @@ -701,12 +701,14 @@ pub trait PrettyPrinter<'tcx>: if self.tcx().sess.verbose() { p!(write("{:?}", sz)); } else if let ty::ConstKind::Unevaluated(..) = sz.val { - // do not try to evaluate unevaluated constants. If we are const evaluating an + // Do not try to evaluate unevaluated constants. If we are const evaluating an // array length anon const, rustc will (with debug assertions) print the // constant's path. Which will end up here again. p!(write("_")); } else if let Some(n) = sz.val.try_to_bits(self.tcx().data_layout.pointer_size) { p!(write("{}", n)); + } else if let ty::ConstKind::Param(param) = sz.val { + p!(write("{}", param)); } else { p!(write("_")); } diff --git a/src/test/ui/array-slice-vec/match_arr_unknown_len.stderr b/src/test/ui/array-slice-vec/match_arr_unknown_len.stderr index 09f65f6acd06..ed29443332f6 100644 --- a/src/test/ui/array-slice-vec/match_arr_unknown_len.stderr +++ b/src/test/ui/array-slice-vec/match_arr_unknown_len.stderr @@ -13,7 +13,7 @@ LL | [1, 2] => true, | ^^^^^^ expected `2usize`, found `N` | = note: expected array `[u32; 2]` - found array `[u32; _]` + found array `[u32; N]` error: aborting due to previous error; 1 warning emitted diff --git a/src/test/ui/const-generics/array-impls/alloc-types-no-impls-length-33.stderr b/src/test/ui/const-generics/array-impls/alloc-types-no-impls-length-33.stderr index d795840551c5..bd26c08a8e5d 100644 --- a/src/test/ui/const-generics/array-impls/alloc-types-no-impls-length-33.stderr +++ b/src/test/ui/const-generics/array-impls/alloc-types-no-impls-length-33.stderr @@ -29,7 +29,7 @@ LL | let boxed_array = >::try_from(boxed_slice); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::convert::TryFrom>` is not implemented for `std::boxed::Box<[i32; 33]>` | = help: the following implementations were found: - as std::convert::TryFrom>> + as std::convert::TryFrom>> error[E0277]: the trait bound `std::rc::Rc<[i32; 33]>: std::convert::From>` is not satisfied --> $DIR/alloc-types-no-impls-length-33.rs:19:23 @@ -53,7 +53,7 @@ LL | let boxed_array = >::try_from(boxed_slice); | ^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::convert::TryFrom>` is not implemented for `std::rc::Rc<[i32; 33]>` | = help: the following implementations were found: - as std::convert::TryFrom>> + as std::convert::TryFrom>> error[E0277]: the trait bound `std::sync::Arc<[i32; 33]>: std::convert::From>` is not satisfied --> $DIR/alloc-types-no-impls-length-33.rs:26:23 @@ -77,7 +77,7 @@ LL | let boxed_array = >::try_from(boxed_slice); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::convert::TryFrom>` is not implemented for `std::sync::Arc<[i32; 33]>` | = help: the following implementations were found: - as std::convert::TryFrom>> + as std::convert::TryFrom>> error: aborting due to 7 previous errors diff --git a/src/test/ui/const-generics/array-impls/core-traits-no-impls-length-33.stderr b/src/test/ui/const-generics/array-impls/core-traits-no-impls-length-33.stderr index c03377d74e9b..76ccc48c32ac 100644 --- a/src/test/ui/const-generics/array-impls/core-traits-no-impls-length-33.stderr +++ b/src/test/ui/const-generics/array-impls/core-traits-no-impls-length-33.stderr @@ -39,9 +39,9 @@ LL | for _ in &[0_usize; 33] { | ^^^^^^^^^^^^^^ the trait `std::iter::IntoIterator` is not implemented for `&[usize; 33]` | = help: the following implementations were found: - <&'a [T; _] as std::iter::IntoIterator> + <&'a [T; N] as std::iter::IntoIterator> <&'a [T] as std::iter::IntoIterator> - <&'a mut [T; _] as std::iter::IntoIterator> + <&'a mut [T; N] as std::iter::IntoIterator> <&'a mut [T] as std::iter::IntoIterator> = note: required by `std::iter::IntoIterator::into_iter` diff --git a/src/test/ui/const-generics/broken-mir-2.stderr b/src/test/ui/const-generics/broken-mir-2.stderr index cbb8159e9b5d..d48524f66dd9 100644 --- a/src/test/ui/const-generics/broken-mir-2.stderr +++ b/src/test/ui/const-generics/broken-mir-2.stderr @@ -10,10 +10,10 @@ error[E0277]: arrays only have std trait implementations for lengths 0..=32 --> $DIR/broken-mir-2.rs:7:36 | LL | struct S([T; N]); - | ^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[T; _]` + | ^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[T; N]` | - = note: required because of the requirements on the impl of `std::fmt::Debug` for `[T; _]` - = note: required because of the requirements on the impl of `std::fmt::Debug` for `&[T; _]` + = note: required because of the requirements on the impl of `std::fmt::Debug` for `[T; N]` + = note: required because of the requirements on the impl of `std::fmt::Debug` for `&[T; N]` = note: required for the cast to the object type `dyn std::fmt::Debug` = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/const-generics/derive-debug-array-wrapper.stderr b/src/test/ui/const-generics/derive-debug-array-wrapper.stderr index 672586fd3fe0..35ecc49cfb3a 100644 --- a/src/test/ui/const-generics/derive-debug-array-wrapper.stderr +++ b/src/test/ui/const-generics/derive-debug-array-wrapper.stderr @@ -10,10 +10,10 @@ error[E0277]: arrays only have std trait implementations for lengths 0..=32 --> $DIR/derive-debug-array-wrapper.rs:6:5 | LL | a: [u32; N], - | ^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[u32; _]` + | ^^^^^^^^^^^ the trait `std::array::LengthAtMost32` is not implemented for `[u32; N]` | - = note: required because of the requirements on the impl of `std::fmt::Debug` for `[u32; _]` - = note: required because of the requirements on the impl of `std::fmt::Debug` for `&[u32; _]` + = note: required because of the requirements on the impl of `std::fmt::Debug` for `[u32; N]` + = note: required because of the requirements on the impl of `std::fmt::Debug` for `&[u32; N]` = note: required for the cast to the object type `dyn std::fmt::Debug` = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/const-generics/issues/issue-62504.stderr b/src/test/ui/const-generics/issues/issue-62504.stderr index a3a864f770cb..5d45e302888d 100644 --- a/src/test/ui/const-generics/issues/issue-62504.stderr +++ b/src/test/ui/const-generics/issues/issue-62504.stderr @@ -4,7 +4,7 @@ error[E0308]: mismatched types LL | ArrayHolder([0; Self::SIZE]) | ^^^^^^^^^^^^^^^ expected `X`, found `Self::SIZE` | - = note: expected array `[u32; _]` + = note: expected array `[u32; X]` found array `[u32; _]` error: constant expression depends on a generic parameter From 0c14ea8ed79ebf0b7368659282136e876f247cc9 Mon Sep 17 00:00:00 2001 From: Glenn Hope Date: Sun, 3 May 2020 10:56:25 -0700 Subject: [PATCH 070/203] Allow 'use super::*;' imports --- clippy_lints/src/wildcard_imports.rs | 19 +++++++++++--- tests/ui/wildcard_imports.fixed | 38 ++++++++++++++++++++++++++++ tests/ui/wildcard_imports.rs | 38 ++++++++++++++++++++++++++++ tests/ui/wildcard_imports.stderr | 20 ++++++++++++++- 4 files changed, 111 insertions(+), 4 deletions(-) diff --git a/clippy_lints/src/wildcard_imports.rs b/clippy_lints/src/wildcard_imports.rs index f3038861cee2..70ad9a60a02c 100644 --- a/clippy_lints/src/wildcard_imports.rs +++ b/clippy_lints/src/wildcard_imports.rs @@ -3,7 +3,7 @@ use if_chain::if_chain; use rustc_errors::Applicability; use rustc_hir::{ def::{DefKind, Res}, - Item, ItemKind, UseKind, + Item, ItemKind, PathSegment, UseKind, }; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; @@ -83,8 +83,8 @@ impl LateLintPass<'_, '_> for WildcardImports { if_chain! { if !in_macro(item.span); if let ItemKind::Use(use_path, UseKind::Glob) = &item.kind; - // don't lint prelude glob imports - if !use_path.segments.iter().last().map_or(false, |ps| ps.ident.as_str() == "prelude"); + if !is_prelude_import(use_path.segments); + if !is_super_only_import_in_test(use_path.segments); let used_imports = cx.tcx.names_imported_by_glob_use(item.hir_id.owner); if !used_imports.is_empty(); // Already handled by `unused_imports` then { @@ -154,3 +154,16 @@ impl LateLintPass<'_, '_> for WildcardImports { } } } + +// Allow "...prelude::*" imports. +// Many crates have a prelude, and it is imported as a glob by design. +fn is_prelude_import(segments: &[PathSegment<'_>]) -> bool { + segments.iter().last().map_or(false, |ps| ps.ident.as_str() == "prelude") +} + +// Allow "super::*" imports. +// This is intended primarily to ease the process of writing unit tests. +fn is_super_only_import_in_test(segments: &[PathSegment<'_>]) -> bool { + segments.iter().len() == 1 && + segments.first().map_or(false, |ps| ps.ident.as_str() == "super") +} diff --git a/tests/ui/wildcard_imports.fixed b/tests/ui/wildcard_imports.fixed index ed6cc00ef048..003f11009a06 100644 --- a/tests/ui/wildcard_imports.fixed +++ b/tests/ui/wildcard_imports.fixed @@ -155,3 +155,41 @@ fn test_weird_formatting() { exported(); foo(); } + +mod test_super_imports { + fn foofoo() {} + + mod use_super { + use super::*; + + fn with_super() { + let _ = foofoo(); + } + } + + mod use_explicit { + use test_super_imports::foofoo; + + fn with_explicit() { + let _ = foofoo(); + } + } + + mod use_double_super { + mod inner { + use super::super::foofoo; + + fn with_double_super() { + let _ = foofoo(); + } + } + } + + mod use_super_explicit { + use super::super::test_super_imports::foofoo; + + fn with_super_explicit() { + let _ = foofoo(); + } + } +} diff --git a/tests/ui/wildcard_imports.rs b/tests/ui/wildcard_imports.rs index c6d6efaece81..7bd57c7965a6 100644 --- a/tests/ui/wildcard_imports.rs +++ b/tests/ui/wildcard_imports.rs @@ -156,3 +156,41 @@ fn test_weird_formatting() { exported(); foo(); } + +mod test_super_imports { + fn foofoo() {} + + mod use_super { + use super::*; + + fn with_super() { + let _ = foofoo(); + } + } + + mod use_explicit { + use test_super_imports::*; + + fn with_explicit() { + let _ = foofoo(); + } + } + + mod use_double_super { + mod inner { + use super::super::*; + + fn with_double_super() { + let _ = foofoo(); + } + } + } + + mod use_super_explicit { + use super::super::test_super_imports::*; + + fn with_super_explicit() { + let _ = foofoo(); + } + } +} diff --git a/tests/ui/wildcard_imports.stderr b/tests/ui/wildcard_imports.stderr index 050e4c6304f0..858dc28797fa 100644 --- a/tests/ui/wildcard_imports.stderr +++ b/tests/ui/wildcard_imports.stderr @@ -92,5 +92,23 @@ LL | use crate:: fn_mod:: LL | | *; | |_________^ help: try: `crate:: fn_mod::foo` -error: aborting due to 15 previous errors +error: usage of wildcard import + --> $DIR/wildcard_imports.rs:172:13 + | +LL | use test_super_imports::*; + | ^^^^^^^^^^^^^^^^^^^^^ help: try: `test_super_imports::foofoo` + +error: usage of wildcard import + --> $DIR/wildcard_imports.rs:181:17 + | +LL | use super::super::*; + | ^^^^^^^^^^^^^^^ help: try: `super::super::foofoo` + +error: usage of wildcard import + --> $DIR/wildcard_imports.rs:190:13 + | +LL | use super::super::test_super_imports::*; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `super::super::test_super_imports::foofoo` + +error: aborting due to 18 previous errors From bdc75dbb7bbdc379b1f8cc346151fac4e63d7deb Mon Sep 17 00:00:00 2001 From: Glenn Hope Date: Sun, 3 May 2020 11:18:10 -0700 Subject: [PATCH 071/203] Run `cargo dev fmt` --- clippy_lints/src/wildcard_imports.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/wildcard_imports.rs b/clippy_lints/src/wildcard_imports.rs index 70ad9a60a02c..e7400642b078 100644 --- a/clippy_lints/src/wildcard_imports.rs +++ b/clippy_lints/src/wildcard_imports.rs @@ -158,12 +158,14 @@ impl LateLintPass<'_, '_> for WildcardImports { // Allow "...prelude::*" imports. // Many crates have a prelude, and it is imported as a glob by design. fn is_prelude_import(segments: &[PathSegment<'_>]) -> bool { - segments.iter().last().map_or(false, |ps| ps.ident.as_str() == "prelude") + segments + .iter() + .last() + .map_or(false, |ps| ps.ident.as_str() == "prelude") } // Allow "super::*" imports. // This is intended primarily to ease the process of writing unit tests. fn is_super_only_import_in_test(segments: &[PathSegment<'_>]) -> bool { - segments.iter().len() == 1 && - segments.first().map_or(false, |ps| ps.ident.as_str() == "super") + segments.iter().len() == 1 && segments.first().map_or(false, |ps| ps.ident.as_str() == "super") } From 56f4e1c3a8be54c1c80de366618e83d8d7a6e9eb Mon Sep 17 00:00:00 2001 From: Glenn Hope Date: Thu, 7 May 2020 08:06:30 -0700 Subject: [PATCH 072/203] Check if the parent module name contains "test" --- clippy_lints/src/wildcard_imports.rs | 19 ++++++++++++------- tests/ui/wildcard_imports.fixed | 16 ++++++++++++---- tests/ui/wildcard_imports.rs | 16 ++++++++++++---- tests/ui/wildcard_imports.stderr | 14 ++++++++++---- 4 files changed, 46 insertions(+), 19 deletions(-) diff --git a/clippy_lints/src/wildcard_imports.rs b/clippy_lints/src/wildcard_imports.rs index e7400642b078..a22d0e6775de 100644 --- a/clippy_lints/src/wildcard_imports.rs +++ b/clippy_lints/src/wildcard_imports.rs @@ -84,7 +84,7 @@ impl LateLintPass<'_, '_> for WildcardImports { if !in_macro(item.span); if let ItemKind::Use(use_path, UseKind::Glob) = &item.kind; if !is_prelude_import(use_path.segments); - if !is_super_only_import_in_test(use_path.segments); + if !(is_super_only_import(use_path.segments) && is_in_test_module(cx, item)); let used_imports = cx.tcx.names_imported_by_glob_use(item.hir_id.owner); if !used_imports.is_empty(); // Already handled by `unused_imports` then { @@ -109,8 +109,7 @@ impl LateLintPass<'_, '_> for WildcardImports { span = use_path.span.with_hi(item.span.hi() - BytePos(1)); } ( - span, - false, + span, false, ) }; @@ -164,8 +163,14 @@ fn is_prelude_import(segments: &[PathSegment<'_>]) -> bool { .map_or(false, |ps| ps.ident.as_str() == "prelude") } -// Allow "super::*" imports. -// This is intended primarily to ease the process of writing unit tests. -fn is_super_only_import_in_test(segments: &[PathSegment<'_>]) -> bool { - segments.iter().len() == 1 && segments.first().map_or(false, |ps| ps.ident.as_str() == "super") +// Allow "super::*" imports in tests. +fn is_super_only_import(segments: &[PathSegment<'_>]) -> bool { + segments.len() == 1 && segments[0].ident.as_str() == "super" +} + +fn is_in_test_module(cx: &LateContext<'_, '_>, item: &Item<'_>) -> bool { + let parent = cx.tcx.hir().get_parent_node(item.hir_id); + let parent_item = cx.tcx.hir().expect_item(parent); + let parent_name = parent_item.ident.name.as_str(); + parent_name.contains("test") } diff --git a/tests/ui/wildcard_imports.fixed b/tests/ui/wildcard_imports.fixed index 003f11009a06..1c5c01f65d15 100644 --- a/tests/ui/wildcard_imports.fixed +++ b/tests/ui/wildcard_imports.fixed @@ -159,7 +159,15 @@ fn test_weird_formatting() { mod test_super_imports { fn foofoo() {} - mod use_super { + mod use_super_should_be_replaced { + use super::foofoo; + + fn with_super() { + let _ = foofoo(); + } + } + + mod use_super_in_test_should_pass { use super::*; fn with_super() { @@ -167,7 +175,7 @@ mod test_super_imports { } } - mod use_explicit { + mod use_explicit_should_be_replaced { use test_super_imports::foofoo; fn with_explicit() { @@ -175,7 +183,7 @@ mod test_super_imports { } } - mod use_double_super { + mod use_double_super_should_be_replaced { mod inner { use super::super::foofoo; @@ -185,7 +193,7 @@ mod test_super_imports { } } - mod use_super_explicit { + mod use_super_explicit_should_be_replaced { use super::super::test_super_imports::foofoo; fn with_super_explicit() { diff --git a/tests/ui/wildcard_imports.rs b/tests/ui/wildcard_imports.rs index 7bd57c7965a6..f783149ef93e 100644 --- a/tests/ui/wildcard_imports.rs +++ b/tests/ui/wildcard_imports.rs @@ -160,7 +160,7 @@ fn test_weird_formatting() { mod test_super_imports { fn foofoo() {} - mod use_super { + mod use_super_should_be_replaced { use super::*; fn with_super() { @@ -168,7 +168,15 @@ mod test_super_imports { } } - mod use_explicit { + mod use_super_in_test_should_pass { + use super::*; + + fn with_super() { + let _ = foofoo(); + } + } + + mod use_explicit_should_be_replaced { use test_super_imports::*; fn with_explicit() { @@ -176,7 +184,7 @@ mod test_super_imports { } } - mod use_double_super { + mod use_double_super_should_be_replaced { mod inner { use super::super::*; @@ -186,7 +194,7 @@ mod test_super_imports { } } - mod use_super_explicit { + mod use_super_explicit_should_be_replaced { use super::super::test_super_imports::*; fn with_super_explicit() { diff --git a/tests/ui/wildcard_imports.stderr b/tests/ui/wildcard_imports.stderr index 858dc28797fa..649d550a88d1 100644 --- a/tests/ui/wildcard_imports.stderr +++ b/tests/ui/wildcard_imports.stderr @@ -93,22 +93,28 @@ LL | | *; | |_________^ help: try: `crate:: fn_mod::foo` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:172:13 + --> $DIR/wildcard_imports.rs:164:13 + | +LL | use super::*; + | ^^^^^^^^ help: try: `super::foofoo` + +error: usage of wildcard import + --> $DIR/wildcard_imports.rs:180:13 | LL | use test_super_imports::*; | ^^^^^^^^^^^^^^^^^^^^^ help: try: `test_super_imports::foofoo` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:181:17 + --> $DIR/wildcard_imports.rs:189:17 | LL | use super::super::*; | ^^^^^^^^^^^^^^^ help: try: `super::super::foofoo` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:190:13 + --> $DIR/wildcard_imports.rs:198:13 | LL | use super::super::test_super_imports::*; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `super::super::test_super_imports::foofoo` -error: aborting due to 18 previous errors +error: aborting due to 19 previous errors From ad92486d52fdede5c712dd27c868c942d8240704 Mon Sep 17 00:00:00 2001 From: Glenn Hope Date: Thu, 7 May 2020 14:41:54 -0700 Subject: [PATCH 073/203] Add check for "test" in parent name. Include flag for disabling wildcard import exceptions --- clippy_lints/src/lib.rs | 3 +- clippy_lints/src/utils/conf.rs | 2 + clippy_lints/src/wildcard_imports.rs | 48 +++++++++++++++---- .../toml_unknown_key/conf_unknown_key.stderr | 2 +- tests/ui/wildcard_imports.fixed | 17 +++++-- tests/ui/wildcard_imports.rs | 17 +++++-- tests/ui/wildcard_imports.stderr | 14 +++--- 7 files changed, 75 insertions(+), 28 deletions(-) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index fb2e9932b8e4..4b67c84e38ed 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -1058,7 +1058,8 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: let max_struct_bools = conf.max_struct_bools; store.register_early_pass(move || box excessive_bools::ExcessiveBools::new(max_struct_bools, max_fn_params_bools)); store.register_early_pass(|| box option_env_unwrap::OptionEnvUnwrap); - store.register_late_pass(|| box wildcard_imports::WildcardImports); + let warn_on_all_wildcard_imports = conf.warn_on_all_wildcard_imports; + store.register_late_pass(move || box wildcard_imports::WildcardImports::new(warn_on_all_wildcard_imports)); store.register_early_pass(|| box macro_use::MacroUseImports); store.register_late_pass(|| box verbose_file_reads::VerboseFileReads); store.register_late_pass(|| box redundant_pub_crate::RedundantPubCrate::default()); diff --git a/clippy_lints/src/utils/conf.rs b/clippy_lints/src/utils/conf.rs index 4b81ff33495c..57b9eafd14db 100644 --- a/clippy_lints/src/utils/conf.rs +++ b/clippy_lints/src/utils/conf.rs @@ -158,6 +158,8 @@ define_Conf! { (max_struct_bools, "max_struct_bools": u64, 3), /// Lint: FN_PARAMS_EXCESSIVE_BOOLS. The maximum number of bools function parameters can have (max_fn_params_bools, "max_fn_params_bools": u64, 3), + /// Lint: WILDCARD_IMPORTS. Whether to allow certain wildcard imports (prelude, super in tests). + (warn_on_all_wildcard_imports, "warn_on_all_wildcard_imports": bool, false), } impl Default for Conf { diff --git a/clippy_lints/src/wildcard_imports.rs b/clippy_lints/src/wildcard_imports.rs index a22d0e6775de..43d0d1b9e96c 100644 --- a/clippy_lints/src/wildcard_imports.rs +++ b/clippy_lints/src/wildcard_imports.rs @@ -6,7 +6,7 @@ use rustc_hir::{ Item, ItemKind, PathSegment, UseKind, }; use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::BytePos; declare_clippy_lint! { @@ -73,18 +73,38 @@ declare_clippy_lint! { "lint `use _::*` statements" } -declare_lint_pass!(WildcardImports => [ENUM_GLOB_USE, WILDCARD_IMPORTS]); +#[derive(Default)] +pub struct WildcardImports { + warn_on_all: bool, + is_test_module: bool, + test_modules_deep: u32, +} + +impl WildcardImports { + pub fn new(warn_on_all: bool) -> Self { + Self { + warn_on_all, + is_test_module: false, + test_modules_deep: 0, + } + } +} + +impl_lint_pass!(WildcardImports => [ENUM_GLOB_USE, WILDCARD_IMPORTS]); impl LateLintPass<'_, '_> for WildcardImports { fn check_item(&mut self, cx: &LateContext<'_, '_>, item: &Item<'_>) { if item.vis.node.is_pub() || item.vis.node.is_pub_restricted() { return; } + if is_test_module(item) { + self.is_test_module = true; + self.test_modules_deep += 1; + } if_chain! { if !in_macro(item.span); if let ItemKind::Use(use_path, UseKind::Glob) = &item.kind; - if !is_prelude_import(use_path.segments); - if !(is_super_only_import(use_path.segments) && is_in_test_module(cx, item)); + if self.warn_on_all || !self.check_exceptions(use_path.segments); let used_imports = cx.tcx.names_imported_by_glob_use(item.hir_id.owner); if !used_imports.is_empty(); // Already handled by `unused_imports` then { @@ -152,6 +172,19 @@ impl LateLintPass<'_, '_> for WildcardImports { } } } + + fn check_item_post(&mut self, _: &LateContext<'_, '_>, _: &Item<'_>) { + if self.is_test_module { + self.is_test_module = false; + self.test_modules_deep -= 1; + } + } +} + +impl WildcardImports { + fn check_exceptions(&self, segments: &[PathSegment<'_>]) -> bool { + is_prelude_import(segments) || (is_super_only_import(segments) && self.test_modules_deep > 0) + } } // Allow "...prelude::*" imports. @@ -168,9 +201,6 @@ fn is_super_only_import(segments: &[PathSegment<'_>]) -> bool { segments.len() == 1 && segments[0].ident.as_str() == "super" } -fn is_in_test_module(cx: &LateContext<'_, '_>, item: &Item<'_>) -> bool { - let parent = cx.tcx.hir().get_parent_node(item.hir_id); - let parent_item = cx.tcx.hir().expect_item(parent); - let parent_name = parent_item.ident.name.as_str(); - parent_name.contains("test") +fn is_test_module(item: &Item<'_>) -> bool { + item.ident.name.as_str().contains("test") } diff --git a/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr b/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr index 18f5d994ba8a..53970af41079 100644 --- a/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr +++ b/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr @@ -1,4 +1,4 @@ -error: error reading Clippy's configuration file `$DIR/clippy.toml`: unknown field `foobar`, expected one of `blacklisted-names`, `cognitive-complexity-threshold`, `cyclomatic-complexity-threshold`, `doc-valid-idents`, `too-many-arguments-threshold`, `type-complexity-threshold`, `single-char-binding-names-threshold`, `too-large-for-stack`, `enum-variant-name-threshold`, `enum-variant-size-threshold`, `verbose-bit-mask-threshold`, `literal-representation-threshold`, `trivial-copy-size-limit`, `too-many-lines-threshold`, `array-size-threshold`, `vec-box-size-threshold`, `max-struct-bools`, `max-fn-params-bools`, `third-party` at line 5 column 1 +error: error reading Clippy's configuration file `$DIR/clippy.toml`: unknown field `foobar`, expected one of `blacklisted-names`, `cognitive-complexity-threshold`, `cyclomatic-complexity-threshold`, `doc-valid-idents`, `too-many-arguments-threshold`, `type-complexity-threshold`, `single-char-binding-names-threshold`, `too-large-for-stack`, `enum-variant-name-threshold`, `enum-variant-size-threshold`, `verbose-bit-mask-threshold`, `literal-representation-threshold`, `trivial-copy-size-limit`, `too-many-lines-threshold`, `array-size-threshold`, `vec-box-size-threshold`, `max-struct-bools`, `max-fn-params-bools`, `warn-on-all-wildcard-imports`, `third-party` at line 5 column 1 error: aborting due to previous error diff --git a/tests/ui/wildcard_imports.fixed b/tests/ui/wildcard_imports.fixed index 1c5c01f65d15..98bf6acfe55f 100644 --- a/tests/ui/wildcard_imports.fixed +++ b/tests/ui/wildcard_imports.fixed @@ -156,10 +156,10 @@ fn test_weird_formatting() { foo(); } -mod test_super_imports { +mod super_imports { fn foofoo() {} - mod use_super_should_be_replaced { + mod should_be_replaced { use super::foofoo; fn with_super() { @@ -167,7 +167,7 @@ mod test_super_imports { } } - mod use_super_in_test_should_pass { + mod test_should_pass { use super::*; fn with_super() { @@ -175,8 +175,15 @@ mod test_super_imports { } } + mod inner { + fn test_should_pass() { + use super::*; + let _ = foofoo(); + } + } + mod use_explicit_should_be_replaced { - use test_super_imports::foofoo; + use super_imports::foofoo; fn with_explicit() { let _ = foofoo(); @@ -194,7 +201,7 @@ mod test_super_imports { } mod use_super_explicit_should_be_replaced { - use super::super::test_super_imports::foofoo; + use super::super::super_imports::foofoo; fn with_super_explicit() { let _ = foofoo(); diff --git a/tests/ui/wildcard_imports.rs b/tests/ui/wildcard_imports.rs index f783149ef93e..9275c5a09286 100644 --- a/tests/ui/wildcard_imports.rs +++ b/tests/ui/wildcard_imports.rs @@ -157,10 +157,10 @@ fn test_weird_formatting() { foo(); } -mod test_super_imports { +mod super_imports { fn foofoo() {} - mod use_super_should_be_replaced { + mod should_be_replaced { use super::*; fn with_super() { @@ -168,7 +168,7 @@ mod test_super_imports { } } - mod use_super_in_test_should_pass { + mod test_should_pass { use super::*; fn with_super() { @@ -176,8 +176,15 @@ mod test_super_imports { } } + mod inner { + fn test_should_pass() { + use super::*; + let _ = foofoo(); + } + } + mod use_explicit_should_be_replaced { - use test_super_imports::*; + use super_imports::*; fn with_explicit() { let _ = foofoo(); @@ -195,7 +202,7 @@ mod test_super_imports { } mod use_super_explicit_should_be_replaced { - use super::super::test_super_imports::*; + use super::super::super_imports::*; fn with_super_explicit() { let _ = foofoo(); diff --git a/tests/ui/wildcard_imports.stderr b/tests/ui/wildcard_imports.stderr index 649d550a88d1..bd000ce81616 100644 --- a/tests/ui/wildcard_imports.stderr +++ b/tests/ui/wildcard_imports.stderr @@ -99,22 +99,22 @@ LL | use super::*; | ^^^^^^^^ help: try: `super::foofoo` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:180:13 + --> $DIR/wildcard_imports.rs:187:13 | -LL | use test_super_imports::*; - | ^^^^^^^^^^^^^^^^^^^^^ help: try: `test_super_imports::foofoo` +LL | use super_imports::*; + | ^^^^^^^^^^^^^^^^ help: try: `super_imports::foofoo` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:189:17 + --> $DIR/wildcard_imports.rs:196:17 | LL | use super::super::*; | ^^^^^^^^^^^^^^^ help: try: `super::super::foofoo` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:198:13 + --> $DIR/wildcard_imports.rs:205:13 | -LL | use super::super::test_super_imports::*; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `super::super::test_super_imports::foofoo` +LL | use super::super::super_imports::*; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `super::super::super_imports::foofoo` error: aborting due to 19 previous errors From a42a2bdac2a6c881f85ebdbce66e84d977c74cfa Mon Sep 17 00:00:00 2001 From: Glenn Hope Date: Thu, 7 May 2020 14:48:27 -0700 Subject: [PATCH 074/203] Also have flag disable macro check --- clippy_lints/src/wildcard_imports.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/wildcard_imports.rs b/clippy_lints/src/wildcard_imports.rs index 43d0d1b9e96c..843ddda03569 100644 --- a/clippy_lints/src/wildcard_imports.rs +++ b/clippy_lints/src/wildcard_imports.rs @@ -102,7 +102,7 @@ impl LateLintPass<'_, '_> for WildcardImports { self.test_modules_deep += 1; } if_chain! { - if !in_macro(item.span); + if self.warn_on_all || !in_macro(item.span); if let ItemKind::Use(use_path, UseKind::Glob) = &item.kind; if self.warn_on_all || !self.check_exceptions(use_path.segments); let used_imports = cx.tcx.names_imported_by_glob_use(item.hir_id.owner); From 152cdcb45be7a8f0f24dbcd4177e0858d94516b6 Mon Sep 17 00:00:00 2001 From: Glenn Hope Date: Fri, 8 May 2020 18:22:27 -0700 Subject: [PATCH 075/203] Remove unnecessary field, check for Mod/Fn ItemKind --- clippy_lints/src/wildcard_imports.rs | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/clippy_lints/src/wildcard_imports.rs b/clippy_lints/src/wildcard_imports.rs index 843ddda03569..48405a00d554 100644 --- a/clippy_lints/src/wildcard_imports.rs +++ b/clippy_lints/src/wildcard_imports.rs @@ -76,7 +76,6 @@ declare_clippy_lint! { #[derive(Default)] pub struct WildcardImports { warn_on_all: bool, - is_test_module: bool, test_modules_deep: u32, } @@ -84,7 +83,6 @@ impl WildcardImports { pub fn new(warn_on_all: bool) -> Self { Self { warn_on_all, - is_test_module: false, test_modules_deep: 0, } } @@ -97,8 +95,7 @@ impl LateLintPass<'_, '_> for WildcardImports { if item.vis.node.is_pub() || item.vis.node.is_pub_restricted() { return; } - if is_test_module(item) { - self.is_test_module = true; + if is_test_module_or_function(item) { self.test_modules_deep += 1; } if_chain! { @@ -173,9 +170,8 @@ impl LateLintPass<'_, '_> for WildcardImports { } } - fn check_item_post(&mut self, _: &LateContext<'_, '_>, _: &Item<'_>) { - if self.is_test_module { - self.is_test_module = false; + fn check_item_post(&mut self, _: &LateContext<'_, '_>, item: &Item<'_>) { + if is_test_module_or_function(item) { self.test_modules_deep -= 1; } } @@ -201,6 +197,6 @@ fn is_super_only_import(segments: &[PathSegment<'_>]) -> bool { segments.len() == 1 && segments[0].ident.as_str() == "super" } -fn is_test_module(item: &Item<'_>) -> bool { - item.ident.name.as_str().contains("test") +fn is_test_module_or_function(item: &Item<'_>) -> bool { + matches!(item.kind, ItemKind::Fn(..) | ItemKind::Mod(..)) && item.ident.name.as_str().contains("test") } From 4db6abcd50eb07a7fa8349a059f80792b7b19a2e Mon Sep 17 00:00:00 2001 From: Glenn Hope Date: Sat, 9 May 2020 08:04:07 -0700 Subject: [PATCH 076/203] Remove check for Fn, reflect this in test cases, make test cases more robust/explicit --- clippy_lints/src/wildcard_imports.rs | 13 +++++++++---- tests/ui/wildcard_imports.fixed | 25 +++++++++++++++++++++++-- tests/ui/wildcard_imports.rs | 24 ++++++++++++++++++++++-- tests/ui/wildcard_imports.stderr | 14 ++++++++++---- 4 files changed, 64 insertions(+), 12 deletions(-) diff --git a/clippy_lints/src/wildcard_imports.rs b/clippy_lints/src/wildcard_imports.rs index 48405a00d554..e12a6659ab5b 100644 --- a/clippy_lints/src/wildcard_imports.rs +++ b/clippy_lints/src/wildcard_imports.rs @@ -43,9 +43,14 @@ declare_clippy_lint! { /// /// This can lead to confusing error messages at best and to unexpected behavior at worst. /// - /// Note that this will not warn about wildcard imports from modules named `prelude`; many - /// crates (including the standard library) provide modules named "prelude" specifically - /// designed for wildcard import. + /// **Exceptions:** + /// + /// Wildcard imports are allowed from modules named `prelude`. Many crates (including the standard library) + /// provide modules named "prelude" specifically designed for wildcard import. + /// + /// `use super::*` is allowed in test modules. This is defined as any module with "test" in the name. + /// + /// These exceptions can be disabled using the `warn-on-all-wildcard-imports` configuration flag. /// /// **Known problems:** If macros are imported through the wildcard, this macro is not included /// by the suggestion and has to be added by hand. @@ -198,5 +203,5 @@ fn is_super_only_import(segments: &[PathSegment<'_>]) -> bool { } fn is_test_module_or_function(item: &Item<'_>) -> bool { - matches!(item.kind, ItemKind::Fn(..) | ItemKind::Mod(..)) && item.ident.name.as_str().contains("test") + matches!(item.kind, ItemKind::Mod(..)) && item.ident.name.as_str().contains("test") } diff --git a/tests/ui/wildcard_imports.fixed b/tests/ui/wildcard_imports.fixed index 98bf6acfe55f..b47c8f23e240 100644 --- a/tests/ui/wildcard_imports.fixed +++ b/tests/ui/wildcard_imports.fixed @@ -175,13 +175,34 @@ mod super_imports { } } - mod inner { - fn test_should_pass() { + mod test_should_pass_inside_function { + fn with_super_inside_function() { use super::*; let _ = foofoo(); } } + mod test_should_pass_further_inside { + fn insidefoo() {} + mod inner { + use super::*; + fn with_super() { + let _ = insidefoo(); + } + } + } + + mod should_be_replaced_futher_inside { + fn insidefoo() {} + mod inner { + use super::insidefoo; + fn with_super() { + let _ = insidefoo(); + } + } + } + + mod use_explicit_should_be_replaced { use super_imports::foofoo; diff --git a/tests/ui/wildcard_imports.rs b/tests/ui/wildcard_imports.rs index 9275c5a09286..3ad1a29aebad 100644 --- a/tests/ui/wildcard_imports.rs +++ b/tests/ui/wildcard_imports.rs @@ -176,13 +176,33 @@ mod super_imports { } } - mod inner { - fn test_should_pass() { + mod test_should_pass_inside_function { + fn with_super_inside_function() { use super::*; let _ = foofoo(); } } + mod test_should_pass_further_inside { + fn insidefoo() {} + mod inner { + use super::*; + fn with_super() { + let _ = insidefoo(); + } + } + } + + mod should_be_replaced_futher_inside { + fn insidefoo() {} + mod inner { + use super::*; + fn with_super() { + let _ = insidefoo(); + } + } + } + mod use_explicit_should_be_replaced { use super_imports::*; diff --git a/tests/ui/wildcard_imports.stderr b/tests/ui/wildcard_imports.stderr index bd000ce81616..de07bd1d69ba 100644 --- a/tests/ui/wildcard_imports.stderr +++ b/tests/ui/wildcard_imports.stderr @@ -99,22 +99,28 @@ LL | use super::*; | ^^^^^^^^ help: try: `super::foofoo` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:187:13 + --> $DIR/wildcard_imports.rs:199:17 + | +LL | use super::*; + | ^^^^^^^^ help: try: `super::insidefoo` + +error: usage of wildcard import + --> $DIR/wildcard_imports.rs:208:13 | LL | use super_imports::*; | ^^^^^^^^^^^^^^^^ help: try: `super_imports::foofoo` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:196:17 + --> $DIR/wildcard_imports.rs:217:17 | LL | use super::super::*; | ^^^^^^^^^^^^^^^ help: try: `super::super::foofoo` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:205:13 + --> $DIR/wildcard_imports.rs:226:13 | LL | use super::super::super_imports::*; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `super::super::super_imports::foofoo` -error: aborting due to 19 previous errors +error: aborting due to 20 previous errors From a339766136a183327faaf13b987be30b2940872e Mon Sep 17 00:00:00 2001 From: Glenn Hope Date: Sat, 9 May 2020 08:33:35 -0700 Subject: [PATCH 077/203] Fix test from auto-formatter fix --- tests/ui/wildcard_imports.fixed | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/ui/wildcard_imports.fixed b/tests/ui/wildcard_imports.fixed index b47c8f23e240..67423e6ec1d1 100644 --- a/tests/ui/wildcard_imports.fixed +++ b/tests/ui/wildcard_imports.fixed @@ -202,7 +202,6 @@ mod super_imports { } } - mod use_explicit_should_be_replaced { use super_imports::foofoo; From 0ba61c612ee873314d252ca1f747c14a2f0161ba Mon Sep 17 00:00:00 2001 From: Glenn Hope Date: Sat, 9 May 2020 10:14:29 -0700 Subject: [PATCH 078/203] Check is_macro inside check_exceptions, update references to fix test --- clippy_lints/src/wildcard_imports.rs | 13 +++++++------ tests/ui/wildcard_imports.stderr | 6 +++--- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/clippy_lints/src/wildcard_imports.rs b/clippy_lints/src/wildcard_imports.rs index e12a6659ab5b..2c4e24780e7d 100644 --- a/clippy_lints/src/wildcard_imports.rs +++ b/clippy_lints/src/wildcard_imports.rs @@ -101,12 +101,11 @@ impl LateLintPass<'_, '_> for WildcardImports { return; } if is_test_module_or_function(item) { - self.test_modules_deep += 1; + self.test_modules_deep = self.test_modules_deep.saturating_add(1); } if_chain! { - if self.warn_on_all || !in_macro(item.span); if let ItemKind::Use(use_path, UseKind::Glob) = &item.kind; - if self.warn_on_all || !self.check_exceptions(use_path.segments); + if self.warn_on_all || !self.check_exceptions(item, use_path.segments); let used_imports = cx.tcx.names_imported_by_glob_use(item.hir_id.owner); if !used_imports.is_empty(); // Already handled by `unused_imports` then { @@ -177,14 +176,16 @@ impl LateLintPass<'_, '_> for WildcardImports { fn check_item_post(&mut self, _: &LateContext<'_, '_>, item: &Item<'_>) { if is_test_module_or_function(item) { - self.test_modules_deep -= 1; + self.test_modules_deep = self.test_modules_deep.saturating_sub(1); } } } impl WildcardImports { - fn check_exceptions(&self, segments: &[PathSegment<'_>]) -> bool { - is_prelude_import(segments) || (is_super_only_import(segments) && self.test_modules_deep > 0) + fn check_exceptions(&self, item: &Item<'_>, segments: &[PathSegment<'_>]) -> bool { + in_macro(item.span) + || is_prelude_import(segments) + || (is_super_only_import(segments) && self.test_modules_deep > 0) } } diff --git a/tests/ui/wildcard_imports.stderr b/tests/ui/wildcard_imports.stderr index de07bd1d69ba..fab43b738eb4 100644 --- a/tests/ui/wildcard_imports.stderr +++ b/tests/ui/wildcard_imports.stderr @@ -105,19 +105,19 @@ LL | use super::*; | ^^^^^^^^ help: try: `super::insidefoo` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:208:13 + --> $DIR/wildcard_imports.rs:207:13 | LL | use super_imports::*; | ^^^^^^^^^^^^^^^^ help: try: `super_imports::foofoo` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:217:17 + --> $DIR/wildcard_imports.rs:216:17 | LL | use super::super::*; | ^^^^^^^^^^^^^^^ help: try: `super::super::foofoo` error: usage of wildcard import - --> $DIR/wildcard_imports.rs:226:13 + --> $DIR/wildcard_imports.rs:225:13 | LL | use super::super::super_imports::*; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `super::super::super_imports::foofoo` From b69200b8468434bc3f5b9ef8468733e5d40f4e01 Mon Sep 17 00:00:00 2001 From: Glenn Hope Date: Sat, 9 May 2020 10:16:47 -0700 Subject: [PATCH 079/203] Move is_test_module check to top of function --- clippy_lints/src/wildcard_imports.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/wildcard_imports.rs b/clippy_lints/src/wildcard_imports.rs index 2c4e24780e7d..32d9a45c37d7 100644 --- a/clippy_lints/src/wildcard_imports.rs +++ b/clippy_lints/src/wildcard_imports.rs @@ -97,12 +97,12 @@ impl_lint_pass!(WildcardImports => [ENUM_GLOB_USE, WILDCARD_IMPORTS]); impl LateLintPass<'_, '_> for WildcardImports { fn check_item(&mut self, cx: &LateContext<'_, '_>, item: &Item<'_>) { - if item.vis.node.is_pub() || item.vis.node.is_pub_restricted() { - return; - } if is_test_module_or_function(item) { self.test_modules_deep = self.test_modules_deep.saturating_add(1); } + if item.vis.node.is_pub() || item.vis.node.is_pub_restricted() { + return; + } if_chain! { if let ItemKind::Use(use_path, UseKind::Glob) = &item.kind; if self.warn_on_all || !self.check_exceptions(item, use_path.segments); From bb6a6e08325a38f735b4806f5146e0d6a3fa687f Mon Sep 17 00:00:00 2001 From: Bastian Kauschke Date: Sat, 9 May 2020 21:02:13 +0200 Subject: [PATCH 080/203] move `ty::List` into a new submodule --- src/librustc_middle/ty/list.rs | 149 ++++++++++++++++++++++++++++++++ src/librustc_middle/ty/mod.rs | 151 ++------------------------------- 2 files changed, 155 insertions(+), 145 deletions(-) create mode 100644 src/librustc_middle/ty/list.rs diff --git a/src/librustc_middle/ty/list.rs b/src/librustc_middle/ty/list.rs new file mode 100644 index 000000000000..6427c547a8f2 --- /dev/null +++ b/src/librustc_middle/ty/list.rs @@ -0,0 +1,149 @@ +use crate::arena::Arena; + +use rustc_serialize::{Encodable, Encoder}; + +use std::cmp::{self, Ordering}; +use std::fmt; +use std::hash::{Hash, Hasher}; +use std::mem; +use std::ops::Deref; +use std::ptr; +use std::slice; + +extern "C" { + /// A dummy type used to force `List` to be unsized while not requiring references to it be wide + /// pointers. + type OpaqueListContents; +} + +/// A wrapper for slices with the additional invariant +/// that the slice is interned and no other slice with +/// the same contents can exist in the same context. +/// This means we can use pointer for both +/// equality comparisons and hashing. +/// Note: `Slice` was already taken by the `Ty`. +#[repr(C)] +pub struct List { + len: usize, + data: [T; 0], + opaque: OpaqueListContents, +} + +unsafe impl Sync for List {} + +impl List { + #[inline] + pub(super) fn from_arena<'tcx>(arena: &'tcx Arena<'tcx>, slice: &[T]) -> &'tcx List { + assert!(!mem::needs_drop::()); + assert!(mem::size_of::() != 0); + assert!(!slice.is_empty()); + + // Align up the size of the len (usize) field + let align = mem::align_of::(); + let align_mask = align - 1; + let offset = mem::size_of::(); + let offset = (offset + align_mask) & !align_mask; + + let size = offset + slice.len() * mem::size_of::(); + + let mem = arena + .dropless + .alloc_raw(size, cmp::max(mem::align_of::(), mem::align_of::())); + unsafe { + let result = &mut *(mem.as_mut_ptr() as *mut List); + // Write the length + result.len = slice.len(); + + // Write the elements + let arena_slice = slice::from_raw_parts_mut(result.data.as_mut_ptr(), result.len); + arena_slice.copy_from_slice(slice); + + result + } + } +} + +impl fmt::Debug for List { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + (**self).fmt(f) + } +} + +impl Encodable for List { + #[inline] + fn encode(&self, s: &mut S) -> Result<(), S::Error> { + (**self).encode(s) + } +} + +impl Ord for List +where + T: Ord, +{ + fn cmp(&self, other: &List) -> Ordering { + if self == other { Ordering::Equal } else { <[T] as Ord>::cmp(&**self, &**other) } + } +} + +impl PartialOrd for List +where + T: PartialOrd, +{ + fn partial_cmp(&self, other: &List) -> Option { + if self == other { + Some(Ordering::Equal) + } else { + <[T] as PartialOrd>::partial_cmp(&**self, &**other) + } + } +} + +impl PartialEq for List { + #[inline] + fn eq(&self, other: &List) -> bool { + ptr::eq(self, other) + } +} +impl Eq for List {} + +impl Hash for List { + #[inline] + fn hash(&self, s: &mut H) { + (self as *const List).hash(s) + } +} + +impl Deref for List { + type Target = [T]; + #[inline(always)] + fn deref(&self) -> &[T] { + self.as_ref() + } +} + +impl AsRef<[T]> for List { + #[inline(always)] + fn as_ref(&self) -> &[T] { + unsafe { slice::from_raw_parts(self.data.as_ptr(), self.len) } + } +} + +impl<'a, T> IntoIterator for &'a List { + type Item = &'a T; + type IntoIter = <&'a [T] as IntoIterator>::IntoIter; + #[inline(always)] + fn into_iter(self) -> Self::IntoIter { + self[..].iter() + } +} + +impl List { + #[inline(always)] + pub fn empty<'a>() -> &'a List { + #[repr(align(64), C)] + struct EmptySlice([u8; 64]); + static EMPTY_SLICE: EmptySlice = EmptySlice([0; 64]); + assert!(mem::align_of::() <= 64); + unsafe { &*(&EMPTY_SLICE as *const _ as *const List) } + } +} diff --git a/src/librustc_middle/ty/mod.rs b/src/librustc_middle/ty/mod.rs index 8bb9934789a2..ae0951842995 100644 --- a/src/librustc_middle/ty/mod.rs +++ b/src/librustc_middle/ty/mod.rs @@ -4,7 +4,6 @@ pub use self::BorrowKind::*; pub use self::IntVarValue::*; pub use self::Variance::*; -use crate::arena::Arena; use crate::hir::exports::ExportMap; use crate::ich::StableHashingContext; use crate::infer::canonical::Canonical; @@ -43,13 +42,11 @@ use rustc_span::Span; use rustc_target::abi::{Align, VariantIdx}; use std::cell::RefCell; -use std::cmp::{self, Ordering}; +use std::cmp::Ordering; use std::fmt; use std::hash::{Hash, Hasher}; -use std::ops::Deref; use std::ops::Range; -use std::slice; -use std::{mem, ptr}; +use std::ptr; pub use self::sty::BoundRegion::*; pub use self::sty::InferTy::*; @@ -81,6 +78,8 @@ pub use self::context::{ pub use self::instance::{Instance, InstanceDef}; +pub use self::list::List; + pub use self::trait_def::TraitDef; pub use self::query::queries; @@ -112,6 +111,7 @@ pub mod walk; mod context; mod diagnostics; mod instance; +mod list; mod structural_impls; mod sty; @@ -663,148 +663,9 @@ pub type Ty<'tcx> = &'tcx TyS<'tcx>; impl<'tcx> rustc_serialize::UseSpecializedEncodable for Ty<'tcx> {} impl<'tcx> rustc_serialize::UseSpecializedDecodable for Ty<'tcx> {} - -pub type CanonicalTy<'tcx> = Canonical<'tcx, Ty<'tcx>>; - -extern "C" { - /// A dummy type used to force `List` to be unsized while not requiring references to it be wide - /// pointers. - type OpaqueListContents; -} - -/// A wrapper for slices with the additional invariant -/// that the slice is interned and no other slice with -/// the same contents can exist in the same context. -/// This means we can use pointer for both -/// equality comparisons and hashing. -/// Note: `Slice` was already taken by the `Ty`. -#[repr(C)] -pub struct List { - len: usize, - data: [T; 0], - opaque: OpaqueListContents, -} - -unsafe impl Sync for List {} - -impl List { - #[inline] - fn from_arena<'tcx>(arena: &'tcx Arena<'tcx>, slice: &[T]) -> &'tcx List { - assert!(!mem::needs_drop::()); - assert!(mem::size_of::() != 0); - assert!(!slice.is_empty()); - - // Align up the size of the len (usize) field - let align = mem::align_of::(); - let align_mask = align - 1; - let offset = mem::size_of::(); - let offset = (offset + align_mask) & !align_mask; - - let size = offset + slice.len() * mem::size_of::(); - - let mem = arena - .dropless - .alloc_raw(size, cmp::max(mem::align_of::(), mem::align_of::())); - unsafe { - let result = &mut *(mem.as_mut_ptr() as *mut List); - // Write the length - result.len = slice.len(); - - // Write the elements - let arena_slice = slice::from_raw_parts_mut(result.data.as_mut_ptr(), result.len); - arena_slice.copy_from_slice(slice); - - result - } - } -} - -impl fmt::Debug for List { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - (**self).fmt(f) - } -} - -impl Encodable for List { - #[inline] - fn encode(&self, s: &mut S) -> Result<(), S::Error> { - (**self).encode(s) - } -} - -impl Ord for List -where - T: Ord, -{ - fn cmp(&self, other: &List) -> Ordering { - if self == other { Ordering::Equal } else { <[T] as Ord>::cmp(&**self, &**other) } - } -} - -impl PartialOrd for List -where - T: PartialOrd, -{ - fn partial_cmp(&self, other: &List) -> Option { - if self == other { - Some(Ordering::Equal) - } else { - <[T] as PartialOrd>::partial_cmp(&**self, &**other) - } - } -} - -impl PartialEq for List { - #[inline] - fn eq(&self, other: &List) -> bool { - ptr::eq(self, other) - } -} -impl Eq for List {} - -impl Hash for List { - #[inline] - fn hash(&self, s: &mut H) { - (self as *const List).hash(s) - } -} - -impl Deref for List { - type Target = [T]; - #[inline(always)] - fn deref(&self) -> &[T] { - self.as_ref() - } -} - -impl AsRef<[T]> for List { - #[inline(always)] - fn as_ref(&self) -> &[T] { - unsafe { slice::from_raw_parts(self.data.as_ptr(), self.len) } - } -} - -impl<'a, T> IntoIterator for &'a List { - type Item = &'a T; - type IntoIter = <&'a [T] as IntoIterator>::IntoIter; - #[inline(always)] - fn into_iter(self) -> Self::IntoIter { - self[..].iter() - } -} - impl<'tcx> rustc_serialize::UseSpecializedDecodable for &'tcx List> {} -impl List { - #[inline(always)] - pub fn empty<'a>() -> &'a List { - #[repr(align(64), C)] - struct EmptySlice([u8; 64]); - static EMPTY_SLICE: EmptySlice = EmptySlice([0; 64]); - assert!(mem::align_of::() <= 64); - unsafe { &*(&EMPTY_SLICE as *const _ as *const List) } - } -} +pub type CanonicalTy<'tcx> = Canonical<'tcx, Ty<'tcx>>; #[derive(Clone, Copy, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, HashStable)] pub struct UpvarPath { From b6e4581937dff28f4534e393907124182fb791d0 Mon Sep 17 00:00:00 2001 From: Marko Mijalkovic Date: Sat, 9 May 2020 15:41:49 -0400 Subject: [PATCH 081/203] Add mipsel-sony-psp target --- src/librustc_target/spec/mipsel_sony_psp.rs | 59 ++++ .../spec/mipsel_sony_psp_linker_script.ld | 289 ++++++++++++++++++ src/librustc_target/spec/mod.rs | 2 + 3 files changed, 350 insertions(+) create mode 100644 src/librustc_target/spec/mipsel_sony_psp.rs create mode 100644 src/librustc_target/spec/mipsel_sony_psp_linker_script.ld diff --git a/src/librustc_target/spec/mipsel_sony_psp.rs b/src/librustc_target/spec/mipsel_sony_psp.rs new file mode 100644 index 000000000000..d5765f01ba34 --- /dev/null +++ b/src/librustc_target/spec/mipsel_sony_psp.rs @@ -0,0 +1,59 @@ +use std::{io, fs, env, path::PathBuf}; +use crate::spec::{LinkerFlavor, LldFlavor, LinkArgs, RelocModel}; +use crate::spec::{Target, TargetOptions, TargetResult}; + +// The PSP has custom linker requirements. +const LINKER_SCRIPT: &str = include_str!("./mipsel_sony_psp_linker_script.ld"); + +fn write_script() -> io::Result { + let path = env::temp_dir().join("rustc-mipsel-sony-psp-linkfile.ld"); + fs::write(&path, LINKER_SCRIPT)?; + Ok(path) +} + +pub fn target() -> TargetResult { + let script = write_script().map_err(|e| { + format!("failed to write link script: {}", e) + })?; + + let mut pre_link_args = LinkArgs::new(); + pre_link_args.insert( + LinkerFlavor::Lld(LldFlavor::Ld), + vec![ + "--eh-frame-hdr".to_string(), + "--emit-relocs".to_string(), + "--script".to_string(), + script.display().to_string(), + ], + ); + + Ok(Target { + llvm_target: "mipsel-sony-psp".to_string(), + target_endian: "little".to_string(), + target_pointer_width: "32".to_string(), + target_c_int_width: "32".to_string(), + data_layout: "e-m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64".to_string(), + arch: "mips".to_string(), + target_os: "psp".to_string(), + target_env: "".to_string(), + target_vendor: "sony".to_string(), + linker_flavor: LinkerFlavor::Lld(LldFlavor::Ld), + + options: TargetOptions { + cpu: "mips2".to_string(), + executables: true, + linker: Some("rust-lld".to_owned()), + relocation_model: RelocModel::Static, + + // PSP FPU only supports single precision floats. + features: "+single-float".to_string(), + + // PSP does not support trap-on-condition instructions. + llvm_args: vec![ + "-mno-check-zero-division".to_string(), + ], + pre_link_args, + ..Default::default() + }, + }) +} diff --git a/src/librustc_target/spec/mipsel_sony_psp_linker_script.ld b/src/librustc_target/spec/mipsel_sony_psp_linker_script.ld new file mode 100644 index 000000000000..9dd38f5ce919 --- /dev/null +++ b/src/librustc_target/spec/mipsel_sony_psp_linker_script.ld @@ -0,0 +1,289 @@ +/* + * Copyright (c) 2005 adresd + * Copyright (c) 2005 Marcus R. Brown + * Copyright (c) 2005 James Forshaw + * Copyright (c) 2005 John Kelley + * Copyright (c) 2005 Jesper Svennevid + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The names of the authors may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +OUTPUT_ARCH(mips:allegrex) +ENTRY(module_start) +SECTIONS +{ + /* Read-only sections, merged into text segment: */ + PROVIDE (__executable_start = 0x0); . = 0x0; + .interp : { *(.interp) } + .dynamic : { *(.dynamic) } + .hash : { *(.hash) } + .dynsym : { *(.dynsym) } + .dynstr : { *(.dynstr) } + .gnu.version : { *(.gnu.version) } + .gnu.version_d : { *(.gnu.version_d) } + .gnu.version_r : { *(.gnu.version_r) } + .rel.text : { *(.rel.text .rel.text.* .rel.gnu.linkonce.t.*) } + .rela.text : { *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*) } + .rel.init : { *(.rel.init) } + .rela.init : { *(.rela.init) } + .rel.fini : { *(.rel.fini) } + .rela.fini : { *(.rela.fini) } + /* PSP-specific relocations. */ + .rel.sceStub.text : { *(.rel.sceStub.text) *(SORT(.rel.sceStub.text.*)) } + .rel.lib.ent.top : { *(.rel.lib.ent.top) } + .rel.lib.ent : { *(.rel.lib.ent) } + .rel.lib.ent.btm : { *(.rel.lib.ent.btm) } + .rel.lib.stub.top : { *(.rel.lib.stub.top) } + .rel.lib.stub : { *(.rel.lib.stub) } + .rel.lib.stub.btm : { *(.rel.lib.stub.btm) } + .rel.rodata.sceModuleInfo : { *(.rel.rodata.sceModuleInfo) } + .rel.rodata.sceResident : { *(.rel.rodata.sceResident) } + .rel.rodata.sceNid : { *(.rel.rodata.sceNid) *(SORT(.rel.rodata.sceNid.*)) } + .rel.rodata.sceVstub : { *(.rel.rodata.sceVstub) *(SORT(.rel.rodata.sceVstub.*)) } + .rel.rodata : { *(.rel.rodata .rel.rodata.* .rel.gnu.linkonce.r.*) } + .rela.rodata : { *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*) } + .rel.data.rel.ro : { *(.rel.data.rel.ro*) } + .rela.data.rel.ro : { *(.rel.data.rel.ro*) } + .rel.data : { *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*) } + .rela.data : { *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*) } + .rel.tdata : { *(.rel.tdata .rel.tdata.* .rel.gnu.linkonce.td.*) } + .rela.tdata : { *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*) } + .rel.tbss : { *(.rel.tbss .rel.tbss.* .rel.gnu.linkonce.tb.*) } + .rela.tbss : { *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*) } + .rel.ctors : { *(.rel.ctors) } + .rela.ctors : { *(.rela.ctors) } + .rel.dtors : { *(.rel.dtors) } + .rela.dtors : { *(.rela.dtors) } + .rel.got : { *(.rel.got) } + .rela.got : { *(.rela.got) } + .rel.sdata : { *(.rel.sdata .rel.sdata.* .rel.gnu.linkonce.s.*) } + .rela.sdata : { *(.rela.sdata .rela.sdata.* .rela.gnu.linkonce.s.*) } + .rel.sbss : { *(.rel.sbss .rel.sbss.* .rel.gnu.linkonce.sb.*) } + .rela.sbss : { *(.rela.sbss .rela.sbss.* .rela.gnu.linkonce.sb.*) } + .rel.sdata2 : { *(.rel.sdata2 .rel.sdata2.* .rel.gnu.linkonce.s2.*) } + .rela.sdata2 : { *(.rela.sdata2 .rela.sdata2.* .rela.gnu.linkonce.s2.*) } + .rel.sbss2 : { *(.rel.sbss2 .rel.sbss2.* .rel.gnu.linkonce.sb2.*) } + .rela.sbss2 : { *(.rela.sbss2 .rela.sbss2.* .rela.gnu.linkonce.sb2.*) } + .rel.bss : { *(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*) } + .rela.bss : { *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*) } + .rel.plt : { *(.rel.plt) } + .rela.plt : { *(.rela.plt) } + + /* Start the text section at 0x0 for PRX generation */ + . = 0; + + .text : + { + _ftext = . ; + *(.text .stub .text.* .gnu.linkonce.t.*) + KEEP (*(.text.*personality*)) + /* .gnu.warning sections are handled specially by elf32.em. */ + *(.gnu.warning) + *(.mips16.fn.*) *(.mips16.call.*) + } =0 + .init : + { + KEEP (*(.init)) + } =0 + .plt : { *(.plt) } + .fini : + { + KEEP (*(.fini)) + } =0 + /* PSP library stub functions. */ + .sceStub.text : { *(.sceStub.text) *(SORT(.sceStub.text.*)) } + PROVIDE (__etext = .); + PROVIDE (_etext = .); + PROVIDE (etext = .); + /* PSP library entry table and library stub table. */ + .lib.ent.top : { *(.lib.ent.top) } + .lib.ent : { *(.lib.ent) } + .lib.ent.btm : { *(.lib.ent.btm) } + .lib.stub.top : { *(.lib.stub.top) } + .lib.stub : { *(.lib.stub) } + .lib.stub.btm : { *(.lib.stub.btm) } + /* PSP read-only data for module info, NIDs, and Vstubs. The + .rodata.sceModuleInfo section must appear before the .rodata section + otherwise it would get absorbed into .rodata and the PSP bootloader + would be unable to locate the module info structure. */ + .rodata.sceModuleInfo : { *(.rodata.sceModuleInfo) } + .rodata.sceResident : { *(.rodata.sceResident) } + .rodata.sceNid : { KEEP(*(.rodata.sceNid)) KEEP(*(SORT(.rodata.sceNid.*))) } + .rodata.sceVstub : { *(.rodata.sceVstub) *(SORT(.rodata.sceVstub.*)) } + .rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) } + .rodata1 : { *(.rodata1) } + .sdata2 : { *(.sdata2 .sdata2.* .gnu.linkonce.s2.*) } + .sbss2 : { *(.sbss2 .sbss2.* .gnu.linkonce.sb2.*) } + .gcc_except_table : ONLY_IF_RO { KEEP (*(.gcc_except_table)) *(.gcc_except_table.*) } + + /* Exception handling */ + .eh_frame_hdr : + { + KEEP(*(.eh_frame_hdr)) + } + + __eh_frame_hdr_start = SIZEOF(.eh_frame_hdr) > 0 ? ADDR(.eh_frame_hdr) : 0; + __eh_frame_hdr_end = SIZEOF(.eh_frame_hdr) > 0 ? . : 0; + + .eh_frame : + { + __eh_frame_start = .; + KEEP(*(.eh_frame)) + __eh_frame_end = .; + } + + /* Adjust the address for the data segment. We want to adjust up to + the same address within the page on the next page up. */ + . = ALIGN(256) + (. & (256 - 1)); + + .gcc_except_table : ONLY_IF_RW { KEEP (*(.gcc_except_table)) *(.gcc_except_table.*) } + /* Thread Local Storage sections */ + .tdata : { *(.tdata .tdata.* .gnu.linkonce.td.*) } + .tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) } + /* Ensure the __preinit_array_start label is properly aligned. We + could instead move the label definition inside the section, but + the linker would then create the section even if it turns out to + be empty, which isn't pretty. */ + . = ALIGN(32 / 8); + PROVIDE (__preinit_array_start = .); + .preinit_array : { KEEP (*(.preinit_array)) } + PROVIDE (__preinit_array_end = .); + PROVIDE (__init_array_start = .); + .init_array : { KEEP (*(.init_array)) } + PROVIDE (__init_array_end = .); + PROVIDE (__fini_array_start = .); + .fini_array : { KEEP (*(.fini_array)) } + PROVIDE (__fini_array_end = .); + .ctors : + { + /* gcc uses crtbegin.o to find the start of + the constructors, so we make sure it is + first. Because this is a wildcard, it + doesn't matter if the user does not + actually link against crtbegin.o; the + linker won't look for a file to match a + wildcard. The wildcard also means that it + doesn't matter which directory crtbegin.o + is in. */ + KEEP (*crtbegin*.o(.ctors)) + /* We don't want to include the .ctor section from + from the crtend.o file until after the sorted ctors. + The .ctor section from the crtend file contains the + end of ctors marker and it must be last */ + KEEP (*(EXCLUDE_FILE (*crtend*.o ) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + } + .dtors : + { + KEEP (*crtbegin*.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend*.o ) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + } + .jcr : { KEEP (*(.jcr)) } + .data.rel.ro : { *(.data.rel.ro.local) *(.data.rel.ro*) } + .data : + { + _fdata = . ; + *(.data .data.* .gnu.linkonce.d.*) + KEEP (*(.gnu.linkonce.d.*personality*)) + SORT(CONSTRUCTORS) + } + .data1 : { *(.data1) } + . = .; + _gp = ALIGN(16) + 0x7ff0; + .got : { *(.got.plt) *(.got) } + /* We want the small data sections together, so single-instruction offsets + can access them all, and initialized data all before uninitialized, so + we can shorten the on-disk segment size. */ + .sdata : + { + *(.sdata .sdata.* .gnu.linkonce.s.*) + } + .lit8 : { *(.lit8) } + .lit4 : { *(.lit4) } + _edata = .; + PROVIDE (edata = .); + __bss_start = .; + _fbss = .; + .sbss : + { + PROVIDE (__sbss_start = .); + PROVIDE (___sbss_start = .); + *(.dynsbss) + *(.sbss .sbss.* .gnu.linkonce.sb.*) + *(.scommon) + PROVIDE (__sbss_end = .); + PROVIDE (___sbss_end = .); + } + .bss : + { + *(.dynbss) + *(.bss .bss.* .gnu.linkonce.b.*) + *(COMMON) + /* Align here to ensure that the .bss section occupies space up to + _end. Align after .bss to ensure correct alignment even if the + .bss section disappears because there are no input sections. */ + . = ALIGN(32 / 8); + } + . = ALIGN(32 / 8); + _end = .; + PROVIDE (end = .); + /* Stabs debugging sections. */ + .stab 0 : { *(.stab) } + .stabstr 0 : { *(.stabstr) } + .stab.excl 0 : { *(.stab.excl) } + .stab.exclstr 0 : { *(.stab.exclstr) } + .stab.index 0 : { *(.stab.index) } + .stab.indexstr 0 : { *(.stab.indexstr) } + .comment 0 : { *(.comment) } + /* DWARF debug sections. + Symbols in the DWARF debugging sections are relative to the beginning + of the section so we begin them at 0. */ + /* DWARF 1 */ + .debug 0 : { *(.debug) } + .line 0 : { *(.line) } + /* GNU DWARF 1 extensions */ + .debug_srcinfo 0 : { *(.debug_srcinfo) } + .debug_sfnames 0 : { *(.debug_sfnames) } + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } + /DISCARD/ : { *(.comment) *(.pdr) } + /DISCARD/ : { *(.note.GNU-stack) } +} diff --git a/src/librustc_target/spec/mod.rs b/src/librustc_target/spec/mod.rs index 51dce9e144ca..dab1e51e3f87 100644 --- a/src/librustc_target/spec/mod.rs +++ b/src/librustc_target/spec/mod.rs @@ -582,6 +582,8 @@ supported_targets! { ("powerpc-wrs-vxworks", powerpc_wrs_vxworks), ("powerpc-wrs-vxworks-spe", powerpc_wrs_vxworks_spe), ("powerpc64-wrs-vxworks", powerpc64_wrs_vxworks), + + ("mipsel-sony-psp", mipsel_sony_psp), } /// Everything `rustc` knows about how to compile for a specific target. From 20a66913233589208934d155491c75157947e03e Mon Sep 17 00:00:00 2001 From: Marko Mijalkovic Date: Sat, 9 May 2020 16:03:40 -0400 Subject: [PATCH 082/203] Update stdarch --- src/stdarch | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/stdarch b/src/stdarch index d10eefc62284..ec6fccd34c30 160000 --- a/src/stdarch +++ b/src/stdarch @@ -1 +1 @@ -Subproject commit d10eefc62284c40c5a95a2eed19fc1f414a5364d +Subproject commit ec6fccd34c30003a7ebf4e7a9dfe4e31f5b76e1b From 8961b083762d3660ca21110836b547e8b3f19022 Mon Sep 17 00:00:00 2001 From: Marko Mijalkovic Date: Sat, 9 May 2020 16:39:45 -0400 Subject: [PATCH 083/203] Formatting --- src/librustc_target/spec/mipsel_sony_psp.rs | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/src/librustc_target/spec/mipsel_sony_psp.rs b/src/librustc_target/spec/mipsel_sony_psp.rs index d5765f01ba34..80c253b86bbd 100644 --- a/src/librustc_target/spec/mipsel_sony_psp.rs +++ b/src/librustc_target/spec/mipsel_sony_psp.rs @@ -1,6 +1,6 @@ -use std::{io, fs, env, path::PathBuf}; -use crate::spec::{LinkerFlavor, LldFlavor, LinkArgs, RelocModel}; +use crate::spec::{LinkArgs, LinkerFlavor, LldFlavor, RelocModel}; use crate::spec::{Target, TargetOptions, TargetResult}; +use std::{env, fs, io, path::PathBuf}; // The PSP has custom linker requirements. const LINKER_SCRIPT: &str = include_str!("./mipsel_sony_psp_linker_script.ld"); @@ -12,9 +12,7 @@ fn write_script() -> io::Result { } pub fn target() -> TargetResult { - let script = write_script().map_err(|e| { - format!("failed to write link script: {}", e) - })?; + let script = write_script().map_err(|e| format!("failed to write link script: {}", e))?; let mut pre_link_args = LinkArgs::new(); pre_link_args.insert( @@ -49,9 +47,7 @@ pub fn target() -> TargetResult { features: "+single-float".to_string(), // PSP does not support trap-on-condition instructions. - llvm_args: vec![ - "-mno-check-zero-division".to_string(), - ], + llvm_args: vec!["-mno-check-zero-division".to_string()], pre_link_args, ..Default::default() }, From 0ceacd022c326dadfc65e5cffcde28449c3d735a Mon Sep 17 00:00:00 2001 From: Trevor Spiteri Date: Sun, 10 May 2020 11:24:06 +0200 Subject: [PATCH 084/203] doc: minus (U+2212) instead of dash (U+002D) for negative infinity --- src/libcore/num/f32.rs | 2 +- src/libcore/num/f64.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libcore/num/f32.rs b/src/libcore/num/f32.rs index 4483940c9a77..434569020d2a 100644 --- a/src/libcore/num/f32.rs +++ b/src/libcore/num/f32.rs @@ -367,7 +367,7 @@ impl f32 { /// Infinity (∞). #[stable(feature = "assoc_int_consts", since = "1.43.0")] pub const INFINITY: f32 = 1.0_f32 / 0.0_f32; - /// Negative infinity (-∞). + /// Negative infinity (−∞). #[stable(feature = "assoc_int_consts", since = "1.43.0")] pub const NEG_INFINITY: f32 = -1.0_f32 / 0.0_f32; diff --git a/src/libcore/num/f64.rs b/src/libcore/num/f64.rs index df45e588369f..6476ddb4541f 100644 --- a/src/libcore/num/f64.rs +++ b/src/libcore/num/f64.rs @@ -366,7 +366,7 @@ impl f64 { /// Infinity (∞). #[stable(feature = "assoc_int_consts", since = "1.43.0")] pub const INFINITY: f64 = 1.0_f64 / 0.0_f64; - /// Negative infinity (-∞). + /// Negative infinity (−∞). #[stable(feature = "assoc_int_consts", since = "1.43.0")] pub const NEG_INFINITY: f64 = -1.0_f64 / 0.0_f64; From c82103cb21942b171c2fe135d0a32be620113e47 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 9 May 2020 13:59:21 +0200 Subject: [PATCH 085/203] use min_specialization for some rustc crates where it requires no changes --- src/librustc_ast_lowering/lib.rs | 2 +- src/librustc_data_structures/lib.rs | 2 +- src/librustc_hir/lib.rs | 2 +- src/librustc_metadata/lib.rs | 2 +- src/librustc_middle/lib.rs | 2 +- src/librustc_mir/lib.rs | 2 +- src/librustc_query_system/lib.rs | 2 +- src/librustc_span/lib.rs | 2 +- src/libserialize/lib.rs | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/librustc_ast_lowering/lib.rs b/src/librustc_ast_lowering/lib.rs index 7e6dfbf00f59..2cf81af04166 100644 --- a/src/librustc_ast_lowering/lib.rs +++ b/src/librustc_ast_lowering/lib.rs @@ -33,7 +33,7 @@ #![feature(array_value_iter)] #![feature(crate_visibility_modifier)] #![feature(marker_trait_attr)] -#![feature(specialization)] +#![feature(specialization)] // FIXME: min_specialization does not work #![feature(or_patterns)] #![recursion_limit = "256"] diff --git a/src/librustc_data_structures/lib.rs b/src/librustc_data_structures/lib.rs index 9164734783c9..7ee60176dbea 100644 --- a/src/librustc_data_structures/lib.rs +++ b/src/librustc_data_structures/lib.rs @@ -12,7 +12,7 @@ #![feature(generators)] #![feature(generator_trait)] #![feature(fn_traits)] -#![feature(specialization)] +#![feature(min_specialization)] #![feature(optin_builtin_traits)] #![feature(nll)] #![feature(allow_internal_unstable)] diff --git a/src/librustc_hir/lib.rs b/src/librustc_hir/lib.rs index 49692c73fad8..b51c0a6e9884 100644 --- a/src/librustc_hir/lib.rs +++ b/src/librustc_hir/lib.rs @@ -8,7 +8,7 @@ #![feature(const_panic)] #![feature(in_band_lifetimes)] #![feature(or_patterns)] -#![feature(specialization)] +#![feature(min_specialization)] #![recursion_limit = "256"] #[macro_use] diff --git a/src/librustc_metadata/lib.rs b/src/librustc_metadata/lib.rs index 8db107ed68aa..2a2169880a54 100644 --- a/src/librustc_metadata/lib.rs +++ b/src/librustc_metadata/lib.rs @@ -7,7 +7,7 @@ #![feature(nll)] #![feature(or_patterns)] #![feature(proc_macro_internals)] -#![feature(specialization)] +#![feature(specialization)] // FIXME: min_specialization ICEs #![feature(stmt_expr_attributes)] #![recursion_limit = "256"] diff --git a/src/librustc_middle/lib.rs b/src/librustc_middle/lib.rs index b17a77e0f6fa..d0f627d8bc57 100644 --- a/src/librustc_middle/lib.rs +++ b/src/librustc_middle/lib.rs @@ -41,7 +41,7 @@ #![feature(option_expect_none)] #![feature(or_patterns)] #![feature(range_is_empty)] -#![feature(specialization)] +#![feature(specialization)] // FIXME: min_specialization does not work #![feature(track_caller)] #![feature(trusted_len)] #![feature(vec_remove_item)] diff --git a/src/librustc_mir/lib.rs b/src/librustc_mir/lib.rs index 09f8588cee28..785c6c21d744 100644 --- a/src/librustc_mir/lib.rs +++ b/src/librustc_mir/lib.rs @@ -19,7 +19,7 @@ Rust MIR: a lowered representation of Rust. #![feature(exhaustive_patterns)] #![feature(iter_order_by)] #![feature(never_type)] -#![feature(specialization)] +#![feature(min_specialization)] #![feature(trusted_len)] #![feature(try_blocks)] #![feature(associated_type_bounds)] diff --git a/src/librustc_query_system/lib.rs b/src/librustc_query_system/lib.rs index 0e6a07e06d0f..8e350d3ba267 100644 --- a/src/librustc_query_system/lib.rs +++ b/src/librustc_query_system/lib.rs @@ -4,7 +4,7 @@ #![feature(const_panic)] #![feature(core_intrinsics)] #![feature(hash_raw_entry)] -#![feature(specialization)] +#![feature(specialization)] // FIXME: min_specialization rejects `default const` #![feature(stmt_expr_attributes)] #![feature(vec_remove_item)] diff --git a/src/librustc_span/lib.rs b/src/librustc_span/lib.rs index dd7ba5cb6fc0..58cdb87158af 100644 --- a/src/librustc_span/lib.rs +++ b/src/librustc_span/lib.rs @@ -12,7 +12,7 @@ #![feature(negative_impls)] #![feature(nll)] #![feature(optin_builtin_traits)] -#![feature(specialization)] +#![feature(min_specialization)] // FIXME(#56935): Work around ICEs during cross-compilation. #[allow(unused)] diff --git a/src/libserialize/lib.rs b/src/libserialize/lib.rs index c0011fddf4ff..7261d631a6f3 100644 --- a/src/libserialize/lib.rs +++ b/src/libserialize/lib.rs @@ -10,7 +10,7 @@ Core encoding and decoding interfaces. test(attr(allow(unused_variables), deny(warnings))) )] #![feature(box_syntax)] -#![feature(specialization)] +#![feature(specialization)] // FIXME: min_specialization does not work #![feature(never_type)] #![feature(nll)] #![feature(associated_type_bounds)] From c400f758e5cda9c2617f6d8dec87a6f24ddb291e Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 29 Apr 2020 10:00:22 +0200 Subject: [PATCH 086/203] Miri interning: replace ICEs by proper errors, make intern_shallow type signature more precise --- src/librustc_mir/interpret/eval_context.rs | 3 + src/librustc_mir/interpret/intern.rs | 263 ++++++++++-------- .../ui/consts/miri_unleashed/mutable_const.rs | 25 -- .../miri_unleashed/mutable_const.stderr | 39 --- .../consts/miri_unleashed/mutable_const2.rs | 16 -- .../miri_unleashed/mutable_const2.stderr | 29 -- .../miri_unleashed/mutable_references.rs | 3 +- .../miri_unleashed/mutable_references.stderr | 6 +- .../miri_unleashed/mutable_references_err.rs | 37 +++ .../mutable_references_err.stderr | 40 +++ .../miri_unleashed/mutable_references_ice.rs | 29 -- .../mutable_references_ice.stderr | 25 -- .../miri_unleashed/raw_mutable_const.rs | 12 + .../miri_unleashed/raw_mutable_const.stderr | 16 ++ src/test/ui/consts/raw-ptr-const.rs | 10 + src/test/ui/consts/raw-ptr-const.stderr | 8 + 16 files changed, 274 insertions(+), 287 deletions(-) delete mode 100644 src/test/ui/consts/miri_unleashed/mutable_const.rs delete mode 100644 src/test/ui/consts/miri_unleashed/mutable_const.stderr delete mode 100644 src/test/ui/consts/miri_unleashed/mutable_const2.rs delete mode 100644 src/test/ui/consts/miri_unleashed/mutable_const2.stderr create mode 100644 src/test/ui/consts/miri_unleashed/mutable_references_err.rs create mode 100644 src/test/ui/consts/miri_unleashed/mutable_references_err.stderr delete mode 100644 src/test/ui/consts/miri_unleashed/mutable_references_ice.rs delete mode 100644 src/test/ui/consts/miri_unleashed/mutable_references_ice.stderr create mode 100644 src/test/ui/consts/miri_unleashed/raw_mutable_const.rs create mode 100644 src/test/ui/consts/miri_unleashed/raw_mutable_const.stderr create mode 100644 src/test/ui/consts/raw-ptr-const.rs create mode 100644 src/test/ui/consts/raw-ptr-const.stderr diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs index 9bb7c879505f..eba4dd336ade 100644 --- a/src/librustc_mir/interpret/eval_context.rs +++ b/src/librustc_mir/interpret/eval_context.rs @@ -871,6 +871,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // Our result will later be validated anyway, and there seems no good reason // to have to fail early here. This is also more consistent with // `Memory::get_static_alloc` which has to use `const_eval_raw` to avoid cycles. + // FIXME: We can hit delay_span_bug if this is an invalid const, interning finds + // that problem, but we never run validation to show an error. Can we ensure + // this does not happen? let val = self.tcx.const_eval_raw(param_env.and(gid))?; self.raw_const_to_mplace(val) } diff --git a/src/librustc_mir/interpret/intern.rs b/src/librustc_mir/interpret/intern.rs index 1c44101595d4..c9661c92d2e2 100644 --- a/src/librustc_mir/interpret/intern.rs +++ b/src/librustc_mir/interpret/intern.rs @@ -8,7 +8,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_errors::ErrorReported; use rustc_hir as hir; use rustc_middle::mir::interpret::{ErrorHandled, InterpResult}; -use rustc_middle::ty::{self, Ty}; +use rustc_middle::ty::{self, query::TyCtxtAt, Ty}; use rustc_ast::ast::Mutability; @@ -29,43 +29,44 @@ struct InternVisitor<'rt, 'mir, 'tcx, M: CompileTimeMachine<'mir, 'tcx>> { /// The ectx from which we intern. ecx: &'rt mut InterpCx<'mir, 'tcx, M>, /// Previously encountered safe references. - ref_tracking: &'rt mut RefTracking<(MPlaceTy<'tcx>, Mutability, InternMode)>, + ref_tracking: &'rt mut RefTracking<(MPlaceTy<'tcx>, InternMode)>, /// A list of all encountered allocations. After type-based interning, we traverse this list to /// also intern allocations that are only referenced by a raw pointer or inside a union. leftover_allocations: &'rt mut FxHashSet, - /// The root node of the value that we're looking at. This field is never mutated and only used + /// The root kind of the value that we're looking at. This field is never mutated and only used /// for sanity assertions that will ICE when `const_qualif` screws up. mode: InternMode, - /// This field stores the mutability of the value *currently* being checked. - /// When encountering a mutable reference, we determine the pointee mutability - /// taking into account the mutability of the context: `& &mut i32` is entirely immutable, - /// despite the nested mutable reference! - /// The field gets updated when an `UnsafeCell` is encountered. - mutability: Mutability, + /// This field stores whether we are *currently* inside an `UnsafeCell`. This can affect + /// the intern mode of references we encounter. + inside_unsafe_cell: bool, /// This flag is to avoid triggering UnsafeCells are not allowed behind references in constants /// for promoteds. /// It's a copy of `mir::Body`'s ignore_interior_mut_in_const_validation field - ignore_interior_mut_in_const_validation: bool, + ignore_interior_mut_in_const: bool, } #[derive(Copy, Clone, Debug, PartialEq, Hash, Eq)] enum InternMode { - /// Mutable references must in fact be immutable due to their surrounding immutability in a - /// `static`. In a `static mut` we start out as mutable and thus can also contain further `&mut` - /// that will actually be treated as mutable. - Static, - /// UnsafeCell is OK in the value of a constant: `const FOO = Cell::new(0)` creates - /// a new cell every time it is used. + /// A static and its current mutability. Below shared references inside a `static mut`, + /// this is *immutable*, and below mutable references inside an `UnsafeCell`, this + /// is *mutable*. + Static(hir::Mutability), + /// The "base value" of a const, which can have `UnsafeCell` (as in `const FOO: Cell`), + /// but that interior mutability is simply ignored. ConstBase, - /// `UnsafeCell` ICEs. - Const, + /// The "inner values" of a const with references, where `UnsafeCell` is an error. + ConstInner, } /// Signalling data structure to ensure we don't recurse /// into the memory of other constants or statics struct IsStaticOrFn; +fn mutable_memory_in_const(tcx: TyCtxtAt<'_>, kind: &str) { + tcx.sess.span_err(tcx.span, &format!("mutable memory ({}) is not allowed in constant", kind)); +} + /// Intern an allocation without looking at its children. /// `mode` is the mode of the environment where we found this pointer. /// `mutablity` is the mutability of the place to be interned; even if that says @@ -75,12 +76,11 @@ struct IsStaticOrFn; fn intern_shallow<'rt, 'mir, 'tcx, M: CompileTimeMachine<'mir, 'tcx>>( ecx: &'rt mut InterpCx<'mir, 'tcx, M>, leftover_allocations: &'rt mut FxHashSet, - mode: InternMode, alloc_id: AllocId, - mutability: Mutability, + mode: InternMode, ty: Option>, ) -> InterpResult<'tcx, Option> { - trace!("InternVisitor::intern {:?} with {:?}", alloc_id, mutability,); + trace!("intern_shallow {:?} with {:?}", alloc_id, mode); // remove allocation let tcx = ecx.tcx; let (kind, mut alloc) = match ecx.memory.alloc_map.remove(&alloc_id) { @@ -89,8 +89,9 @@ fn intern_shallow<'rt, 'mir, 'tcx, M: CompileTimeMachine<'mir, 'tcx>>( // Pointer not found in local memory map. It is either a pointer to the global // map, or dangling. // If the pointer is dangling (neither in local nor global memory), we leave it - // to validation to error. The `delay_span_bug` ensures that we don't forget such - // a check in validation. + // to validation to error -- it has the much better error messages, pointing out where + // in the value the dangling reference lies. + // The `delay_span_bug` ensures that we don't forget such a check in validation. if tcx.get_global_alloc(alloc_id).is_none() { tcx.sess.delay_span_bug(ecx.tcx.span, "tried to intern dangling pointer"); } @@ -107,28 +108,28 @@ fn intern_shallow<'rt, 'mir, 'tcx, M: CompileTimeMachine<'mir, 'tcx>>( // Set allocation mutability as appropriate. This is used by LLVM to put things into // read-only memory, and also by Miri when evaluating other globals that // access this one. - if mode == InternMode::Static { - // When `ty` is `None`, we assume no interior mutability. + if let InternMode::Static(mutability) = mode { + // For this, we need to take into account `UnsafeCell`. When `ty` is `None`, we assume + // no interior mutability. let frozen = ty.map_or(true, |ty| ty.is_freeze(ecx.tcx.tcx, ecx.param_env, ecx.tcx.span)); // For statics, allocation mutability is the combination of the place mutability and // the type mutability. // The entire allocation needs to be mutable if it contains an `UnsafeCell` anywhere. - if mutability == Mutability::Not && frozen { + let immutable = mutability == Mutability::Not && frozen; + if immutable { alloc.mutability = Mutability::Not; } else { // Just making sure we are not "upgrading" an immutable allocation to mutable. assert_eq!(alloc.mutability, Mutability::Mut); } } else { - // We *could* be non-frozen at `ConstBase`, for constants like `Cell::new(0)`. - // But we still intern that as immutable as the memory cannot be changed once the - // initial value was computed. - // Constants are never mutable. - assert_eq!( - mutability, - Mutability::Not, - "Something went very wrong: mutability requested for a constant" - ); + // No matter what, *constants are never mutable*. Mutating them is UB. + // See const_eval::machine::MemoryExtra::can_access_statics for why + // immutability is so important. + + // There are no sensible checks we can do here; grep for `mutable_memory_in_const` to + // find the checks we are doing elsewhere to avoid even getting here for memory + // that "wants" to be mutable. alloc.mutability = Mutability::Not; }; // link the alloc id to the actual allocation @@ -142,10 +143,16 @@ impl<'rt, 'mir, 'tcx, M: CompileTimeMachine<'mir, 'tcx>> InternVisitor<'rt, 'mir fn intern_shallow( &mut self, alloc_id: AllocId, - mutability: Mutability, + mode: InternMode, ty: Option>, ) -> InterpResult<'tcx, Option> { - intern_shallow(self.ecx, self.leftover_allocations, self.mode, alloc_id, mutability, ty) + intern_shallow( + self.ecx, + self.leftover_allocations, + alloc_id, + mode, + ty, + ) } } @@ -166,22 +173,22 @@ impl<'rt, 'mir, 'tcx: 'mir, M: CompileTimeMachine<'mir, 'tcx>> ValueVisitor<'mir ) -> InterpResult<'tcx> { if let Some(def) = mplace.layout.ty.ty_adt_def() { if Some(def.did) == self.ecx.tcx.lang_items().unsafe_cell_type() { + if self.mode == InternMode::ConstInner && !self.ignore_interior_mut_in_const { + // We do not actually make this memory mutable. But in case the user + // *expected* it to be mutable, make sure we error. This is just a + // sanity check to prevent users from accidentally exploiting the UB + // they caused. It also helps us to find cases where const-checking + // failed to prevent an `UnsafeCell` (but as `ignore_interior_mut_in_const` + // shows that part is not airtight). + mutable_memory_in_const(self.ecx.tcx, "`UnsafeCell`"); + } // We are crossing over an `UnsafeCell`, we can mutate again. This means that // References we encounter inside here are interned as pointing to mutable // allocations. - let old = std::mem::replace(&mut self.mutability, Mutability::Mut); - if !self.ignore_interior_mut_in_const_validation { - assert_ne!( - self.mode, - InternMode::Const, - "UnsafeCells are not allowed behind references in constants. This should \ - have been prevented statically by const qualification. If this were \ - allowed one would be able to change a constant at one use site and other \ - use sites could observe that mutation.", - ); - } + // Remember the `old` value to handle nested `UnsafeCell`. + let old = std::mem::replace(&mut self.inside_unsafe_cell, true); let walked = self.walk_aggregate(mplace, fields); - self.mutability = old; + self.inside_unsafe_cell = old; return walked; } } @@ -191,23 +198,26 @@ impl<'rt, 'mir, 'tcx: 'mir, M: CompileTimeMachine<'mir, 'tcx>> ValueVisitor<'mir fn visit_value(&mut self, mplace: MPlaceTy<'tcx>) -> InterpResult<'tcx> { // Handle Reference types, as these are the only relocations supported by const eval. // Raw pointers (and boxes) are handled by the `leftover_relocations` logic. + let tcx = self.ecx.tcx; let ty = mplace.layout.ty; - if let ty::Ref(_, referenced_ty, mutability) = ty.kind { + if let ty::Ref(_, referenced_ty, ref_mutability) = ty.kind { let value = self.ecx.read_immediate(mplace.into())?; let mplace = self.ecx.ref_to_mplace(value)?; + assert_eq!(mplace.layout.ty, referenced_ty); // Handle trait object vtables. if let ty::Dynamic(..) = - self.ecx.tcx.struct_tail_erasing_lifetimes(referenced_ty, self.ecx.param_env).kind + tcx.struct_tail_erasing_lifetimes(referenced_ty, self.ecx.param_env).kind { - // Validation has already errored on an invalid vtable pointer so we can safely not - // do anything if this is not a real pointer. + // Validation will error (with a better message) on an invalid vtable pointer + // so we can safely not do anything if this is not a real pointer. if let Scalar::Ptr(vtable) = mplace.meta.unwrap_meta() { - // Explicitly choose `Immutable` here, since vtables are immutable, even + // Explicitly choose const mode here, since vtables are immutable, even // if the reference of the fat pointer is mutable. - self.intern_shallow(vtable.alloc_id, Mutability::Not, None)?; + self.intern_shallow(vtable.alloc_id, InternMode::ConstInner, None)?; } else { - self.ecx().tcx.sess.delay_span_bug( - rustc_span::DUMMY_SP, + // Let validation show the error message, but make sure it *does* error. + tcx.sess.delay_span_bug( + tcx.span, "vtables pointers cannot be integer pointers", ); } @@ -215,54 +225,66 @@ impl<'rt, 'mir, 'tcx: 'mir, M: CompileTimeMachine<'mir, 'tcx>> ValueVisitor<'mir // Check if we have encountered this pointer+layout combination before. // Only recurse for allocation-backed pointers. if let Scalar::Ptr(ptr) = mplace.ptr { - // We do not have any `frozen` logic here, because it's essentially equivalent to - // the mutability except for the outermost item. Only `UnsafeCell` can "unfreeze", - // and we check that in `visit_aggregate`. - // This is not an inherent limitation, but one that we know to be true, because - // const qualification enforces it. We can lift it in the future. - match (self.mode, mutability) { - // immutable references are fine everywhere - (_, hir::Mutability::Not) => {} - // all is "good and well" in the unsoundness of `static mut` + // Compute the mode with which we intern this. + let ref_mode = match self.mode { + InternMode::Static(mutbl) => { + // In statics, merge outer mutability with reference mutability and + // take into account whether we are in an `UnsafeCell`. - // mutable references are ok in `static`. Either they are treated as immutable - // because they are behind an immutable one, or they are behind an `UnsafeCell` - // and thus ok. - (InternMode::Static, hir::Mutability::Mut) => {} - // we statically prevent `&mut T` via `const_qualif` and double check this here - (InternMode::ConstBase | InternMode::Const, hir::Mutability::Mut) => { - match referenced_ty.kind { - ty::Array(_, n) - if n.eval_usize(self.ecx.tcx.tcx, self.ecx.param_env) == 0 => {} - ty::Slice(_) - if mplace.meta.unwrap_meta().to_machine_usize(self.ecx)? == 0 => {} - _ => bug!("const qualif failed to prevent mutable references"), + // The only way a mutable reference actually works as a mutable reference is + // by being in a `static mut` directly or behind another mutable reference. + // If there's an immutable reference or we are inside a `static`, then our + // mutable reference is equivalent to an immutable one. As an example: + // `&&mut Foo` is semantically equivalent to `&&Foo` + match ref_mutability { + _ if self.inside_unsafe_cell => { + // Inside an `UnsafeCell` is like inside a `static mut`, the "outer" + // mutability does not matter. + InternMode::Static(ref_mutability) + } + Mutability::Not => { + // A shared reference, things become immutable. + // We do *not* consier `freeze` here -- that is done more precisely + // when traversing the referenced data (by tracking `UnsafeCell`). + InternMode::Static(Mutability::Not) + } + Mutability::Mut => { + // Mutable reference. + InternMode::Static(mutbl) + } } } - } - // Compute the mutability with which we'll start visiting the allocation. This is - // what gets changed when we encounter an `UnsafeCell`. - // - // The only way a mutable reference actually works as a mutable reference is - // by being in a `static mut` directly or behind another mutable reference. - // If there's an immutable reference or we are inside a static, then our - // mutable reference is equivalent to an immutable one. As an example: - // `&&mut Foo` is semantically equivalent to `&&Foo` - let mutability = self.mutability.and(mutability); - // Recursing behind references changes the intern mode for constants in order to - // cause assertions to trigger if we encounter any `UnsafeCell`s. - let mode = match self.mode { - InternMode::ConstBase => InternMode::Const, - other => other, + InternMode::ConstBase | InternMode::ConstInner => { + // Ignore `UnsafeCell`, everything is immutable. Do some sanity checking + // for mutable references that we encounter -- they must all be ZST. + // This helps to prevent users from accidentally exploiting UB that they + // caused (by somehow getting a mutable reference in a `const`). + if ref_mutability == Mutability::Mut { + match referenced_ty.kind { + ty::Array(_, n) + if n.eval_usize(tcx.tcx, self.ecx.param_env) == 0 => {} + ty::Slice(_) + if mplace.meta.unwrap_meta().to_machine_usize(self.ecx)? == 0 => {} + _ => mutable_memory_in_const(tcx, "`&mut`"), + } + } else { + // A shared reference. We cannot check `freeze` here due to references + // like `&dyn Trait` that are actually immutable. We do check for + // concrete `UnsafeCell` when traversing the pointee though (if it is + // a new allocation, not yet interned). + } + // Go on with the "inner" rules. + InternMode::ConstInner + } }; - match self.intern_shallow(ptr.alloc_id, mutability, Some(mplace.layout.ty))? { + match self.intern_shallow(ptr.alloc_id, ref_mode, Some(referenced_ty))? { // No need to recurse, these are interned already and statics may have // cycles, so we don't want to recurse there Some(IsStaticOrFn) => {} // intern everything referenced by this value. The mutability is taken from the // reference. It is checked above that mutable references only happen in // `static mut` - None => self.ref_tracking.track((mplace, mutability, mode), || ()), + None => self.ref_tracking.track((mplace, ref_mode), || ()), } } Ok(()) @@ -273,6 +295,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: CompileTimeMachine<'mir, 'tcx>> ValueVisitor<'mir } } +#[derive(Copy, Clone, Debug, PartialEq, Hash, Eq)] pub enum InternKind { /// The `mutability` of the static, ignoring the type which may have interior mutability. Static(hir::Mutability), @@ -285,48 +308,48 @@ pub fn intern_const_alloc_recursive>( ecx: &mut InterpCx<'mir, 'tcx, M>, intern_kind: InternKind, ret: MPlaceTy<'tcx>, - ignore_interior_mut_in_const_validation: bool, + ignore_interior_mut_in_const: bool, ) -> InterpResult<'tcx> where 'tcx: 'mir, { let tcx = ecx.tcx; - let (base_mutability, base_intern_mode) = match intern_kind { - // `static mut` doesn't care about interior mutability, it's mutable anyway - InternKind::Static(mutbl) => (mutbl, InternMode::Static), + let base_intern_mode = match intern_kind { + InternKind::Static(mutbl) => InternMode::Static(mutbl), // FIXME: what about array lengths, array initializers? - InternKind::Constant | InternKind::ConstProp => (Mutability::Not, InternMode::ConstBase), - InternKind::Promoted => (Mutability::Not, InternMode::ConstBase), + InternKind::Constant | InternKind::ConstProp | InternKind::Promoted => + InternMode::ConstBase, }; // Type based interning. - // `ref_tracking` tracks typed references we have seen and still need to crawl for + // `ref_tracking` tracks typed references we have already interned and still need to crawl for // more typed information inside them. // `leftover_allocations` collects *all* allocations we see, because some might not // be available in a typed way. They get interned at the end. - let mut ref_tracking = RefTracking::new((ret, base_mutability, base_intern_mode)); + let mut ref_tracking = RefTracking::empty(); let leftover_allocations = &mut FxHashSet::default(); // start with the outermost allocation intern_shallow( ecx, leftover_allocations, - base_intern_mode, // The outermost allocation must exist, because we allocated it with // `Memory::allocate`. ret.ptr.assert_ptr().alloc_id, - base_mutability, + base_intern_mode, Some(ret.layout.ty), )?; - while let Some(((mplace, mutability, mode), _)) = ref_tracking.todo.pop() { + ref_tracking.track((ret, base_intern_mode), || ()); + + while let Some(((mplace, mode), _)) = ref_tracking.todo.pop() { let interned = InternVisitor { ref_tracking: &mut ref_tracking, ecx, mode, leftover_allocations, - mutability, - ignore_interior_mut_in_const_validation, + ignore_interior_mut_in_const, + inside_unsafe_cell: false, } .visit_value(mplace); if let Err(error) = interned { @@ -366,26 +389,28 @@ where InternKind::Static(_) => {} // Raw pointers in promoteds may only point to immutable things so we mark // everything as immutable. - // It is UB to mutate through a raw pointer obtained via an immutable reference. + // It is UB to mutate through a raw pointer obtained via an immutable reference: // Since all references and pointers inside a promoted must by their very definition // be created from an immutable reference (and promotion also excludes interior // mutability), mutating through them would be UB. // There's no way we can check whether the user is using raw pointers correctly, // so all we can do is mark this as immutable here. InternKind::Promoted => { + // See const_eval::machine::MemoryExtra::can_access_statics for why + // immutability is so important. alloc.mutability = Mutability::Not; } InternKind::Constant | InternKind::ConstProp => { - // If it's a constant, it *must* be immutable. - // We cannot have mutable memory inside a constant. - // We use `delay_span_bug` here, because this can be reached in the presence - // of fancy transmutes. - if alloc.mutability == Mutability::Mut { - // For better errors later, mark the allocation as immutable - // (on top of the delayed ICE). - alloc.mutability = Mutability::Not; - ecx.tcx.sess.delay_span_bug(ecx.tcx.span, "mutable allocation in constant"); - } + // If it's a constant, we should not have any "leftovers" as everything + // is tracked by const-checking. + // FIXME: downgrade this to a warning? It rejects some legitimate consts, + // such as `const CONST_RAW: *const Vec = &Vec::new() as *const _;`. + ecx.tcx.sess.span_err( + ecx.tcx.span, + "untyped pointers are not allowed in constant", + ); + // For better errors later, mark the allocation as immutable. + alloc.mutability = Mutability::Not; } } let alloc = tcx.intern_const_alloc(alloc); diff --git a/src/test/ui/consts/miri_unleashed/mutable_const.rs b/src/test/ui/consts/miri_unleashed/mutable_const.rs deleted file mode 100644 index f8aa65282738..000000000000 --- a/src/test/ui/consts/miri_unleashed/mutable_const.rs +++ /dev/null @@ -1,25 +0,0 @@ -// compile-flags: -Zunleash-the-miri-inside-of-you -// normalize-stderr-test "alloc[0-9]+" -> "allocN" - -#![deny(const_err)] // The `allow` variant is tested by `mutable_const2`. -//~^ NOTE lint level -// Here we check that even though `MUTABLE_BEHIND_RAW` is created from a mutable -// allocation, we intern that allocation as *immutable* and reject writes to it. -// We avoid the `delay_span_bug` ICE by having compilation fail via the `deny` above. - -use std::cell::UnsafeCell; - -// make sure we do not just intern this as mutable -const MUTABLE_BEHIND_RAW: *mut i32 = &UnsafeCell::new(42) as *const _ as *mut _; - -const MUTATING_BEHIND_RAW: () = { //~ NOTE - // Test that `MUTABLE_BEHIND_RAW` is actually immutable, by doing this at const time. - unsafe { - *MUTABLE_BEHIND_RAW = 99 //~ ERROR any use of this value will cause an error - //~^ NOTE: which is read-only - // FIXME would be good to match more of the error message here, but looks like we - // normalize *after* checking the annoations here. - } -}; - -fn main() {} diff --git a/src/test/ui/consts/miri_unleashed/mutable_const.stderr b/src/test/ui/consts/miri_unleashed/mutable_const.stderr deleted file mode 100644 index 4772baf9d9a0..000000000000 --- a/src/test/ui/consts/miri_unleashed/mutable_const.stderr +++ /dev/null @@ -1,39 +0,0 @@ -error: any use of this value will cause an error - --> $DIR/mutable_const.rs:18:9 - | -LL | / const MUTATING_BEHIND_RAW: () = { -LL | | // Test that `MUTABLE_BEHIND_RAW` is actually immutable, by doing this at const time. -LL | | unsafe { -LL | | *MUTABLE_BEHIND_RAW = 99 - | | ^^^^^^^^^^^^^^^^^^^^^^^^ writing to allocN which is read-only -... | -LL | | } -LL | | }; - | |__- - | -note: the lint level is defined here - --> $DIR/mutable_const.rs:4:9 - | -LL | #![deny(const_err)] // The `allow` variant is tested by `mutable_const2`. - | ^^^^^^^^^ - -warning: skipping const checks - | -help: skipping check that does not even have a feature gate - --> $DIR/mutable_const.rs:13:38 - | -LL | const MUTABLE_BEHIND_RAW: *mut i32 = &UnsafeCell::new(42) as *const _ as *mut _; - | ^^^^^^^^^^^^^^^^^^^^ -help: skipping check for `const_raw_ptr_deref` feature - --> $DIR/mutable_const.rs:18:9 - | -LL | *MUTABLE_BEHIND_RAW = 99 - | ^^^^^^^^^^^^^^^^^^^^^^^^ -help: skipping check for `const_mut_refs` feature - --> $DIR/mutable_const.rs:18:9 - | -LL | *MUTABLE_BEHIND_RAW = 99 - | ^^^^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to previous error; 1 warning emitted - diff --git a/src/test/ui/consts/miri_unleashed/mutable_const2.rs b/src/test/ui/consts/miri_unleashed/mutable_const2.rs deleted file mode 100644 index 867091af7ba7..000000000000 --- a/src/test/ui/consts/miri_unleashed/mutable_const2.rs +++ /dev/null @@ -1,16 +0,0 @@ -// compile-flags: -Zunleash-the-miri-inside-of-you -// failure-status: 101 -// rustc-env:RUST_BACKTRACE=0 -// normalize-stderr-test "note: rustc 1.* running on .*" -> "note: rustc VERSION running on TARGET" -// normalize-stderr-test "note: compiler flags: .*" -> "note: compiler flags: FLAGS" -// normalize-stderr-test "interpret/intern.rs:[0-9]+:[0-9]+" -> "interpret/intern.rs:LL:CC" - -#![allow(const_err)] - -use std::cell::UnsafeCell; - -// make sure we do not just intern this as mutable -const MUTABLE_BEHIND_RAW: *mut i32 = &UnsafeCell::new(42) as *const _ as *mut _; -//~^ ERROR: mutable allocation in constant - -fn main() {} diff --git a/src/test/ui/consts/miri_unleashed/mutable_const2.stderr b/src/test/ui/consts/miri_unleashed/mutable_const2.stderr deleted file mode 100644 index 98a1c8bdd896..000000000000 --- a/src/test/ui/consts/miri_unleashed/mutable_const2.stderr +++ /dev/null @@ -1,29 +0,0 @@ -warning: skipping const checks - | -help: skipping check that does not even have a feature gate - --> $DIR/mutable_const2.rs:13:38 - | -LL | const MUTABLE_BEHIND_RAW: *mut i32 = &UnsafeCell::new(42) as *const _ as *mut _; - | ^^^^^^^^^^^^^^^^^^^^ - -warning: 1 warning emitted - -error: internal compiler error: mutable allocation in constant - --> $DIR/mutable_const2.rs:13:1 - | -LL | const MUTABLE_BEHIND_RAW: *mut i32 = &UnsafeCell::new(42) as *const _ as *mut _; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -thread 'rustc' panicked at 'no errors encountered even though `delay_span_bug` issued', src/librustc_errors/lib.rs:366:17 -note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace - -error: internal compiler error: unexpected panic - -note: the compiler unexpectedly panicked. this is a bug. - -note: we would appreciate a bug report: https://github.com/rust-lang/rust/blob/master/CONTRIBUTING.md#bug-reports - -note: rustc VERSION running on TARGET - -note: compiler flags: FLAGS - diff --git a/src/test/ui/consts/miri_unleashed/mutable_references.rs b/src/test/ui/consts/miri_unleashed/mutable_references.rs index ed2ca86ba2c6..ca927ef4a518 100644 --- a/src/test/ui/consts/miri_unleashed/mutable_references.rs +++ b/src/test/ui/consts/miri_unleashed/mutable_references.rs @@ -17,12 +17,11 @@ struct Foo(T); // this is fine for the same reason as `BAR`. static BOO: &mut Foo<()> = &mut Foo(()); +// interior mutability is fine struct Meh { x: &'static UnsafeCell, } - unsafe impl Sync for Meh {} - static MEH: Meh = Meh { x: &UnsafeCell::new(42), }; diff --git a/src/test/ui/consts/miri_unleashed/mutable_references.stderr b/src/test/ui/consts/miri_unleashed/mutable_references.stderr index 83c4e0ceba0d..7109ffd8b61d 100644 --- a/src/test/ui/consts/miri_unleashed/mutable_references.stderr +++ b/src/test/ui/consts/miri_unleashed/mutable_references.stderr @@ -1,5 +1,5 @@ error[E0594]: cannot assign to `*OH_YES`, as `OH_YES` is an immutable static item - --> $DIR/mutable_references.rs:37:5 + --> $DIR/mutable_references.rs:36:5 | LL | *OH_YES = 99; | ^^^^^^^^^^^^ cannot assign @@ -22,12 +22,12 @@ help: skipping check for `const_mut_refs` feature LL | static BOO: &mut Foo<()> = &mut Foo(()); | ^^^^^^^^^^^^ help: skipping check that does not even have a feature gate - --> $DIR/mutable_references.rs:27:8 + --> $DIR/mutable_references.rs:26:8 | LL | x: &UnsafeCell::new(42), | ^^^^^^^^^^^^^^^^^^^^ help: skipping check for `const_mut_refs` feature - --> $DIR/mutable_references.rs:31:27 + --> $DIR/mutable_references.rs:30:27 | LL | static OH_YES: &mut i32 = &mut 42; | ^^^^^^^ diff --git a/src/test/ui/consts/miri_unleashed/mutable_references_err.rs b/src/test/ui/consts/miri_unleashed/mutable_references_err.rs new file mode 100644 index 000000000000..5014a601390d --- /dev/null +++ b/src/test/ui/consts/miri_unleashed/mutable_references_err.rs @@ -0,0 +1,37 @@ +// compile-flags: -Zunleash-the-miri-inside-of-you + +#![allow(const_err)] + +use std::cell::UnsafeCell; + +// this test ICEs to ensure that our mutability story is sound + +struct Meh { + x: &'static UnsafeCell, +} +unsafe impl Sync for Meh {} + +// the following will never be ok! no interior mut behind consts, because +// all allocs interned here will be marked immutable. +const MUH: Meh = Meh { //~ ERROR: mutable memory (`UnsafeCell`) is not allowed in constant + x: &UnsafeCell::new(42), +}; + +struct Synced { + x: UnsafeCell, +} +unsafe impl Sync for Synced {} + +// Make sure we also catch this behind a type-erased `dyn Trait` reference. +const SNEAKY: &dyn Sync = &Synced { x: UnsafeCell::new(42) }; +//~^ ERROR: mutable memory (`UnsafeCell`) is not allowed in constant + +// Make sure we also catch mutable references. +const BLUNT: &mut i32 = &mut 42; +//~^ ERROR: mutable memory (`&mut`) is not allowed in constant + +fn main() { + unsafe { + *MUH.x.get() = 99; + } +} diff --git a/src/test/ui/consts/miri_unleashed/mutable_references_err.stderr b/src/test/ui/consts/miri_unleashed/mutable_references_err.stderr new file mode 100644 index 000000000000..45e7d5a2cc3b --- /dev/null +++ b/src/test/ui/consts/miri_unleashed/mutable_references_err.stderr @@ -0,0 +1,40 @@ +error: mutable memory (`UnsafeCell`) is not allowed in constant + --> $DIR/mutable_references_err.rs:16:1 + | +LL | / const MUH: Meh = Meh { +LL | | x: &UnsafeCell::new(42), +LL | | }; + | |__^ + +error: mutable memory (`UnsafeCell`) is not allowed in constant + --> $DIR/mutable_references_err.rs:26:1 + | +LL | const SNEAKY: &dyn Sync = &Synced { x: UnsafeCell::new(42) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: mutable memory (`&mut`) is not allowed in constant + --> $DIR/mutable_references_err.rs:30:1 + | +LL | const BLUNT: &mut i32 = &mut 42; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: skipping const checks + | +help: skipping check that does not even have a feature gate + --> $DIR/mutable_references_err.rs:17:8 + | +LL | x: &UnsafeCell::new(42), + | ^^^^^^^^^^^^^^^^^^^^ +help: skipping check that does not even have a feature gate + --> $DIR/mutable_references_err.rs:26:27 + | +LL | const SNEAKY: &dyn Sync = &Synced { x: UnsafeCell::new(42) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: skipping check for `const_mut_refs` feature + --> $DIR/mutable_references_err.rs:30:25 + | +LL | const BLUNT: &mut i32 = &mut 42; + | ^^^^^^^ + +error: aborting due to 3 previous errors; 1 warning emitted + diff --git a/src/test/ui/consts/miri_unleashed/mutable_references_ice.rs b/src/test/ui/consts/miri_unleashed/mutable_references_ice.rs deleted file mode 100644 index 7388aad2a9e5..000000000000 --- a/src/test/ui/consts/miri_unleashed/mutable_references_ice.rs +++ /dev/null @@ -1,29 +0,0 @@ -// compile-flags: -Zunleash-the-miri-inside-of-you -// failure-status: 101 -// rustc-env:RUST_BACKTRACE=0 -// normalize-stderr-test "note: rustc 1.* running on .*" -> "note: rustc VERSION running on TARGET" -// normalize-stderr-test "note: compiler flags: .*" -> "note: compiler flags: FLAGS" -// normalize-stderr-test "interpret/intern.rs:[0-9]+:[0-9]+" -> "interpret/intern.rs:LL:CC" - -#![allow(const_err)] - -use std::cell::UnsafeCell; - -// this test ICEs to ensure that our mutability story is sound - -struct Meh { - x: &'static UnsafeCell, -} - -unsafe impl Sync for Meh {} - -// the following will never be ok! -const MUH: Meh = Meh { - x: &UnsafeCell::new(42), -}; - -fn main() { - unsafe { - *MUH.x.get() = 99; - } -} diff --git a/src/test/ui/consts/miri_unleashed/mutable_references_ice.stderr b/src/test/ui/consts/miri_unleashed/mutable_references_ice.stderr deleted file mode 100644 index 7ddf77af4d3a..000000000000 --- a/src/test/ui/consts/miri_unleashed/mutable_references_ice.stderr +++ /dev/null @@ -1,25 +0,0 @@ -thread 'rustc' panicked at 'assertion failed: `(left != right)` - left: `Const`, - right: `Const`: UnsafeCells are not allowed behind references in constants. This should have been prevented statically by const qualification. If this were allowed one would be able to change a constant at one use site and other use sites could observe that mutation.', src/librustc_mir/interpret/intern.rs:LL:CC -note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace - -error: internal compiler error: unexpected panic - -note: the compiler unexpectedly panicked. this is a bug. - -note: we would appreciate a bug report: https://github.com/rust-lang/rust/blob/master/CONTRIBUTING.md#bug-reports - -note: rustc VERSION running on TARGET - -note: compiler flags: FLAGS - -warning: skipping const checks - | -help: skipping check that does not even have a feature gate - --> $DIR/mutable_references_ice.rs:22:8 - | -LL | x: &UnsafeCell::new(42), - | ^^^^^^^^^^^^^^^^^^^^ - -warning: 1 warning emitted - diff --git a/src/test/ui/consts/miri_unleashed/raw_mutable_const.rs b/src/test/ui/consts/miri_unleashed/raw_mutable_const.rs new file mode 100644 index 000000000000..3d200e231733 --- /dev/null +++ b/src/test/ui/consts/miri_unleashed/raw_mutable_const.rs @@ -0,0 +1,12 @@ +// compile-flags: -Zunleash-the-miri-inside-of-you + +#![feature(const_raw_ptr_deref)] +#![feature(const_mut_refs)] +#![allow(const_err)] + +use std::cell::UnsafeCell; + +const MUTABLE_BEHIND_RAW: *mut i32 = &UnsafeCell::new(42) as *const _ as *mut _; +//~^ ERROR: untyped pointers are not allowed in constant + +fn main() {} diff --git a/src/test/ui/consts/miri_unleashed/raw_mutable_const.stderr b/src/test/ui/consts/miri_unleashed/raw_mutable_const.stderr new file mode 100644 index 000000000000..c6dbf086ec0e --- /dev/null +++ b/src/test/ui/consts/miri_unleashed/raw_mutable_const.stderr @@ -0,0 +1,16 @@ +error: untyped pointers are not allowed in constant + --> $DIR/raw_mutable_const.rs:9:1 + | +LL | const MUTABLE_BEHIND_RAW: *mut i32 = &UnsafeCell::new(42) as *const _ as *mut _; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: skipping const checks + | +help: skipping check that does not even have a feature gate + --> $DIR/raw_mutable_const.rs:9:38 + | +LL | const MUTABLE_BEHIND_RAW: *mut i32 = &UnsafeCell::new(42) as *const _ as *mut _; + | ^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error; 1 warning emitted + diff --git a/src/test/ui/consts/raw-ptr-const.rs b/src/test/ui/consts/raw-ptr-const.rs new file mode 100644 index 000000000000..00fad046b557 --- /dev/null +++ b/src/test/ui/consts/raw-ptr-const.rs @@ -0,0 +1,10 @@ +#![allow(const_err)] // make sure we hit the `delay_span_bug` + +// This is a regression test for a `delay_span_bug` during interning when a constant +// evaluates to a (non-dangling) raw pointer. For now this errors; potentially it +// could also be allowed. + +const CONST_RAW: *const Vec = &Vec::new() as *const _; +//~^ ERROR untyped pointers are not allowed in constant + +fn main() {} diff --git a/src/test/ui/consts/raw-ptr-const.stderr b/src/test/ui/consts/raw-ptr-const.stderr new file mode 100644 index 000000000000..974b1c3ff45b --- /dev/null +++ b/src/test/ui/consts/raw-ptr-const.stderr @@ -0,0 +1,8 @@ +error: untyped pointers are not allowed in constant + --> $DIR/raw-ptr-const.rs:7:1 + | +LL | const CONST_RAW: *const Vec = &Vec::new() as *const _; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to previous error + From 8e48a304dc1aa87bfed8f8e8c137477efc64cfd0 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 29 Apr 2020 10:14:57 +0200 Subject: [PATCH 087/203] remove some dead code, and assert we do not swallow allocating errors --- src/librustc_mir/interpret/intern.rs | 37 ++++++++++++++-------------- 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/src/librustc_mir/interpret/intern.rs b/src/librustc_mir/interpret/intern.rs index c9661c92d2e2..7b42d7ab6e81 100644 --- a/src/librustc_mir/interpret/intern.rs +++ b/src/librustc_mir/interpret/intern.rs @@ -343,7 +343,7 @@ where ref_tracking.track((ret, base_intern_mode), || ()); while let Some(((mplace, mode), _)) = ref_tracking.todo.pop() { - let interned = InternVisitor { + let res = InternVisitor { ref_tracking: &mut ref_tracking, ecx, mode, @@ -352,23 +352,24 @@ where inside_unsafe_cell: false, } .visit_value(mplace); - if let Err(error) = interned { - // This can happen when e.g. the tag of an enum is not a valid discriminant. We do have - // to read enum discriminants in order to find references in enum variant fields. - if let err_ub!(ValidationFailure(_)) = error.kind { - let err = crate::const_eval::error_to_const_error(&ecx, error); - match err.struct_error( - ecx.tcx, - "it is undefined behavior to use this value", - |mut diag| { - diag.note(crate::const_eval::note_on_undefined_behavior_error()); - diag.emit(); - }, - ) { - ErrorHandled::TooGeneric - | ErrorHandled::Reported(ErrorReported) - | ErrorHandled::Linted => {} - } + // We deliberately *ignore* interpreter errors here. When there is a problem, the remaining + // references are "leftover"-interned, and later validation will show a proper error + // and point at the right part of the value causing the problem. + match res { + Ok(()) => {}, + Err(error) => { + ecx.tcx.sess.delay_span_bug( + ecx.tcx.span, + "error during interning should later cause validation failure", + ); + // Some errors shouldn't come up because creating them causes + // an allocation, which we should avoid. When that happens, + // dedicated error variants should be introduced instead. + assert!( + !error.kind.allocates(), + "interning encountered allocating error: {}", + error + ); } } } From ff39457364659e485991fdb0f145858ff2fb016f Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 29 Apr 2020 12:34:51 +0200 Subject: [PATCH 088/203] avoid raising interpreter errors from interning --- src/librustc_mir/const_eval/eval_queries.rs | 2 +- src/librustc_mir/const_eval/mod.rs | 2 +- src/librustc_mir/interpret/intern.rs | 39 ++++++++++++------- src/librustc_mir/transform/const_prop.rs | 3 +- src/test/ui/consts/dangling-alloc-id-ice.rs | 4 +- .../ui/consts/dangling-alloc-id-ice.stderr | 22 ++++++++--- src/test/ui/consts/dangling_raw_ptr.rs | 2 +- src/test/ui/consts/dangling_raw_ptr.stderr | 6 +-- 8 files changed, 50 insertions(+), 30 deletions(-) diff --git a/src/librustc_mir/const_eval/eval_queries.rs b/src/librustc_mir/const_eval/eval_queries.rs index b6c635fb22ab..0637ebf959e5 100644 --- a/src/librustc_mir/const_eval/eval_queries.rs +++ b/src/librustc_mir/const_eval/eval_queries.rs @@ -66,7 +66,7 @@ fn eval_body_using_ecx<'mir, 'tcx>( intern_kind, ret, body.ignore_interior_mut_in_const_validation, - )?; + ); debug!("eval_body_using_ecx done: {:?}", *ret); Ok(ret) diff --git a/src/librustc_mir/const_eval/mod.rs b/src/librustc_mir/const_eval/mod.rs index e1146ef30d13..7f557e340bbc 100644 --- a/src/librustc_mir/const_eval/mod.rs +++ b/src/librustc_mir/const_eval/mod.rs @@ -53,7 +53,7 @@ pub(crate) fn const_caller_location( let mut ecx = mk_eval_cx(tcx, DUMMY_SP, ty::ParamEnv::reveal_all(), false); let loc_place = ecx.alloc_caller_location(file, line, col); - intern_const_alloc_recursive(&mut ecx, InternKind::Constant, loc_place, false).unwrap(); + intern_const_alloc_recursive(&mut ecx, InternKind::Constant, loc_place, false); ConstValue::Scalar(loc_place.ptr) } diff --git a/src/librustc_mir/interpret/intern.rs b/src/librustc_mir/interpret/intern.rs index 7b42d7ab6e81..4caf2caa8cc3 100644 --- a/src/librustc_mir/interpret/intern.rs +++ b/src/librustc_mir/interpret/intern.rs @@ -5,9 +5,8 @@ use super::validity::RefTracking; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; -use rustc_errors::ErrorReported; use rustc_hir as hir; -use rustc_middle::mir::interpret::{ErrorHandled, InterpResult}; +use rustc_middle::mir::interpret::InterpResult; use rustc_middle::ty::{self, query::TyCtxtAt, Ty}; use rustc_ast::ast::Mutability; @@ -64,6 +63,7 @@ enum InternMode { struct IsStaticOrFn; fn mutable_memory_in_const(tcx: TyCtxtAt<'_>, kind: &str) { + // FIXME: show this in validation instead so we can point at where in the value the error is? tcx.sess.span_err(tcx.span, &format!("mutable memory ({}) is not allowed in constant", kind)); } @@ -79,7 +79,7 @@ fn intern_shallow<'rt, 'mir, 'tcx, M: CompileTimeMachine<'mir, 'tcx>>( alloc_id: AllocId, mode: InternMode, ty: Option>, -) -> InterpResult<'tcx, Option> { +) -> Option { trace!("intern_shallow {:?} with {:?}", alloc_id, mode); // remove allocation let tcx = ecx.tcx; @@ -97,7 +97,7 @@ fn intern_shallow<'rt, 'mir, 'tcx, M: CompileTimeMachine<'mir, 'tcx>>( } // treat dangling pointers like other statics // just to stop trying to recurse into them - return Ok(Some(IsStaticOrFn)); + return Some(IsStaticOrFn); } }; // This match is just a canary for future changes to `MemoryKind`, which most likely need @@ -136,7 +136,7 @@ fn intern_shallow<'rt, 'mir, 'tcx, M: CompileTimeMachine<'mir, 'tcx>>( let alloc = tcx.intern_const_alloc(alloc); leftover_allocations.extend(alloc.relocations().iter().map(|&(_, ((), reloc))| reloc)); tcx.set_alloc_id_memory(alloc_id, alloc); - Ok(None) + None } impl<'rt, 'mir, 'tcx, M: CompileTimeMachine<'mir, 'tcx>> InternVisitor<'rt, 'mir, 'tcx, M> { @@ -145,7 +145,7 @@ impl<'rt, 'mir, 'tcx, M: CompileTimeMachine<'mir, 'tcx>> InternVisitor<'rt, 'mir alloc_id: AllocId, mode: InternMode, ty: Option>, - ) -> InterpResult<'tcx, Option> { + ) -> Option { intern_shallow( self.ecx, self.leftover_allocations, @@ -213,7 +213,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: CompileTimeMachine<'mir, 'tcx>> ValueVisitor<'mir if let Scalar::Ptr(vtable) = mplace.meta.unwrap_meta() { // Explicitly choose const mode here, since vtables are immutable, even // if the reference of the fat pointer is mutable. - self.intern_shallow(vtable.alloc_id, InternMode::ConstInner, None)?; + self.intern_shallow(vtable.alloc_id, InternMode::ConstInner, None); } else { // Let validation show the error message, but make sure it *does* error. tcx.sess.delay_span_bug( @@ -277,7 +277,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: CompileTimeMachine<'mir, 'tcx>> ValueVisitor<'mir InternMode::ConstInner } }; - match self.intern_shallow(ptr.alloc_id, ref_mode, Some(referenced_ty))? { + match self.intern_shallow(ptr.alloc_id, ref_mode, Some(referenced_ty)) { // No need to recurse, these are interned already and statics may have // cycles, so we don't want to recurse there Some(IsStaticOrFn) => {} @@ -304,12 +304,18 @@ pub enum InternKind { ConstProp, } +/// Intern `ret` and everything it references. +/// +/// This *cannot raise an interpreter error*. Doing so is left to validation, which +/// trakcs where in the value we are and thus can show much better error messages. +/// Any errors here would anyway be turned into `const_err` lints, whereas validation failures +/// are hard errors. pub fn intern_const_alloc_recursive>( ecx: &mut InterpCx<'mir, 'tcx, M>, intern_kind: InternKind, ret: MPlaceTy<'tcx>, ignore_interior_mut_in_const: bool, -) -> InterpResult<'tcx> +) where 'tcx: 'mir, { @@ -338,7 +344,7 @@ where ret.ptr.assert_ptr().alloc_id, base_intern_mode, Some(ret.layout.ty), - )?; + ); ref_tracking.track((ret, base_intern_mode), || ()); @@ -422,13 +428,16 @@ where } } } else if ecx.memory.dead_alloc_map.contains_key(&alloc_id) { - // dangling pointer - throw_ub_format!("encountered dangling pointer in final constant") + // Codegen does not like dangling pointers, and generally `tcx` assumes that + // all allocations referenced anywhere actually exist. So, make sure we error here. + ecx.tcx.sess.span_err( + ecx.tcx.span, + "encountered dangling pointer in final constant", + ); } else if ecx.tcx.get_global_alloc(alloc_id).is_none() { - // We have hit an `AllocId` that is neither in local or global memory and isn't marked - // as dangling by local memory. + // We have hit an `AllocId` that is neither in local or global memory and isn't + // marked as dangling by local memory. That should be impossible. span_bug!(ecx.tcx.span, "encountered unknown alloc id {:?}", alloc_id); } } - Ok(()) } diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index 4be95b69850d..81de8dcece68 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -702,8 +702,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { )) => l.is_bits() && r.is_bits(), interpret::Operand::Indirect(_) if mir_opt_level >= 2 => { let mplace = op.assert_mem_place(&self.ecx); - intern_const_alloc_recursive(&mut self.ecx, InternKind::ConstProp, mplace, false) - .expect("failed to intern alloc"); + intern_const_alloc_recursive(&mut self.ecx, InternKind::ConstProp, mplace, false); true } _ => false, diff --git a/src/test/ui/consts/dangling-alloc-id-ice.rs b/src/test/ui/consts/dangling-alloc-id-ice.rs index dbc50f1fbd4b..3b7f1de5b9be 100644 --- a/src/test/ui/consts/dangling-alloc-id-ice.rs +++ b/src/test/ui/consts/dangling-alloc-id-ice.rs @@ -1,11 +1,13 @@ // https://github.com/rust-lang/rust/issues/55223 +#![allow(const_err)] union Foo<'a> { y: &'a (), long_live_the_unit: &'static (), } -const FOO: &() = { //~ ERROR any use of this value will cause an error +const FOO: &() = { //~ ERROR it is undefined behavior to use this value +//~^ ERROR encountered dangling pointer in final constant let y = (); unsafe { Foo { y: &y }.long_live_the_unit } }; diff --git a/src/test/ui/consts/dangling-alloc-id-ice.stderr b/src/test/ui/consts/dangling-alloc-id-ice.stderr index 0e213555052c..14a49810b9de 100644 --- a/src/test/ui/consts/dangling-alloc-id-ice.stderr +++ b/src/test/ui/consts/dangling-alloc-id-ice.stderr @@ -1,13 +1,25 @@ -error: any use of this value will cause an error - --> $DIR/dangling-alloc-id-ice.rs:8:1 +error: encountered dangling pointer in final constant + --> $DIR/dangling-alloc-id-ice.rs:9:1 | LL | / const FOO: &() = { +LL | | LL | | let y = (); LL | | unsafe { Foo { y: &y }.long_live_the_unit } LL | | }; - | |__^ encountered dangling pointer in final constant + | |__^ + +error[E0080]: it is undefined behavior to use this value + --> $DIR/dangling-alloc-id-ice.rs:9:1 | - = note: `#[deny(const_err)]` on by default +LL | / const FOO: &() = { +LL | | +LL | | let y = (); +LL | | unsafe { Foo { y: &y }.long_live_the_unit } +LL | | }; + | |__^ type validation failed: encountered a dangling reference (use-after-free) + | + = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. -error: aborting due to previous error +error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0080`. diff --git a/src/test/ui/consts/dangling_raw_ptr.rs b/src/test/ui/consts/dangling_raw_ptr.rs index c2d8e6d421a2..ddd1fb1ba76e 100644 --- a/src/test/ui/consts/dangling_raw_ptr.rs +++ b/src/test/ui/consts/dangling_raw_ptr.rs @@ -1,4 +1,4 @@ -const FOO: *const u32 = { //~ ERROR any use of this value will cause an error +const FOO: *const u32 = { //~ ERROR encountered dangling pointer in final constant let x = 42; &x }; diff --git a/src/test/ui/consts/dangling_raw_ptr.stderr b/src/test/ui/consts/dangling_raw_ptr.stderr index 4d4c2876c459..a79ac62d5cdb 100644 --- a/src/test/ui/consts/dangling_raw_ptr.stderr +++ b/src/test/ui/consts/dangling_raw_ptr.stderr @@ -1,13 +1,11 @@ -error: any use of this value will cause an error +error: encountered dangling pointer in final constant --> $DIR/dangling_raw_ptr.rs:1:1 | LL | / const FOO: *const u32 = { LL | | let x = 42; LL | | &x LL | | }; - | |__^ encountered dangling pointer in final constant - | - = note: `#[deny(const_err)]` on by default + | |__^ error: aborting due to previous error From d3b2e1fb9ed93575c9780e63f29a28d478b36c2b Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 29 Apr 2020 14:02:41 +0200 Subject: [PATCH 089/203] fmt --- src/librustc_mir/interpret/intern.rs | 43 +++++++++++----------------- 1 file changed, 16 insertions(+), 27 deletions(-) diff --git a/src/librustc_mir/interpret/intern.rs b/src/librustc_mir/interpret/intern.rs index 4caf2caa8cc3..8ce2cabed5dd 100644 --- a/src/librustc_mir/interpret/intern.rs +++ b/src/librustc_mir/interpret/intern.rs @@ -146,13 +146,7 @@ impl<'rt, 'mir, 'tcx, M: CompileTimeMachine<'mir, 'tcx>> InternVisitor<'rt, 'mir mode: InternMode, ty: Option>, ) -> Option { - intern_shallow( - self.ecx, - self.leftover_allocations, - alloc_id, - mode, - ty, - ) + intern_shallow(self.ecx, self.leftover_allocations, alloc_id, mode, ty) } } @@ -216,10 +210,8 @@ impl<'rt, 'mir, 'tcx: 'mir, M: CompileTimeMachine<'mir, 'tcx>> ValueVisitor<'mir self.intern_shallow(vtable.alloc_id, InternMode::ConstInner, None); } else { // Let validation show the error message, but make sure it *does* error. - tcx.sess.delay_span_bug( - tcx.span, - "vtables pointers cannot be integer pointers", - ); + tcx.sess + .delay_span_bug(tcx.span, "vtables pointers cannot be integer pointers"); } } // Check if we have encountered this pointer+layout combination before. @@ -264,7 +256,8 @@ impl<'rt, 'mir, 'tcx: 'mir, M: CompileTimeMachine<'mir, 'tcx>> ValueVisitor<'mir ty::Array(_, n) if n.eval_usize(tcx.tcx, self.ecx.param_env) == 0 => {} ty::Slice(_) - if mplace.meta.unwrap_meta().to_machine_usize(self.ecx)? == 0 => {} + if mplace.meta.unwrap_meta().to_machine_usize(self.ecx)? + == 0 => {} _ => mutable_memory_in_const(tcx, "`&mut`"), } } else { @@ -315,16 +308,16 @@ pub fn intern_const_alloc_recursive>( intern_kind: InternKind, ret: MPlaceTy<'tcx>, ignore_interior_mut_in_const: bool, -) -where +) where 'tcx: 'mir, { let tcx = ecx.tcx; let base_intern_mode = match intern_kind { InternKind::Static(mutbl) => InternMode::Static(mutbl), // FIXME: what about array lengths, array initializers? - InternKind::Constant | InternKind::ConstProp | InternKind::Promoted => - InternMode::ConstBase, + InternKind::Constant | InternKind::ConstProp | InternKind::Promoted => { + InternMode::ConstBase + } }; // Type based interning. @@ -362,7 +355,7 @@ where // references are "leftover"-interned, and later validation will show a proper error // and point at the right part of the value causing the problem. match res { - Ok(()) => {}, + Ok(()) => {} Err(error) => { ecx.tcx.sess.delay_span_bug( ecx.tcx.span, @@ -412,10 +405,9 @@ where // is tracked by const-checking. // FIXME: downgrade this to a warning? It rejects some legitimate consts, // such as `const CONST_RAW: *const Vec = &Vec::new() as *const _;`. - ecx.tcx.sess.span_err( - ecx.tcx.span, - "untyped pointers are not allowed in constant", - ); + ecx.tcx + .sess + .span_err(ecx.tcx.span, "untyped pointers are not allowed in constant"); // For better errors later, mark the allocation as immutable. alloc.mutability = Mutability::Not; } @@ -430,13 +422,10 @@ where } else if ecx.memory.dead_alloc_map.contains_key(&alloc_id) { // Codegen does not like dangling pointers, and generally `tcx` assumes that // all allocations referenced anywhere actually exist. So, make sure we error here. - ecx.tcx.sess.span_err( - ecx.tcx.span, - "encountered dangling pointer in final constant", - ); + ecx.tcx.sess.span_err(ecx.tcx.span, "encountered dangling pointer in final constant"); } else if ecx.tcx.get_global_alloc(alloc_id).is_none() { - // We have hit an `AllocId` that is neither in local or global memory and isn't - // marked as dangling by local memory. That should be impossible. + // We have hit an `AllocId` that is neither in local or global memory and isn't + // marked as dangling by local memory. That should be impossible. span_bug!(ecx.tcx.span, "encountered unknown alloc id {:?}", alloc_id); } } From a06740cbea6c821d0aab3bf9f4882ed3716d0a36 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 29 Apr 2020 14:04:40 +0200 Subject: [PATCH 090/203] Typo Co-Authored-By: Oliver Scherer --- src/librustc_mir/interpret/intern.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_mir/interpret/intern.rs b/src/librustc_mir/interpret/intern.rs index 8ce2cabed5dd..02a7f24a1e35 100644 --- a/src/librustc_mir/interpret/intern.rs +++ b/src/librustc_mir/interpret/intern.rs @@ -300,7 +300,7 @@ pub enum InternKind { /// Intern `ret` and everything it references. /// /// This *cannot raise an interpreter error*. Doing so is left to validation, which -/// trakcs where in the value we are and thus can show much better error messages. +/// tracks where in the value we are and thus can show much better error messages. /// Any errors here would anyway be turned into `const_err` lints, whereas validation failures /// are hard errors. pub fn intern_const_alloc_recursive>( From e73ee41241240f740afc10a6fc16521215759ed7 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 4 May 2020 11:29:16 +0200 Subject: [PATCH 091/203] rebase fallout --- src/test/ui/consts/miri_unleashed/mutable_references_err.rs | 2 +- src/test/ui/consts/miri_unleashed/raw_mutable_const.rs | 2 -- src/test/ui/consts/miri_unleashed/raw_mutable_const.stderr | 4 ++-- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/test/ui/consts/miri_unleashed/mutable_references_err.rs b/src/test/ui/consts/miri_unleashed/mutable_references_err.rs index 5014a601390d..06fb27bcff86 100644 --- a/src/test/ui/consts/miri_unleashed/mutable_references_err.rs +++ b/src/test/ui/consts/miri_unleashed/mutable_references_err.rs @@ -4,7 +4,7 @@ use std::cell::UnsafeCell; -// this test ICEs to ensure that our mutability story is sound +// this test ensures that our mutability story is sound struct Meh { x: &'static UnsafeCell, diff --git a/src/test/ui/consts/miri_unleashed/raw_mutable_const.rs b/src/test/ui/consts/miri_unleashed/raw_mutable_const.rs index 3d200e231733..cabd754e01ac 100644 --- a/src/test/ui/consts/miri_unleashed/raw_mutable_const.rs +++ b/src/test/ui/consts/miri_unleashed/raw_mutable_const.rs @@ -1,7 +1,5 @@ // compile-flags: -Zunleash-the-miri-inside-of-you -#![feature(const_raw_ptr_deref)] -#![feature(const_mut_refs)] #![allow(const_err)] use std::cell::UnsafeCell; diff --git a/src/test/ui/consts/miri_unleashed/raw_mutable_const.stderr b/src/test/ui/consts/miri_unleashed/raw_mutable_const.stderr index c6dbf086ec0e..b5b5a965295a 100644 --- a/src/test/ui/consts/miri_unleashed/raw_mutable_const.stderr +++ b/src/test/ui/consts/miri_unleashed/raw_mutable_const.stderr @@ -1,5 +1,5 @@ error: untyped pointers are not allowed in constant - --> $DIR/raw_mutable_const.rs:9:1 + --> $DIR/raw_mutable_const.rs:7:1 | LL | const MUTABLE_BEHIND_RAW: *mut i32 = &UnsafeCell::new(42) as *const _ as *mut _; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -7,7 +7,7 @@ LL | const MUTABLE_BEHIND_RAW: *mut i32 = &UnsafeCell::new(42) as *const _ as *m warning: skipping const checks | help: skipping check that does not even have a feature gate - --> $DIR/raw_mutable_const.rs:9:38 + --> $DIR/raw_mutable_const.rs:7:38 | LL | const MUTABLE_BEHIND_RAW: *mut i32 = &UnsafeCell::new(42) as *const _ as *mut _; | ^^^^^^^^^^^^^^^^^^^^ From d80ac6416d1a6b38756e18c5b5ea421bbd11dfba Mon Sep 17 00:00:00 2001 From: Faris Sufyan <47665123+Dolpheyn@users.noreply.github.com> Date: Sun, 10 May 2020 18:06:30 +0800 Subject: [PATCH 092/203] Fix link to `map` documentation in example Co-authored-by: Timo --- src/libcore/option.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcore/option.rs b/src/libcore/option.rs index 4647ad010067..4df9eaa48156 100644 --- a/src/libcore/option.rs +++ b/src/libcore/option.rs @@ -1380,7 +1380,7 @@ impl<'a, T> From<&'a Option> for Option<&'a T> { /// so this technique uses `as_ref` to first take an `Option` to a reference /// to the value inside the original. /// - /// [`map`]: enum.Option.html#method.map + /// [`map`]: ../../std/option/enum.Option.html#method.map /// [`String`]: ../../std/string/struct.String.html /// [`usize`]: ../../std/primitive.usize.html /// From a26335b2a0972ccd92468f9ea811a5c9253c9f84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Marie?= Date: Sun, 10 May 2020 10:23:13 +0000 Subject: [PATCH 093/203] update stacker to 0.1.9 to unbreak build on OpenBSD --- Cargo.lock | 4 ++-- src/librustc_data_structures/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 34d83e0d339a..33fee44d7933 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4778,9 +4778,9 @@ checksum = "ffbc596e092fe5f598b12ef46cc03754085ac2f4d8c739ad61c4ae266cc3b3fa" [[package]] name = "stacker" -version = "0.1.8" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32c2467b8abbb417e4e62fd62229719b9c9d77714a7fa989f1afad16ba9c9743" +checksum = "72dd941b456e1c006d6b9f27c526d5b69281288aeea8cba82c19d3843d8ccdd2" dependencies = [ "cc", "cfg-if", diff --git a/src/librustc_data_structures/Cargo.toml b/src/librustc_data_structures/Cargo.toml index f543f8051a44..81ad032967bf 100644 --- a/src/librustc_data_structures/Cargo.toml +++ b/src/librustc_data_structures/Cargo.toml @@ -28,7 +28,7 @@ rustc_index = { path = "../librustc_index", package = "rustc_index" } bitflags = "1.2.1" measureme = "0.7.1" libc = "0.2" -stacker = "0.1.6" +stacker = "0.1.9" [dependencies.parking_lot] version = "0.10" From 0aaff14ae38aa24729fe2fc056ce9fc79b5dda57 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 10 May 2020 12:40:11 +0200 Subject: [PATCH 094/203] Improve E0571 wording --- src/librustc_error_codes/error_codes/E0571.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/librustc_error_codes/error_codes/E0571.md b/src/librustc_error_codes/error_codes/E0571.md index c2a3a8d75888..eadae05aa304 100644 --- a/src/librustc_error_codes/error_codes/E0571.md +++ b/src/librustc_error_codes/error_codes/E0571.md @@ -7,7 +7,7 @@ Example of erroneous code: # fn satisfied(n: usize) -> bool { n % 23 == 0 } let result = while true { if satisfied(i) { - break 2*i; // error: `break` with value from a `while` loop + break 2 * i; // error: `break` with value from a `while` loop } i += 1; }; @@ -22,9 +22,9 @@ Make sure `break value;` statements only occur in `loop` loops: ``` # let mut i = 1; # fn satisfied(n: usize) -> bool { n % 23 == 0 } -let result = loop { // ok! +let result = loop { // This is now a "loop" loop. if satisfied(i) { - break 2*i; + break 2 * i; // ok! } i += 1; }; From 62116c31cd863c8aab35e5c7acfb8ded41ca28a1 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Sun, 10 May 2020 00:33:08 +0200 Subject: [PATCH 095/203] Emit a warning when optimization fuel runs out `eprintln!` gets swallowed by Cargo too easily. --- src/librustc_session/session.rs | 2 +- src/test/ui/optimization-fuel-0.rs | 3 +-- src/test/ui/optimization-fuel-0.stderr | 5 ++++- src/test/ui/optimization-fuel-1.rs | 3 +-- src/test/ui/optimization-fuel-1.stderr | 5 ++++- 5 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/librustc_session/session.rs b/src/librustc_session/session.rs index 48e36fdb3d49..15bd87d5ffdb 100644 --- a/src/librustc_session/session.rs +++ b/src/librustc_session/session.rs @@ -813,7 +813,7 @@ impl Session { let mut fuel = self.optimization_fuel.lock(); ret = fuel.remaining != 0; if fuel.remaining == 0 && !fuel.out_of_fuel { - eprintln!("optimization-fuel-exhausted: {}", msg()); + self.warn(&format!("optimization-fuel-exhausted: {}", msg())); fuel.out_of_fuel = true; } else if fuel.remaining > 0 { fuel.remaining -= 1; diff --git a/src/test/ui/optimization-fuel-0.rs b/src/test/ui/optimization-fuel-0.rs index f86972b73482..a97c5750f94c 100644 --- a/src/test/ui/optimization-fuel-0.rs +++ b/src/test/ui/optimization-fuel-0.rs @@ -4,8 +4,7 @@ use std::mem::size_of; -// (#55495: The --error-format is to sidestep an issue in our test harness) -// compile-flags: --error-format human -Z fuel=foo=0 +// compile-flags: -Z fuel=foo=0 struct S1(u8, u16, u8); struct S2(u8, u16, u8); diff --git a/src/test/ui/optimization-fuel-0.stderr b/src/test/ui/optimization-fuel-0.stderr index 3ad405b2b50f..f0e2ebfc37a3 100644 --- a/src/test/ui/optimization-fuel-0.stderr +++ b/src/test/ui/optimization-fuel-0.stderr @@ -1 +1,4 @@ -optimization-fuel-exhausted: Reorder fields of "S1" +warning: optimization-fuel-exhausted: Reorder fields of "S1" + +warning: 1 warning emitted + diff --git a/src/test/ui/optimization-fuel-1.rs b/src/test/ui/optimization-fuel-1.rs index 98283066361c..a09f91c68abe 100644 --- a/src/test/ui/optimization-fuel-1.rs +++ b/src/test/ui/optimization-fuel-1.rs @@ -4,8 +4,7 @@ use std::mem::size_of; -// (#55495: The --error-format is to sidestep an issue in our test harness) -// compile-flags: --error-format human -Z fuel=foo=1 +// compile-flags: -Z fuel=foo=1 struct S1(u8, u16, u8); struct S2(u8, u16, u8); diff --git a/src/test/ui/optimization-fuel-1.stderr b/src/test/ui/optimization-fuel-1.stderr index 197e45219c3f..53eafb05830c 100644 --- a/src/test/ui/optimization-fuel-1.stderr +++ b/src/test/ui/optimization-fuel-1.stderr @@ -1 +1,4 @@ -optimization-fuel-exhausted: Reorder fields of "S2" +warning: optimization-fuel-exhausted: Reorder fields of "S2" + +warning: 1 warning emitted + From 32a46e91155de70eeca062a1ece74cea56574649 Mon Sep 17 00:00:00 2001 From: csmoe Date: Wed, 6 May 2020 18:43:56 +0800 Subject: [PATCH 096/203] add test case for issue-61076 --- src/test/ui/async-await/issue-61076.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 src/test/ui/async-await/issue-61076.rs diff --git a/src/test/ui/async-await/issue-61076.rs b/src/test/ui/async-await/issue-61076.rs new file mode 100644 index 000000000000..0c6c53119977 --- /dev/null +++ b/src/test/ui/async-await/issue-61076.rs @@ -0,0 +1,12 @@ +// edition:2018 + +async fn foo() -> Result<(), ()> { + Ok(()) +} + +async fn bar() -> Result<(), ()> { + foo()?; + Ok(()) +} + +fn main() {} From 2e2aac4f57b6bd4ca8e17b9143d49c14371e071f Mon Sep 17 00:00:00 2001 From: csmoe Date: Wed, 6 May 2020 18:44:14 +0800 Subject: [PATCH 097/203] add try trait as lang item --- src/libcore/ops/try.rs | 1 + src/librustc_hir/lang_items.rs | 1 + src/librustc_typeck/check/mod.rs | 32 ++++++++++++++++++++++---------- 3 files changed, 24 insertions(+), 10 deletions(-) diff --git a/src/libcore/ops/try.rs b/src/libcore/ops/try.rs index 996a01d413cb..ed8c614b1097 100644 --- a/src/libcore/ops/try.rs +++ b/src/libcore/ops/try.rs @@ -25,6 +25,7 @@ ) )] #[doc(alias = "?")] + #[cfg_attr(not(bootstrap), lang = "try_trait")] pub trait Try { /// The type of this value when viewed as successful. #[unstable(feature = "try_trait", issue = "42327")] diff --git a/src/librustc_hir/lang_items.rs b/src/librustc_hir/lang_items.rs index 53f72804a848..2ffa77031f33 100644 --- a/src/librustc_hir/lang_items.rs +++ b/src/librustc_hir/lang_items.rs @@ -194,6 +194,7 @@ language_item_table! { ShrAssignTraitLangItem, "shr_assign", shr_assign_trait, Target::Trait; IndexTraitLangItem, "index", index_trait, Target::Trait; IndexMutTraitLangItem, "index_mut", index_mut_trait, Target::Trait; + TryTraitLangItem, "try_trait", try_trait, Target::Trait; UnsafeCellTypeLangItem, "unsafe_cell", unsafe_cell_type, Target::Struct; VaListTypeLangItem, "va_list", va_list, Target::Struct; diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 956e09ec52b4..53891a4fd9fd 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -5289,6 +5289,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expected: Ty<'tcx>, found: Ty<'tcx>, ) { + debug!("suggest_missing_await: expr={:?} expected={:?}, found={:?}", expr, expected, found); // `.await` is not permitted outside of `async` bodies, so don't bother to suggest if the // body isn't `async`. let item_id = self.tcx().hir().get_parent_node(self.body_id); @@ -5306,22 +5307,33 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .next() .unwrap() .def_id; + // `::Output` + let projection_ty = ty::ProjectionTy { + // `T` + substs: self + .tcx + .mk_substs_trait(found, self.fresh_substs_for_item(sp, item_def_id)), + // `Future::Output` + item_def_id, + }; + let predicate = ty::Predicate::Projection(ty::Binder::bind(ty::ProjectionPredicate { - // `::Output` - projection_ty: ty::ProjectionTy { - // `T` - substs: self.tcx.mk_substs_trait( - found, - self.fresh_substs_for_item(sp, item_def_id), - ), - // `Future::Output` - item_def_id, - }, + projection_ty, ty: expected, })); let obligation = traits::Obligation::new(self.misc(sp), self.param_env, predicate); debug!("suggest_missing_await: trying obligation {:?}", obligation); + + //let try_trait_def_id = self.tcx.require_lang_item(lang_items::TryTraitLangItem, None); + //let try_trait_ref = ty::TraitRef { + // def_id: try_trait_def_id, + // substs: self.tcx.mk_substs_trait(self.tcx.type_of(item_def_id), &[]), + //}; + //let try_obligation = traits::Obligation::new(self.misc(sp), self.param_env, try_trait_ref.without_const().to_predicate()); + //let try_trait_is_implemented = self.predicate_must_hold_modulo_regions(&try_obligation); + //debug!("suggest_missing_await: try trait is implemented {}", try_trait_is_implemented); + if self.infcx.predicate_may_hold(&obligation) { debug!("suggest_missing_await: obligation held: {:?}", obligation); if let Ok(code) = self.sess().source_map().span_to_snippet(sp) { From 114cd006f52272618bd64382213cd08eaa313136 Mon Sep 17 00:00:00 2001 From: csmoe Date: Sat, 9 May 2020 22:04:02 +0800 Subject: [PATCH 098/203] normalize Future::Ouput --- src/librustc_typeck/check/mod.rs | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 53891a4fd9fd..bd5049446e61 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -5317,22 +5317,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { item_def_id, }; + let cause = traits::ObligationCause::misc(sp, self.body_id); + let normalized_ty = self.fulfillment_cx.borrow_mut().normalize_projection_type( + &self.infcx, + self.param_env, + projection_ty, + cause, + ); + debug!("suggest_missing_await: projection_type {:?}", normalized_ty); + let predicate = ty::Predicate::Projection(ty::Binder::bind(ty::ProjectionPredicate { projection_ty, ty: expected, })); let obligation = traits::Obligation::new(self.misc(sp), self.param_env, predicate); - debug!("suggest_missing_await: trying obligation {:?}", obligation); - //let try_trait_def_id = self.tcx.require_lang_item(lang_items::TryTraitLangItem, None); - //let try_trait_ref = ty::TraitRef { - // def_id: try_trait_def_id, - // substs: self.tcx.mk_substs_trait(self.tcx.type_of(item_def_id), &[]), - //}; - //let try_obligation = traits::Obligation::new(self.misc(sp), self.param_env, try_trait_ref.without_const().to_predicate()); - //let try_trait_is_implemented = self.predicate_must_hold_modulo_regions(&try_obligation); - //debug!("suggest_missing_await: try trait is implemented {}", try_trait_is_implemented); + debug!("suggest_missing_await: trying obligation {:?}", obligation); if self.infcx.predicate_may_hold(&obligation) { debug!("suggest_missing_await: obligation held: {:?}", obligation); From 627f473dd426497972cce58ba64e8b0ff2409078 Mon Sep 17 00:00:00 2001 From: csmoe Date: Sun, 10 May 2020 20:07:42 +0800 Subject: [PATCH 099/203] suggest await before try when performing trait selection --- src/libcore/ops/try.rs | 2 +- .../traits/error_reporting/mod.rs | 11 +++ .../traits/error_reporting/suggestions.rs | 80 +++++++++++++++++++ src/librustc_typeck/check/mod.rs | 9 --- 4 files changed, 92 insertions(+), 10 deletions(-) diff --git a/src/libcore/ops/try.rs b/src/libcore/ops/try.rs index ed8c614b1097..ef748bcee6e2 100644 --- a/src/libcore/ops/try.rs +++ b/src/libcore/ops/try.rs @@ -25,7 +25,7 @@ ) )] #[doc(alias = "?")] - #[cfg_attr(not(bootstrap), lang = "try_trait")] +#[cfg_attr(not(bootstrap), lang = "try_trait")] pub trait Try { /// The type of this value when viewed as successful. #[unstable(feature = "try_trait", issue = "42327")] diff --git a/src/librustc_trait_selection/traits/error_reporting/mod.rs b/src/librustc_trait_selection/traits/error_reporting/mod.rs index 405c656bad56..272827cfef83 100644 --- a/src/librustc_trait_selection/traits/error_reporting/mod.rs +++ b/src/librustc_trait_selection/traits/error_reporting/mod.rs @@ -400,6 +400,17 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { self.suggest_remove_reference(&obligation, &mut err, &trait_ref); self.suggest_semicolon_removal(&obligation, &mut err, span, &trait_ref); self.note_version_mismatch(&mut err, &trait_ref); + //self.sugggest_await_before_try(&mut err, &obligation, &trait_ref); + debug!( + "suggest_await_befor_try: trait_predicate={:?} obligation={:?}, trait_ref={:?}", + trait_predicate, obligation, trait_ref + ); + self.suggest_await_befor_try( + &mut err, + &obligation, + trait_ref.self_ty(), + span, + ); if self.suggest_impl_trait(&mut err, span, &obligation, &trait_ref) { err.emit(); return; diff --git a/src/librustc_trait_selection/traits/error_reporting/suggestions.rs b/src/librustc_trait_selection/traits/error_reporting/suggestions.rs index 74dd47a91c27..d0b39d6016af 100644 --- a/src/librustc_trait_selection/traits/error_reporting/suggestions.rs +++ b/src/librustc_trait_selection/traits/error_reporting/suggestions.rs @@ -1,8 +1,10 @@ use super::{ EvaluationResult, Obligation, ObligationCause, ObligationCauseCode, PredicateObligation, + SelectionContext, }; use crate::infer::InferCtxt; +use crate::traits::normalize_projection_type; use rustc_errors::{error_code, struct_span_err, Applicability, DiagnosticBuilder, Style}; use rustc_hir as hir; @@ -150,6 +152,15 @@ pub trait InferCtxtExt<'tcx> { T: fmt::Display; fn suggest_new_overflow_limit(&self, err: &mut DiagnosticBuilder<'_>); + + /// Suggest to await before try: future? => future.await? + fn suggest_await_befor_try( + &self, + err: &mut DiagnosticBuilder<'_>, + obligation: &PredicateObligation<'tcx>, + ty: Ty<'tcx>, + span: Span, + ); } fn predicate_constraint(generics: &hir::Generics<'_>, pred: String) -> (Span, String) { @@ -1765,6 +1776,75 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { suggested_limit, self.tcx.crate_name, )); } + + fn suggest_await_befor_try( + &self, + err: &mut DiagnosticBuilder<'_>, + obligation: &PredicateObligation<'tcx>, + ty: Ty<'tcx>, + span: Span, + ) { + debug!("suggest_await_befor_try: obligation={:?}, span={:?}", obligation, span); + let body_hir_id = obligation.cause.body_id; + let item_id = self.tcx.hir().get_parent_node(body_hir_id); + if let Some(body_id) = self.tcx.hir().maybe_body_owned_by(item_id) { + let body = self.tcx.hir().body(body_id); + if let Some(hir::GeneratorKind::Async(_)) = body.generator_kind { + // Check for `Future` implementations by constructing a predicate to + // prove: `::Output == U` + let future_trait = self.tcx.lang_items().future_trait().unwrap(); + let item_def_id = self + .tcx + .associated_items(future_trait) + .in_definition_order() + .next() + .unwrap() + .def_id; + // `::Output` + let projection_ty = ty::ProjectionTy { + // `T` + substs: self + .tcx + .mk_substs_trait(ty, self.fresh_substs_for_item(span, item_def_id)), + // `Future::Output` + item_def_id, + }; + + let cause = ObligationCause::misc(span, body_hir_id); + let mut selcx = SelectionContext::new(self); + + let mut obligations = vec![]; + let normalized_ty = normalize_projection_type( + &mut selcx, + obligation.param_env, + projection_ty, + obligation.cause.clone(), + 0, + &mut obligations, + ); + + debug!("suggest_await_befor_try: normalized_projection_type {:?}", normalized_ty); + let try_trait_ref_id = self.tcx.lang_items().try_trait().unwrap(); + if let Some(try_trait_ref) = self.tcx.impl_trait_ref(try_trait_ref_id) { + let try_predicate = try_trait_ref.without_const().to_predicate(); + let try_obligation = + Obligation::new(cause, obligation.param_env, try_predicate); + debug!("suggest_await_befor_try: try_trait_obligation {:?}", try_obligation); + if self.predicate_may_hold(&try_obligation) { + debug!("try_obligation holds"); + if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) { + err.span_suggestion( + span, + "consider using `.await` here", + format!("{}.await", snippet), + Applicability::MaybeIncorrect, + ); + } + } + } + } + } + } } /// Collect all the returned expressions within the input expression. diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index bd5049446e61..c142e88b7de5 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -5317,15 +5317,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { item_def_id, }; - let cause = traits::ObligationCause::misc(sp, self.body_id); - let normalized_ty = self.fulfillment_cx.borrow_mut().normalize_projection_type( - &self.infcx, - self.param_env, - projection_ty, - cause, - ); - debug!("suggest_missing_await: projection_type {:?}", normalized_ty); - let predicate = ty::Predicate::Projection(ty::Binder::bind(ty::ProjectionPredicate { projection_ty, From c7e64f54c86a05ddd09fc3da4e98a8d748658337 Mon Sep 17 00:00:00 2001 From: csmoe Date: Sun, 10 May 2020 22:34:01 +0800 Subject: [PATCH 100/203] remove try_trait lang item --- src/libcore/ops/try.rs | 1 - src/librustc_hir/lang_items.rs | 2 - .../traits/error_reporting/mod.rs | 12 +---- .../traits/error_reporting/suggestions.rs | 46 ++++++++++--------- 4 files changed, 26 insertions(+), 35 deletions(-) diff --git a/src/libcore/ops/try.rs b/src/libcore/ops/try.rs index ef748bcee6e2..996a01d413cb 100644 --- a/src/libcore/ops/try.rs +++ b/src/libcore/ops/try.rs @@ -25,7 +25,6 @@ ) )] #[doc(alias = "?")] -#[cfg_attr(not(bootstrap), lang = "try_trait")] pub trait Try { /// The type of this value when viewed as successful. #[unstable(feature = "try_trait", issue = "42327")] diff --git a/src/librustc_hir/lang_items.rs b/src/librustc_hir/lang_items.rs index 2ffa77031f33..a503e3534e3b 100644 --- a/src/librustc_hir/lang_items.rs +++ b/src/librustc_hir/lang_items.rs @@ -194,8 +194,6 @@ language_item_table! { ShrAssignTraitLangItem, "shr_assign", shr_assign_trait, Target::Trait; IndexTraitLangItem, "index", index_trait, Target::Trait; IndexMutTraitLangItem, "index_mut", index_mut_trait, Target::Trait; - TryTraitLangItem, "try_trait", try_trait, Target::Trait; - UnsafeCellTypeLangItem, "unsafe_cell", unsafe_cell_type, Target::Struct; VaListTypeLangItem, "va_list", va_list, Target::Struct; diff --git a/src/librustc_trait_selection/traits/error_reporting/mod.rs b/src/librustc_trait_selection/traits/error_reporting/mod.rs index 272827cfef83..c74870306869 100644 --- a/src/librustc_trait_selection/traits/error_reporting/mod.rs +++ b/src/librustc_trait_selection/traits/error_reporting/mod.rs @@ -400,17 +400,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { self.suggest_remove_reference(&obligation, &mut err, &trait_ref); self.suggest_semicolon_removal(&obligation, &mut err, span, &trait_ref); self.note_version_mismatch(&mut err, &trait_ref); - //self.sugggest_await_before_try(&mut err, &obligation, &trait_ref); - debug!( - "suggest_await_befor_try: trait_predicate={:?} obligation={:?}, trait_ref={:?}", - trait_predicate, obligation, trait_ref - ); - self.suggest_await_befor_try( - &mut err, - &obligation, - trait_ref.self_ty(), - span, - ); + self.suggest_await_before_try(&mut err, &obligation, &trait_ref, span); if self.suggest_impl_trait(&mut err, span, &obligation, &trait_ref) { err.emit(); return; diff --git a/src/librustc_trait_selection/traits/error_reporting/suggestions.rs b/src/librustc_trait_selection/traits/error_reporting/suggestions.rs index d0b39d6016af..b28f0001cd97 100644 --- a/src/librustc_trait_selection/traits/error_reporting/suggestions.rs +++ b/src/librustc_trait_selection/traits/error_reporting/suggestions.rs @@ -154,11 +154,11 @@ pub trait InferCtxtExt<'tcx> { fn suggest_new_overflow_limit(&self, err: &mut DiagnosticBuilder<'_>); /// Suggest to await before try: future? => future.await? - fn suggest_await_befor_try( + fn suggest_await_before_try( &self, err: &mut DiagnosticBuilder<'_>, obligation: &PredicateObligation<'tcx>, - ty: Ty<'tcx>, + trait_ref: &ty::Binder>, span: Span, ); } @@ -1777,21 +1777,23 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { )); } - fn suggest_await_befor_try( + fn suggest_await_before_try( &self, err: &mut DiagnosticBuilder<'_>, obligation: &PredicateObligation<'tcx>, - ty: Ty<'tcx>, + trait_ref: &ty::Binder>, span: Span, ) { - debug!("suggest_await_befor_try: obligation={:?}, span={:?}", obligation, span); + debug!( + "suggest_await_befor_try: obligation={:?}, span={:?}, trait_ref={:?}", + obligation, span, trait_ref + ); let body_hir_id = obligation.cause.body_id; let item_id = self.tcx.hir().get_parent_node(body_hir_id); + if let Some(body_id) = self.tcx.hir().maybe_body_owned_by(item_id) { let body = self.tcx.hir().body(body_id); if let Some(hir::GeneratorKind::Async(_)) = body.generator_kind { - // Check for `Future` implementations by constructing a predicate to - // prove: `::Output == U` let future_trait = self.tcx.lang_items().future_trait().unwrap(); let item_def_id = self .tcx @@ -1803,14 +1805,15 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { // `::Output` let projection_ty = ty::ProjectionTy { // `T` - substs: self - .tcx - .mk_substs_trait(ty, self.fresh_substs_for_item(span, item_def_id)), + substs: self.tcx.mk_substs_trait( + trait_ref.self_ty(), + self.fresh_substs_for_item(span, item_def_id), + ), // `Future::Output` item_def_id, }; - let cause = ObligationCause::misc(span, body_hir_id); + //let cause = ObligationCause::misc(span, body_hir_id); let mut selcx = SelectionContext::new(self); let mut obligations = vec![]; @@ -1824,19 +1827,20 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { ); debug!("suggest_await_befor_try: normalized_projection_type {:?}", normalized_ty); - let try_trait_ref_id = self.tcx.lang_items().try_trait().unwrap(); - if let Some(try_trait_ref) = self.tcx.impl_trait_ref(try_trait_ref_id) { - let try_predicate = try_trait_ref.without_const().to_predicate(); - let try_obligation = - Obligation::new(cause, obligation.param_env, try_predicate); - debug!("suggest_await_befor_try: try_trait_obligation {:?}", try_obligation); - if self.predicate_may_hold(&try_obligation) { - debug!("try_obligation holds"); - if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) { + let try_obligation = self.mk_obligation_for_def_id( + trait_ref.def_id(), + normalized_ty, + obligation.cause.clone(), + obligation.param_env, + ); + debug!("suggest_await_befor_try: try_trait_obligation {:?}", try_obligation); + if self.predicate_may_hold(&try_obligation) { + if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) { + if snippet.ends_with('?') { err.span_suggestion( span, "consider using `.await` here", - format!("{}.await", snippet), + format!("{}.await?", snippet.trim_end_matches('?')), Applicability::MaybeIncorrect, ); } From 7e62240801cc5f7aa70300fb0f92f54370eabea6 Mon Sep 17 00:00:00 2001 From: Marko Mijalkovic Date: Sun, 10 May 2020 16:06:33 -0400 Subject: [PATCH 101/203] Add lld_link_script to TargetOptions --- src/librustc_codegen_ssa/back/link.rs | 31 +++++++++++++++++++++ src/librustc_target/spec/mipsel_sony_psp.rs | 17 ++--------- src/librustc_target/spec/mod.rs | 6 ++++ 3 files changed, 39 insertions(+), 15 deletions(-) diff --git a/src/librustc_codegen_ssa/back/link.rs b/src/librustc_codegen_ssa/back/link.rs index 7a0e1e2c6388..ab59a1c5f487 100644 --- a/src/librustc_codegen_ssa/back/link.rs +++ b/src/librustc_codegen_ssa/back/link.rs @@ -1179,6 +1179,34 @@ fn add_pre_link_args( cmd.args(&sess.opts.debugging_opts.pre_link_args); } +/// Add an LLD link script embedded in the target, if applicable. +fn add_lld_link_script( + cmd: &mut dyn Linker, + sess: &Session, + flavor: LinkerFlavor, + tmpdir: &Path, + crate_type: CrateType, +) { + match (flavor, crate_type, &sess.target.target.options.lld_link_script) { + ( + LinkerFlavor::Lld(LldFlavor::Ld), + CrateType::Cdylib | CrateType::Executable, + Some(script), + ) => { + let file_name = ["rustc", &sess.target.target.llvm_target, "linkfile.ld"].join("-"); + + let path = tmpdir.join(file_name); + if let Err(e) = fs::write(&path, script) { + sess.fatal(&format!("failed to write link script to {}: {}", path.display(), e)); + } + + cmd.arg("--script"); + cmd.arg(path); + } + _ => {} + } +} + /// Add arbitrary "user defined" args defined from command line and by `#[link_args]` attributes. /// FIXME: Determine where exactly these args need to be inserted. fn add_user_defined_link_args( @@ -1421,6 +1449,9 @@ fn linker_with_args<'a, B: ArchiveBuilder<'a>>( // NO-OPT-OUT, OBJECT-FILES-MAYBE, CUSTOMIZATION-POINT add_pre_link_args(cmd, sess, flavor, crate_type); + // NO-OPT-OUT + add_lld_link_script(cmd, sess, flavor, tmpdir, crate_type); + // NO-OPT-OUT, OBJECT-FILES-NO, AUDIT-ORDER if sess.target.target.options.is_like_fuchsia { let prefix = match sess.opts.debugging_opts.sanitizer { diff --git a/src/librustc_target/spec/mipsel_sony_psp.rs b/src/librustc_target/spec/mipsel_sony_psp.rs index 80c253b86bbd..eb38dee63b68 100644 --- a/src/librustc_target/spec/mipsel_sony_psp.rs +++ b/src/librustc_target/spec/mipsel_sony_psp.rs @@ -1,28 +1,14 @@ use crate::spec::{LinkArgs, LinkerFlavor, LldFlavor, RelocModel}; use crate::spec::{Target, TargetOptions, TargetResult}; -use std::{env, fs, io, path::PathBuf}; // The PSP has custom linker requirements. const LINKER_SCRIPT: &str = include_str!("./mipsel_sony_psp_linker_script.ld"); -fn write_script() -> io::Result { - let path = env::temp_dir().join("rustc-mipsel-sony-psp-linkfile.ld"); - fs::write(&path, LINKER_SCRIPT)?; - Ok(path) -} - pub fn target() -> TargetResult { - let script = write_script().map_err(|e| format!("failed to write link script: {}", e))?; - let mut pre_link_args = LinkArgs::new(); pre_link_args.insert( LinkerFlavor::Lld(LldFlavor::Ld), - vec![ - "--eh-frame-hdr".to_string(), - "--emit-relocs".to_string(), - "--script".to_string(), - script.display().to_string(), - ], + vec!["--eh-frame-hdr".to_string(), "--emit-relocs".to_string()], ); Ok(Target { @@ -49,6 +35,7 @@ pub fn target() -> TargetResult { // PSP does not support trap-on-condition instructions. llvm_args: vec!["-mno-check-zero-division".to_string()], pre_link_args, + lld_link_script: Some(LINKER_SCRIPT.to_string()), ..Default::default() }, }) diff --git a/src/librustc_target/spec/mod.rs b/src/librustc_target/spec/mod.rs index dab1e51e3f87..91dfa1550f62 100644 --- a/src/librustc_target/spec/mod.rs +++ b/src/librustc_target/spec/mod.rs @@ -668,6 +668,9 @@ pub struct TargetOptions { /// Linker arguments that are unconditionally passed *after* any /// user-defined libraries. pub post_link_args: LinkArgs, + /// Optional LLD link script applied to `dylib` and `executable` crate + /// types. This is a string containing the script, not a path. + pub lld_link_script: Option, /// Environment variables to be set for the linker invocation. pub link_env: Vec<(String, String)>, @@ -897,6 +900,7 @@ impl Default for TargetOptions { pre_link_args: LinkArgs::new(), pre_link_args_crt: LinkArgs::new(), post_link_args: LinkArgs::new(), + lld_link_script: None, asm_args: Vec::new(), cpu: "generic".to_string(), features: String::new(), @@ -1246,6 +1250,7 @@ impl Target { key!(post_link_objects, list); key!(post_link_objects_crt, list); key!(post_link_args, link_args); + key!(lld_link_script, optional); key!(link_env, env); key!(link_env_remove, list); key!(asm_args, list); @@ -1475,6 +1480,7 @@ impl ToJson for Target { target_option_val!(post_link_objects); target_option_val!(post_link_objects_crt); target_option_val!(link_args - post_link_args); + target_option_val!(lld_link_script); target_option_val!(env - link_env); target_option_val!(link_env_remove); target_option_val!(asm_args); From dc7524be2720fd4ca8d30ecdd776c4c620b83846 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 9 May 2020 19:53:48 +0200 Subject: [PATCH 102/203] remove lldb package from bootstrap, config and build-manifest it's not been built since a long time ago --- config.toml.example | 4 - src/bootstrap/builder.rs | 1 - src/bootstrap/config.rs | 3 - src/bootstrap/configure.py | 1 - src/bootstrap/dist.rs | 121 --------------------------- src/bootstrap/lib.rs | 8 -- src/bootstrap/native.rs | 16 +--- src/bootstrap/sanity.rs | 8 -- src/bootstrap/test.rs | 11 +-- src/tools/build-manifest/src/main.rs | 18 ---- 10 files changed, 7 insertions(+), 184 deletions(-) diff --git a/config.toml.example b/config.toml.example index e32beb1c6119..5447434143cf 100644 --- a/config.toml.example +++ b/config.toml.example @@ -411,10 +411,6 @@ # sysroot. #llvm-tools = false -# Indicates whether LLDB will be made available in the sysroot. -# This is only built if LLVM is also being built. -#lldb = false - # Whether to deny warnings in crates #deny-warnings = true diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index 028623aa7aa9..b8960784ad21 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -441,7 +441,6 @@ impl<'a> Builder<'a> { dist::Clippy, dist::Miri, dist::LlvmTools, - dist::Lldb, dist::Extended, dist::HashSign ), diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index 390630ee51b8..13f88c185ae4 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -85,7 +85,6 @@ pub struct Config { pub use_lld: bool, pub lld_enabled: bool, - pub lldb_enabled: bool, pub llvm_tools_enabled: bool, pub llvm_cflags: Option, @@ -337,7 +336,6 @@ struct Rust { lld: Option, use_lld: Option, llvm_tools: Option, - lldb: Option, deny_warnings: Option, backtrace_on_ice: Option, verify_llvm_ir: Option, @@ -585,7 +583,6 @@ impl Config { } set(&mut config.use_lld, rust.use_lld); set(&mut config.lld_enabled, rust.lld); - set(&mut config.lldb_enabled, rust.lldb); set(&mut config.llvm_tools_enabled, rust.llvm_tools); config.rustc_parallel = rust.parallel_compiler.unwrap_or(false); config.rustc_default_linker = rust.default_linker.clone(); diff --git a/src/bootstrap/configure.py b/src/bootstrap/configure.py index 2a46c563d1f8..d1e53db573e4 100755 --- a/src/bootstrap/configure.py +++ b/src/bootstrap/configure.py @@ -57,7 +57,6 @@ o("cargo-native-static", "build.cargo-native-static", "static native libraries i o("profiler", "build.profiler", "build the profiler runtime") o("full-tools", None, "enable all tools") o("lld", "rust.lld", "build lld") -o("lldb", "rust.lldb", "build lldb") o("missing-tools", "dist.missing-tools", "allow failures when building tools") o("use-libcxx", "llvm.use-libcxx", "build LLVM with libc++") o("control-flow-guard", "rust.control-flow-guard", "Enable Control Flow Guard") diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index bae904114960..c4bca4a00408 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -38,8 +38,6 @@ pub fn pkgname(builder: &Builder<'_>, component: &str) -> String { format!("{}-{}", component, builder.rustfmt_package_vers()) } else if component == "llvm-tools" { format!("{}-{}", component, builder.llvm_tools_package_vers()) - } else if component == "lldb" { - format!("{}-{}", component, builder.lldb_package_vers()) } else { assert!(component.starts_with("rust")); format!("{}-{}", component, builder.rust_package_vers()) @@ -1645,7 +1643,6 @@ impl Step for Extended { let llvm_tools_installer = builder.ensure(LlvmTools { target }); let clippy_installer = builder.ensure(Clippy { compiler, target }); let miri_installer = builder.ensure(Miri { compiler, target }); - let lldb_installer = builder.ensure(Lldb { target }); let mingw_installer = builder.ensure(Mingw { host: target }); let analysis_installer = builder.ensure(Analysis { compiler, target }); @@ -1681,7 +1678,6 @@ impl Step for Extended { tarballs.extend(miri_installer.clone()); tarballs.extend(rustfmt_installer.clone()); tarballs.extend(llvm_tools_installer); - tarballs.extend(lldb_installer); tarballs.push(analysis_installer); tarballs.push(std_installer); if builder.config.docs { @@ -2222,7 +2218,6 @@ impl Step for HashSign { cmd.arg(builder.package_vers(&builder.release_num("miri"))); cmd.arg(builder.package_vers(&builder.release_num("rustfmt"))); cmd.arg(builder.llvm_tools_package_vers()); - cmd.arg(builder.lldb_package_vers()); builder.create_dir(&distdir(builder)); @@ -2349,119 +2344,3 @@ impl Step for LlvmTools { Some(distdir(builder).join(format!("{}-{}.tar.gz", name, target))) } } - -#[derive(Clone, Debug, Eq, Hash, PartialEq)] -pub struct Lldb { - pub target: Interned, -} - -impl Step for Lldb { - type Output = Option; - const ONLY_HOSTS: bool = true; - const DEFAULT: bool = true; - - fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - run.path("src/llvm-project/lldb").path("src/tools/lldb") - } - - fn make_run(run: RunConfig<'_>) { - run.builder.ensure(Lldb { target: run.target }); - } - - fn run(self, builder: &Builder<'_>) -> Option { - let target = self.target; - - if builder.config.dry_run { - return None; - } - - let bindir = builder.llvm_out(target).join("bin"); - let lldb_exe = bindir.join(exe("lldb", &target)); - if !lldb_exe.exists() { - return None; - } - - builder.info(&format!("Dist Lldb ({})", target)); - let src = builder.src.join("src/llvm-project/lldb"); - let name = pkgname(builder, "lldb"); - - let tmp = tmpdir(builder); - let image = tmp.join("lldb-image"); - drop(fs::remove_dir_all(&image)); - - // Prepare the image directory - let root = image.join("lib/rustlib").join(&*target); - let dst = root.join("bin"); - t!(fs::create_dir_all(&dst)); - for program in &["lldb", "lldb-argdumper", "lldb-mi", "lldb-server"] { - let exe = bindir.join(exe(program, &target)); - builder.install(&exe, &dst, 0o755); - } - - // The libraries. - let libdir = builder.llvm_out(target).join("lib"); - let dst = root.join("lib"); - t!(fs::create_dir_all(&dst)); - for entry in t!(fs::read_dir(&libdir)) { - let entry = entry.unwrap(); - if let Ok(name) = entry.file_name().into_string() { - if name.starts_with("liblldb.") && !name.ends_with(".a") { - if t!(entry.file_type()).is_symlink() { - builder.copy_to_folder(&entry.path(), &dst); - } else { - builder.install(&entry.path(), &dst, 0o755); - } - } - } - } - - // The lldb scripts might be installed in lib/python$version - // or in lib64/python$version. If lib64 exists, use it; - // otherwise lib. - let libdir = builder.llvm_out(target).join("lib64"); - let (libdir, libdir_name) = if libdir.exists() { - (libdir, "lib64") - } else { - (builder.llvm_out(target).join("lib"), "lib") - }; - for entry in t!(fs::read_dir(&libdir)) { - let entry = t!(entry); - if let Ok(name) = entry.file_name().into_string() { - if name.starts_with("python") { - let dst = root.join(libdir_name).join(entry.file_name()); - t!(fs::create_dir_all(&dst)); - builder.cp_r(&entry.path(), &dst); - break; - } - } - } - - // Prepare the overlay - let overlay = tmp.join("lldb-overlay"); - drop(fs::remove_dir_all(&overlay)); - builder.create_dir(&overlay); - builder.install(&src.join("LICENSE.TXT"), &overlay, 0o644); - builder.create(&overlay.join("version"), &builder.lldb_vers()); - - // Generate the installer tarball - let mut cmd = rust_installer(builder); - cmd.arg("generate") - .arg("--product-name=Rust") - .arg("--rel-manifest-dir=rustlib") - .arg("--success-message=lldb-installed.") - .arg("--image-dir") - .arg(&image) - .arg("--work-dir") - .arg(&tmpdir(builder)) - .arg("--output-dir") - .arg(&distdir(builder)) - .arg("--non-installed-overlay") - .arg(&overlay) - .arg(format!("--package-name={}-{}", name, target)) - .arg("--legacy-manifest-dirs=rustlib,cargo") - .arg("--component-name=lldb-preview"); - - builder.run(&mut cmd); - Some(distdir(builder).join(format!("{}-{}.tar.gz", name, target))) - } -} diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index 31bbd92cd620..15bf831a1483 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -1029,14 +1029,6 @@ impl Build { self.rust_version() } - fn lldb_package_vers(&self) -> String { - self.package_vers(channel::CFG_RELEASE_NUM) - } - - fn lldb_vers(&self) -> String { - self.rust_version() - } - fn llvm_link_tools_dynamically(&self, target: Interned) -> bool { target.contains("linux-gnu") || target.contains("apple-darwin") } diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs index bcd79a49eced..446017f1fabe 100644 --- a/src/bootstrap/native.rs +++ b/src/bootstrap/native.rs @@ -184,7 +184,7 @@ impl Step for Llvm { } // For distribution we want the LLVM tools to be *statically* linked to libstdc++ - if builder.config.llvm_tools_enabled || builder.config.lldb_enabled { + if builder.config.llvm_tools_enabled { if !target.contains("msvc") { if target.contains("apple") { cfg.define("CMAKE_EXE_LINKER_FLAGS", "-static-libstdc++"); @@ -212,17 +212,9 @@ impl Step for Llvm { enabled_llvm_projects.push("compiler-rt"); } - if builder.config.lldb_enabled { - enabled_llvm_projects.push("clang"); - enabled_llvm_projects.push("lldb"); - // For the time being, disable code signing. - cfg.define("LLDB_CODESIGN_IDENTITY", ""); - cfg.define("LLDB_NO_DEBUGSERVER", "ON"); - } else { - // LLDB requires libxml2; but otherwise we want it to be disabled. - // See https://github.com/rust-lang/rust/pull/50104 - cfg.define("LLVM_ENABLE_LIBXML2", "OFF"); - } + // We want libxml to be disabled. + // See https://github.com/rust-lang/rust/pull/50104 + cfg.define("LLVM_ENABLE_LIBXML2", "OFF"); if !enabled_llvm_projects.is_empty() { enabled_llvm_projects.sort(); diff --git a/src/bootstrap/sanity.rs b/src/bootstrap/sanity.rs index 1760d655b3b4..74b47d077283 100644 --- a/src/bootstrap/sanity.rs +++ b/src/bootstrap/sanity.rs @@ -117,14 +117,6 @@ pub fn check(build: &mut Build) { build.config.ninja = true; } } - - if build.config.lldb_enabled { - cmd_finder.must_have("swig"); - let out = output(Command::new("swig").arg("-version")); - if !out.contains("SWIG Version 3") && !out.contains("SWIG Version 4") { - panic!("Ensure that Swig 3.x.x or 4.x.x is installed."); - } - } } build.config.python = build diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index 0cf47d20ead0..69d65ce9d2d2 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -1106,20 +1106,15 @@ impl Step for Compiletest { .to_string() }) }; - let lldb_exe = if builder.config.lldb_enabled { - // Test against the lldb that was just built. - builder.llvm_out(target).join("bin").join("lldb") - } else { - PathBuf::from("lldb") - }; - let lldb_version = Command::new(&lldb_exe) + let lldb_exe = "lldb"; + let lldb_version = Command::new(lldb_exe) .arg("--version") .output() .map(|output| String::from_utf8_lossy(&output.stdout).to_string()) .ok(); if let Some(ref vers) = lldb_version { cmd.arg("--lldb-version").arg(vers); - let lldb_python_dir = run(Command::new(&lldb_exe).arg("-P")).ok(); + let lldb_python_dir = run(Command::new(lldb_exe).arg("-P")).ok(); if let Some(ref dir) = lldb_python_dir { cmd.arg("--lldb-python-dir").arg(dir); } diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs index 6de07d3e5cfd..39baa6b8540d 100644 --- a/src/tools/build-manifest/src/main.rs +++ b/src/tools/build-manifest/src/main.rs @@ -228,7 +228,6 @@ struct Builder { clippy_release: String, rustfmt_release: String, llvm_tools_release: String, - lldb_release: String, miri_release: String, input: PathBuf, @@ -244,7 +243,6 @@ struct Builder { clippy_version: Option, rustfmt_version: Option, llvm_tools_version: Option, - lldb_version: Option, miri_version: Option, rust_git_commit_hash: Option, @@ -253,7 +251,6 @@ struct Builder { clippy_git_commit_hash: Option, rustfmt_git_commit_hash: Option, llvm_tools_git_commit_hash: Option, - lldb_git_commit_hash: Option, miri_git_commit_hash: Option, should_sign: bool, @@ -284,7 +281,6 @@ fn main() { let miri_release = args.next().unwrap(); let rustfmt_release = args.next().unwrap(); let llvm_tools_release = args.next().unwrap(); - let lldb_release = args.next().unwrap(); // Do not ask for a passphrase while manually testing let mut passphrase = String::new(); @@ -300,7 +296,6 @@ fn main() { clippy_release, rustfmt_release, llvm_tools_release, - lldb_release, miri_release, input, @@ -316,7 +311,6 @@ fn main() { clippy_version: None, rustfmt_version: None, llvm_tools_version: None, - lldb_version: None, miri_version: None, rust_git_commit_hash: None, @@ -325,7 +319,6 @@ fn main() { clippy_git_commit_hash: None, rustfmt_git_commit_hash: None, llvm_tools_git_commit_hash: None, - lldb_git_commit_hash: None, miri_git_commit_hash: None, should_sign, @@ -340,7 +333,6 @@ enum PkgType { Clippy, Rustfmt, LlvmTools, - Lldb, Miri, Other, } @@ -355,7 +347,6 @@ impl PkgType { "clippy" | "clippy-preview" => Clippy, "rustfmt" | "rustfmt-preview" => Rustfmt, "llvm-tools" | "llvm-tools-preview" => LlvmTools, - "lldb" | "lldb-preview" => Lldb, "miri" | "miri-preview" => Miri, _ => Other, } @@ -370,8 +361,6 @@ impl Builder { self.clippy_version = self.version("clippy", "x86_64-unknown-linux-gnu"); self.rustfmt_version = self.version("rustfmt", "x86_64-unknown-linux-gnu"); self.llvm_tools_version = self.version("llvm-tools", "x86_64-unknown-linux-gnu"); - // lldb is only built for macOS. - self.lldb_version = self.version("lldb", "x86_64-apple-darwin"); self.miri_version = self.version("miri", "x86_64-unknown-linux-gnu"); self.rust_git_commit_hash = self.git_commit_hash("rust", "x86_64-unknown-linux-gnu"); @@ -381,7 +370,6 @@ impl Builder { self.rustfmt_git_commit_hash = self.git_commit_hash("rustfmt", "x86_64-unknown-linux-gnu"); self.llvm_tools_git_commit_hash = self.git_commit_hash("llvm-tools", "x86_64-unknown-linux-gnu"); - self.lldb_git_commit_hash = self.git_commit_hash("lldb", "x86_64-unknown-linux-gnu"); self.miri_git_commit_hash = self.git_commit_hash("miri", "x86_64-unknown-linux-gnu"); self.check_toolstate(); @@ -456,7 +444,6 @@ impl Builder { package("rustfmt-preview", HOSTS); package("rust-analysis", TARGETS); package("llvm-tools-preview", TARGETS); - package("lldb-preview", TARGETS); } fn add_profiles_to(&mut self, manifest: &mut Manifest) { @@ -487,7 +474,6 @@ impl Builder { "rls-preview", "rust-src", "llvm-tools-preview", - "lldb-preview", "rust-analysis", "miri-preview", ], @@ -562,7 +548,6 @@ impl Builder { host_component("rls-preview"), host_component("rustfmt-preview"), host_component("llvm-tools-preview"), - host_component("lldb-preview"), host_component("rust-analysis"), ]); @@ -692,7 +677,6 @@ impl Builder { Clippy => format!("clippy-{}-{}.tar.gz", self.clippy_release, target), Rustfmt => format!("rustfmt-{}-{}.tar.gz", self.rustfmt_release, target), LlvmTools => format!("llvm-tools-{}-{}.tar.gz", self.llvm_tools_release, target), - Lldb => format!("lldb-{}-{}.tar.gz", self.lldb_release, target), Miri => format!("miri-{}-{}.tar.gz", self.miri_release, target), Other => format!("{}-{}-{}.tar.gz", component, self.rust_release, target), } @@ -706,7 +690,6 @@ impl Builder { Clippy => &self.clippy_version, Rustfmt => &self.rustfmt_version, LlvmTools => &self.llvm_tools_version, - Lldb => &self.lldb_version, Miri => &self.miri_version, _ => &self.rust_version, } @@ -720,7 +703,6 @@ impl Builder { Clippy => &self.clippy_git_commit_hash, Rustfmt => &self.rustfmt_git_commit_hash, LlvmTools => &self.llvm_tools_git_commit_hash, - Lldb => &self.lldb_git_commit_hash, Miri => &self.miri_git_commit_hash, _ => &self.rust_git_commit_hash, } From a5ba75283e279205dd96d402dfde42041ac53fb4 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Sun, 10 May 2020 16:53:48 -0400 Subject: [PATCH 103/203] Fail if I/O error occurs during testing --- src/tools/compiletest/src/main.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/tools/compiletest/src/main.rs b/src/tools/compiletest/src/main.rs index 3a8a5491255a..93a414ff6b9f 100644 --- a/src/tools/compiletest/src/main.rs +++ b/src/tools/compiletest/src/main.rs @@ -347,7 +347,10 @@ pub fn run_tests(config: Config) { Ok(true) => {} Ok(false) => panic!("Some tests failed"), Err(e) => { - println!("I/O failure during tests: {:?}", e); + // We don't know if tests passed or not, but if there was an error + // during testing we don't want to just suceeed (we may not have + // tested something), so fail. + panic!("I/O failure during tests: {:?}", e); } } } From 23d880b127c346be631d2a9dbcef3bd5dff7d305 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 10 May 2020 23:36:41 +0200 Subject: [PATCH 104/203] rustc_driver: factor out computing the exit code --- src/librustc_driver/lib.rs | 19 ++++++++++++------- src/tools/clippy/src/driver.rs | 4 +--- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index 913ccf8e6808..f8afaecf2185 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -1138,6 +1138,16 @@ pub fn catch_fatal_errors R, R>(f: F) -> Result }) } +/// Variant of `catch_fatal_errors` for the `interface::Result` return type +/// that also computes the exit code. +pub fn catch_with_exit_code(f: impl FnOnce() -> interface::Result<()>) -> i32 { + let result = catch_fatal_errors(f).and_then(|result| result); + match result { + Ok(()) => EXIT_SUCCESS, + Err(_) => EXIT_FAILURE, + } +} + lazy_static! { static ref DEFAULT_HOOK: Box) + Sync + Send + 'static> = { let hook = panic::take_hook(); @@ -1233,7 +1243,7 @@ pub fn main() { init_rustc_env_logger(); let mut callbacks = TimePassesCallbacks::default(); install_ice_hook(); - let result = catch_fatal_errors(|| { + let exit_code = catch_with_exit_code(|| { let args = env::args_os() .enumerate() .map(|(i, arg)| { @@ -1246,12 +1256,7 @@ pub fn main() { }) .collect::>(); run_compiler(&args, &mut callbacks, None, None) - }) - .and_then(|result| result); - let exit_code = match result { - Ok(_) => EXIT_SUCCESS, - Err(_) => EXIT_FAILURE, - }; + }); // The extra `\t` is necessary to align this label with the others. print_time_passes_entry(callbacks.time_passes, "\ttotal", start.elapsed()); process::exit(exit_code); diff --git a/src/tools/clippy/src/driver.rs b/src/tools/clippy/src/driver.rs index 2c699998ea90..1ce0300f2390 100644 --- a/src/tools/clippy/src/driver.rs +++ b/src/tools/clippy/src/driver.rs @@ -296,7 +296,7 @@ pub fn main() { rustc_driver::init_rustc_env_logger(); lazy_static::initialize(&ICE_HOOK); exit( - rustc_driver::catch_fatal_errors(move || { + rustc_driver::catch_with_exit_code(move || { let mut orig_args: Vec = env::args().collect(); if orig_args.iter().any(|a| a == "--version" || a == "-V") { @@ -411,7 +411,5 @@ pub fn main() { if clippy_enabled { &mut clippy } else { &mut default }; rustc_driver::run_compiler(&args, callbacks, None, None) }) - .and_then(|result| result) - .is_err() as i32, ) } From 7b649c7364f5128da33c34573a158477df030b70 Mon Sep 17 00:00:00 2001 From: Marko Mijalkovic Date: Sun, 10 May 2020 17:39:57 -0400 Subject: [PATCH 105/203] Renamed lld_link_script to link_script and support all GNU-like linkers --- src/librustc_codegen_ssa/back/link.rs | 19 +++++++++---------- src/librustc_target/spec/mipsel_sony_psp.rs | 3 ++- src/librustc_target/spec/mod.rs | 13 +++++++------ 3 files changed, 18 insertions(+), 17 deletions(-) diff --git a/src/librustc_codegen_ssa/back/link.rs b/src/librustc_codegen_ssa/back/link.rs index ab59a1c5f487..dca9f12df09b 100644 --- a/src/librustc_codegen_ssa/back/link.rs +++ b/src/librustc_codegen_ssa/back/link.rs @@ -1179,20 +1179,19 @@ fn add_pre_link_args( cmd.args(&sess.opts.debugging_opts.pre_link_args); } -/// Add an LLD link script embedded in the target, if applicable. -fn add_lld_link_script( +/// Add a link script embedded in the target, if applicable. +fn add_link_script( cmd: &mut dyn Linker, sess: &Session, - flavor: LinkerFlavor, tmpdir: &Path, crate_type: CrateType, ) { - match (flavor, crate_type, &sess.target.target.options.lld_link_script) { - ( - LinkerFlavor::Lld(LldFlavor::Ld), - CrateType::Cdylib | CrateType::Executable, - Some(script), - ) => { + match (crate_type, &sess.target.target.options.link_script) { + (CrateType::Cdylib | CrateType::Executable, Some(script)) => { + if !sess.target.target.options.linker_is_gnu { + sess.fatal("can only use link script when linking with GNU-like linker"); + } + let file_name = ["rustc", &sess.target.target.llvm_target, "linkfile.ld"].join("-"); let path = tmpdir.join(file_name); @@ -1450,7 +1449,7 @@ fn linker_with_args<'a, B: ArchiveBuilder<'a>>( add_pre_link_args(cmd, sess, flavor, crate_type); // NO-OPT-OUT - add_lld_link_script(cmd, sess, flavor, tmpdir, crate_type); + add_link_script(cmd, sess, tmpdir, crate_type); // NO-OPT-OUT, OBJECT-FILES-NO, AUDIT-ORDER if sess.target.target.options.is_like_fuchsia { diff --git a/src/librustc_target/spec/mipsel_sony_psp.rs b/src/librustc_target/spec/mipsel_sony_psp.rs index eb38dee63b68..0c74454d0c5f 100644 --- a/src/librustc_target/spec/mipsel_sony_psp.rs +++ b/src/librustc_target/spec/mipsel_sony_psp.rs @@ -27,6 +27,7 @@ pub fn target() -> TargetResult { cpu: "mips2".to_string(), executables: true, linker: Some("rust-lld".to_owned()), + linker_is_gnu: true, relocation_model: RelocModel::Static, // PSP FPU only supports single precision floats. @@ -35,7 +36,7 @@ pub fn target() -> TargetResult { // PSP does not support trap-on-condition instructions. llvm_args: vec!["-mno-check-zero-division".to_string()], pre_link_args, - lld_link_script: Some(LINKER_SCRIPT.to_string()), + link_script: Some(LINKER_SCRIPT.to_string()), ..Default::default() }, }) diff --git a/src/librustc_target/spec/mod.rs b/src/librustc_target/spec/mod.rs index 91dfa1550f62..00088a0d0404 100644 --- a/src/librustc_target/spec/mod.rs +++ b/src/librustc_target/spec/mod.rs @@ -668,9 +668,10 @@ pub struct TargetOptions { /// Linker arguments that are unconditionally passed *after* any /// user-defined libraries. pub post_link_args: LinkArgs, - /// Optional LLD link script applied to `dylib` and `executable` crate - /// types. This is a string containing the script, not a path. - pub lld_link_script: Option, + /// Optional link script applied to `dylib` and `executable` crate types. + /// This is a string containing the script, not a path. Can only be applied + /// to linkers where `linker_is_gnu` is true. + pub link_script: Option, /// Environment variables to be set for the linker invocation. pub link_env: Vec<(String, String)>, @@ -900,7 +901,7 @@ impl Default for TargetOptions { pre_link_args: LinkArgs::new(), pre_link_args_crt: LinkArgs::new(), post_link_args: LinkArgs::new(), - lld_link_script: None, + link_script: None, asm_args: Vec::new(), cpu: "generic".to_string(), features: String::new(), @@ -1250,7 +1251,7 @@ impl Target { key!(post_link_objects, list); key!(post_link_objects_crt, list); key!(post_link_args, link_args); - key!(lld_link_script, optional); + key!(link_script, optional); key!(link_env, env); key!(link_env_remove, list); key!(asm_args, list); @@ -1480,7 +1481,7 @@ impl ToJson for Target { target_option_val!(post_link_objects); target_option_val!(post_link_objects_crt); target_option_val!(link_args - post_link_args); - target_option_val!(lld_link_script); + target_option_val!(link_script); target_option_val!(env - link_env); target_option_val!(link_env_remove); target_option_val!(asm_args); From 744449433004fbdc3d0d665551e59ca2880f0552 Mon Sep 17 00:00:00 2001 From: Marko Mijalkovic Date: Sun, 10 May 2020 17:53:04 -0400 Subject: [PATCH 106/203] Run rustfmt --- src/librustc_codegen_ssa/back/link.rs | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/librustc_codegen_ssa/back/link.rs b/src/librustc_codegen_ssa/back/link.rs index dca9f12df09b..ca2d1b0488da 100644 --- a/src/librustc_codegen_ssa/back/link.rs +++ b/src/librustc_codegen_ssa/back/link.rs @@ -1180,12 +1180,7 @@ fn add_pre_link_args( } /// Add a link script embedded in the target, if applicable. -fn add_link_script( - cmd: &mut dyn Linker, - sess: &Session, - tmpdir: &Path, - crate_type: CrateType, -) { +fn add_link_script(cmd: &mut dyn Linker, sess: &Session, tmpdir: &Path, crate_type: CrateType) { match (crate_type, &sess.target.target.options.link_script) { (CrateType::Cdylib | CrateType::Executable, Some(script)) => { if !sess.target.target.options.linker_is_gnu { From 82e81191e44fc61c5b583608dd17d76fa8fdc06e Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 10 May 2020 23:55:41 +0200 Subject: [PATCH 107/203] update miri --- src/tools/miri | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/miri b/src/tools/miri index 7f3366288d12..4c7847961031 160000 --- a/src/tools/miri +++ b/src/tools/miri @@ -1 +1 @@ -Subproject commit 7f3366288d126408815eeafa8d7cd6e9f3ea56b9 +Subproject commit 4c784796103173c503e44fcdb12cb79ef0aba820 From 51e466de3cbfb94b7d0736066a765d8ea31394e4 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 11 May 2020 00:11:42 +0200 Subject: [PATCH 108/203] rustc_driver::main: more informative return type --- src/librustc_driver/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index f8afaecf2185..6847b175e60e 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -1238,7 +1238,7 @@ pub fn init_rustc_env_logger() { env_logger::init_from_env("RUSTC_LOG"); } -pub fn main() { +pub fn main() -> ! { let start = Instant::now(); init_rustc_env_logger(); let mut callbacks = TimePassesCallbacks::default(); @@ -1259,5 +1259,5 @@ pub fn main() { }); // The extra `\t` is necessary to align this label with the others. print_time_passes_entry(callbacks.time_passes, "\ttotal", start.elapsed()); - process::exit(exit_code); + process::exit(exit_code) } From 00dcb665e7ede908ba11638e8230340f396674f8 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Mon, 11 May 2020 00:16:16 +0300 Subject: [PATCH 109/203] cmdline: Make target features individually overridable --- src/doc/rustc/src/codegen-options/index.md | 10 +++++++++- src/librustc_session/options.rs | 16 +++++++++++++++- src/test/codegen/target-feature-multiple.rs | 9 +++++++++ 3 files changed, 33 insertions(+), 2 deletions(-) create mode 100644 src/test/codegen/target-feature-multiple.rs diff --git a/src/doc/rustc/src/codegen-options/index.md b/src/doc/rustc/src/codegen-options/index.md index dbe281be7df7..c638f88057a5 100644 --- a/src/doc/rustc/src/codegen-options/index.md +++ b/src/doc/rustc/src/codegen-options/index.md @@ -464,7 +464,15 @@ machine. Each target has a default base CPU. Individual targets will support different features; this flag lets you control enabling or disabling a feature. Each feature should be prefixed with a `+` to -enable it or `-` to disable it. Separate multiple features with commas. +enable it or `-` to disable it. + +Features from multiple `-C target-feature` options are combined. \ +Multiple features can be specified in a single option by separating them +with commas - `-C target-feature=+x,-y`. \ +If some feature is specified more than once with both `+` and `-`, +then values passed later override values passed earlier. \ +For example, `-C target-feature=+x,-y,+z -Ctarget-feature=-x,+y` +is equivalent to `-C target-feature=-x,+y,+z`. To see the valid options and an example of use, run `rustc --print target-features`. diff --git a/src/librustc_session/options.rs b/src/librustc_session/options.rs index 4eabb55e6dfe..ed7b2b3d58a7 100644 --- a/src/librustc_session/options.rs +++ b/src/librustc_session/options.rs @@ -270,6 +270,7 @@ macro_rules! options { "one of supported relocation models (`rustc --print relocation-models`)"; pub const parse_tls_model: &str = "one of supported TLS models (`rustc --print tls-models`)"; + pub const parse_target_feature: &str = parse_string; } #[allow(dead_code)] @@ -636,6 +637,19 @@ macro_rules! options { } true } + + fn parse_target_feature(slot: &mut String, v: Option<&str>) -> bool { + match v { + Some(s) => { + if !slot.is_empty() { + slot.push_str(","); + } + slot.push_str(s); + true + } + None => false, + } + } } ) } @@ -731,7 +745,7 @@ options! {CodegenOptions, CodegenSetter, basic_codegen_options, "use soft float ABI (*eabihf targets only) (default: no)"), target_cpu: Option = (None, parse_opt_string, [TRACKED], "select target processor (`rustc --print target-cpus` for details)"), - target_feature: String = (String::new(), parse_string, [TRACKED], + target_feature: String = (String::new(), parse_target_feature, [TRACKED], "target specific attributes. (`rustc --print target-features` for details). \ This feature is unsafe."), diff --git a/src/test/codegen/target-feature-multiple.rs b/src/test/codegen/target-feature-multiple.rs new file mode 100644 index 000000000000..f71a9c3c5821 --- /dev/null +++ b/src/test/codegen/target-feature-multiple.rs @@ -0,0 +1,9 @@ +// only-x86_64 +// compile-flags: -C target-feature=+sse2,-avx,+avx2 -C target-feature=+avx,-avx2 + +#![crate_type = "lib"] + +#[no_mangle] +pub fn foo() { + // CHECK: attributes #0 = { {{.*}}"target-features"="+sse2,-avx,+avx2,+avx,-avx2"{{.*}} } +} From a32463ade42d12de8da974796fb45a72e57721db Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Mon, 11 May 2020 02:10:25 +0200 Subject: [PATCH 110/203] Make MIR typeck use `LocalDefId` and fix docs --- src/librustc_mir/borrow_check/mod.rs | 2 +- src/librustc_mir/borrow_check/nll.rs | 8 +-- .../borrow_check/type_check/input_output.rs | 56 ++++++++++--------- .../borrow_check/type_check/mod.rs | 38 ++++++------- 4 files changed, 50 insertions(+), 54 deletions(-) diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index d3ab7df817b3..a3ee49651ba7 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -209,7 +209,7 @@ fn do_mir_borrowck<'a, 'tcx>( nll_errors, } = nll::compute_regions( infcx, - def_id.to_def_id(), + def_id, free_regions, body, &promoted, diff --git a/src/librustc_mir/borrow_check/nll.rs b/src/librustc_mir/borrow_check/nll.rs index 29636a067092..b820b79c47fe 100644 --- a/src/librustc_mir/borrow_check/nll.rs +++ b/src/librustc_mir/borrow_check/nll.rs @@ -2,7 +2,7 @@ use rustc_data_structures::fx::FxHashMap; use rustc_errors::Diagnostic; -use rustc_hir::def_id::DefId; +use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_index::vec::IndexVec; use rustc_infer::infer::InferCtxt; use rustc_middle::mir::{ @@ -157,7 +157,7 @@ fn populate_polonius_move_facts( /// This may result in errors being reported. pub(in crate::borrow_check) fn compute_regions<'cx, 'tcx>( infcx: &InferCtxt<'cx, 'tcx>, - def_id: DefId, + def_id: LocalDefId, universal_regions: UniversalRegions<'tcx>, body: &Body<'tcx>, promoted: &IndexVec>, @@ -272,7 +272,7 @@ pub(in crate::borrow_check) fn compute_regions<'cx, 'tcx>( // Dump facts if requested. let polonius_output = all_facts.and_then(|all_facts| { if infcx.tcx.sess.opts.debugging_opts.nll_facts { - let def_path = infcx.tcx.def_path(def_id); + let def_path = infcx.tcx.def_path(def_id.to_def_id()); let dir_path = PathBuf::from("nll-facts").join(def_path.to_filename_friendly_no_crate()); all_facts.write_to_dir(dir_path, location_table).unwrap(); @@ -292,7 +292,7 @@ pub(in crate::borrow_check) fn compute_regions<'cx, 'tcx>( // Solve the region constraints. let (closure_region_requirements, nll_errors) = - regioncx.solve(infcx, &body, def_id, polonius_output.clone()); + regioncx.solve(infcx, &body, def_id.to_def_id(), polonius_output.clone()); if !nll_errors.is_empty() { // Suppress unhelpful extra errors in `infer_opaque_types`. diff --git a/src/librustc_mir/borrow_check/type_check/input_output.rs b/src/librustc_mir/borrow_check/type_check/input_output.rs index 894a997ea7a4..edd2dc3c2de5 100644 --- a/src/librustc_mir/borrow_check/type_check/input_output.rs +++ b/src/librustc_mir/borrow_check/type_check/input_output.rs @@ -33,35 +33,37 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { // // e.g., `|x: FxHashMap<_, &'static u32>| ...` let user_provided_sig; - if !self.tcx().is_closure(self.mir_def_id) { + if !self.tcx().is_closure(self.mir_def_id.to_def_id()) { user_provided_sig = None; } else { - let typeck_tables = self.tcx().typeck_tables_of(self.mir_def_id.expect_local()); - user_provided_sig = match typeck_tables.user_provided_sigs.get(&self.mir_def_id) { - None => None, - Some(user_provided_poly_sig) => { - // Instantiate the canonicalized variables from - // user-provided signature (e.g., the `_` in the code - // above) with fresh variables. - let (poly_sig, _) = self.infcx.instantiate_canonical_with_fresh_inference_vars( - body.span, - &user_provided_poly_sig, - ); - - // Replace the bound items in the fn sig with fresh - // variables, so that they represent the view from - // "inside" the closure. - Some( - self.infcx - .replace_bound_vars_with_fresh_vars( + let typeck_tables = self.tcx().typeck_tables_of(self.mir_def_id); + user_provided_sig = + match typeck_tables.user_provided_sigs.get(&self.mir_def_id.to_def_id()) { + None => None, + Some(user_provided_poly_sig) => { + // Instantiate the canonicalized variables from + // user-provided signature (e.g., the `_` in the code + // above) with fresh variables. + let (poly_sig, _) = + self.infcx.instantiate_canonical_with_fresh_inference_vars( body.span, - LateBoundRegionConversionTime::FnCall, - &poly_sig, - ) - .0, - ) + &user_provided_poly_sig, + ); + + // Replace the bound items in the fn sig with fresh + // variables, so that they represent the view from + // "inside" the closure. + Some( + self.infcx + .replace_bound_vars_with_fresh_vars( + body.span, + LateBoundRegionConversionTime::FnCall, + &poly_sig, + ) + .0, + ) + } } - } }; debug!( @@ -120,7 +122,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { if let Err(terr) = self.eq_opaque_type_and_type( mir_output_ty, normalized_output_ty, - self.mir_def_id, + self.mir_def_id.to_def_id(), Locations::All(output_span), ConstraintCategory::BoringNoLocation, ) { @@ -143,7 +145,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { if let Err(err) = self.eq_opaque_type_and_type( mir_output_ty, user_provided_output_ty, - self.mir_def_id, + self.mir_def_id.to_def_id(), Locations::All(output_span), ConstraintCategory::BoringNoLocation, ) { diff --git a/src/librustc_mir/borrow_check/type_check/mod.rs b/src/librustc_mir/borrow_check/type_check/mod.rs index ee8a4358147c..9282a0a06b48 100644 --- a/src/librustc_mir/borrow_check/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/type_check/mod.rs @@ -108,26 +108,22 @@ mod relate_tys; /// /// - `infcx` -- inference context to use /// - `param_env` -- parameter environment to use for trait solving -/// - `mir` -- MIR to type-check -/// - `mir_def_id` -- DefId from which the MIR is derived (must be local) -/// - `region_bound_pairs` -- the implied outlives obligations between type parameters -/// and lifetimes (e.g., `&'a T` implies `T: 'a`) -/// - `implicit_region_bound` -- a region which all generic parameters are assumed -/// to outlive; should represent the fn body -/// - `input_tys` -- fully liberated, but **not** normalized, expected types of the arguments; -/// the types of the input parameters found in the MIR itself will be equated with these -/// - `output_ty` -- fully liberated, but **not** normalized, expected return type; -/// the type for the RETURN_PLACE will be equated with this -/// - `liveness` -- results of a liveness computation on the MIR; used to create liveness -/// constraints for the regions in the types of variables +/// - `body` -- MIR body to type-check +/// - `promoted` -- map of promoted constants within `body` +/// - `mir_def_id` -- `LocalDefId` from which the MIR is derived +/// - `universal_regions` -- the universal regions from `body`s function signature +/// - `location_table` -- MIR location map of `body` +/// - `borrow_set` -- information about borrows occurring in `body` +/// - `all_facts` -- when using Polonius, this is the generated set of Polonius facts /// - `flow_inits` -- results of a maybe-init dataflow analysis /// - `move_data` -- move-data constructed when performing the maybe-init dataflow analysis +/// - `elements` -- MIR region map pub(crate) fn type_check<'mir, 'tcx>( infcx: &InferCtxt<'_, 'tcx>, param_env: ty::ParamEnv<'tcx>, body: &Body<'tcx>, promoted: &IndexVec>, - mir_def_id: DefId, + mir_def_id: LocalDefId, universal_regions: &Rc>, location_table: &LocationTable, borrow_set: &BorrowSet<'tcx>, @@ -191,7 +187,7 @@ pub(crate) fn type_check<'mir, 'tcx>( fn type_check_internal<'a, 'tcx, R>( infcx: &'a InferCtxt<'a, 'tcx>, - mir_def_id: DefId, + mir_def_id: LocalDefId, param_env: ty::ParamEnv<'tcx>, body: &'a Body<'tcx>, promoted: &'a IndexVec>, @@ -271,7 +267,7 @@ struct TypeVerifier<'a, 'b, 'tcx> { body: &'b Body<'tcx>, promoted: &'b IndexVec>, last_span: Span, - mir_def_id: DefId, + mir_def_id: LocalDefId, errors_reported: bool, } @@ -815,7 +811,7 @@ struct TypeChecker<'a, 'tcx> { /// User type annotations are shared between the main MIR and the MIR of /// all of the promoted items. user_type_annotations: &'a CanonicalUserTypeAnnotations<'tcx>, - mir_def_id: DefId, + mir_def_id: LocalDefId, region_bound_pairs: &'a RegionBoundPairs<'tcx>, implicit_region_bound: ty::Region<'tcx>, reported_errors: FxHashSet<(Ty<'tcx>, Span)>, @@ -963,7 +959,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { fn new( infcx: &'a InferCtxt<'a, 'tcx>, body: &'a Body<'tcx>, - mir_def_id: DefId, + mir_def_id: LocalDefId, param_env: ty::ParamEnv<'tcx>, region_bound_pairs: &'a RegionBoundPairs<'tcx>, implicit_region_bound: ty::Region<'tcx>, @@ -1142,7 +1138,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { // When you have `let x: impl Foo = ...` in a closure, // the resulting inferend values are stored with the // def-id of the base function. - let parent_def_id = self.tcx().closure_base_def_id(self.mir_def_id); + let parent_def_id = self.tcx().closure_base_def_id(self.mir_def_id.to_def_id()); return self.eq_opaque_type_and_type(sub, sup, parent_def_id, locations, category); } else { return Err(terr); @@ -1994,7 +1990,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { if !self.infcx.type_is_copy_modulo_regions(self.param_env, ty, span) { let ccx = ConstCx::new_with_param_env( tcx, - self.mir_def_id.expect_local(), + self.mir_def_id, body, self.param_env, ); @@ -2010,9 +2006,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { &traits::Obligation::new( ObligationCause::new( span, - self.tcx() - .hir() - .local_def_id_to_hir_id(self.mir_def_id.expect_local()), + self.tcx().hir().local_def_id_to_hir_id(self.mir_def_id), traits::ObligationCauseCode::RepeatVec(should_suggest), ), self.param_env, From a1104b4dea0e0d3b35fa73c7f7c186f76b23db78 Mon Sep 17 00:00:00 2001 From: csmoe Date: Sun, 10 May 2020 22:34:20 +0800 Subject: [PATCH 111/203] bless ui tests --- src/librustc_hir/lang_items.rs | 1 + src/librustc_middle/hir/map/mod.rs | 6 +---- .../traits/error_reporting/suggestions.rs | 22 ++++++++++++++++--- .../incorrect-syntax-suggestions.stderr | 5 ++++- src/test/ui/async-await/issue-61076.rs | 2 +- src/test/ui/async-await/issue-61076.stderr | 15 +++++++++++++ 6 files changed, 41 insertions(+), 10 deletions(-) create mode 100644 src/test/ui/async-await/issue-61076.stderr diff --git a/src/librustc_hir/lang_items.rs b/src/librustc_hir/lang_items.rs index a503e3534e3b..53f72804a848 100644 --- a/src/librustc_hir/lang_items.rs +++ b/src/librustc_hir/lang_items.rs @@ -194,6 +194,7 @@ language_item_table! { ShrAssignTraitLangItem, "shr_assign", shr_assign_trait, Target::Trait; IndexTraitLangItem, "index", index_trait, Target::Trait; IndexMutTraitLangItem, "index_mut", index_mut_trait, Target::Trait; + UnsafeCellTypeLangItem, "unsafe_cell", unsafe_cell_type, Target::Struct; VaListTypeLangItem, "va_list", va_list, Target::Struct; diff --git a/src/librustc_middle/hir/map/mod.rs b/src/librustc_middle/hir/map/mod.rs index de0373c13849..a3f8cd1ee36f 100644 --- a/src/librustc_middle/hir/map/mod.rs +++ b/src/librustc_middle/hir/map/mod.rs @@ -390,11 +390,7 @@ impl<'hir> Map<'hir> { /// Given a `HirId`, returns the `BodyId` associated with it, /// if the node is a body owner, otherwise returns `None`. pub fn maybe_body_owned_by(&self, hir_id: HirId) -> Option { - if let Some(node) = self.find(hir_id) { - associated_body(node) - } else { - bug!("no entry for id `{}`", hir_id) - } + if let Some(node) = self.find(hir_id) { associated_body(node) } else { None } } /// Given a body owner's id, returns the `BodyId` associated with it. diff --git a/src/librustc_trait_selection/traits/error_reporting/suggestions.rs b/src/librustc_trait_selection/traits/error_reporting/suggestions.rs index b28f0001cd97..5e3b383ff258 100644 --- a/src/librustc_trait_selection/traits/error_reporting/suggestions.rs +++ b/src/librustc_trait_selection/traits/error_reporting/suggestions.rs @@ -1791,6 +1791,19 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { let body_hir_id = obligation.cause.body_id; let item_id = self.tcx.hir().get_parent_node(body_hir_id); + let mut is_future = false; + if let ty::Opaque(def_id, substs) = trait_ref.self_ty().kind { + let preds = self.tcx.predicates_of(def_id).instantiate(self.tcx, substs); + for p in preds.predicates { + if let Some(trait_ref) = p.to_opt_poly_trait_ref() { + if Some(trait_ref.def_id()) == self.tcx.lang_items().future_trait() { + is_future = true; + break; + } + } + } + } + if let Some(body_id) = self.tcx.hir().maybe_body_owned_by(item_id) { let body = self.tcx.hir().body(body_id); if let Some(hir::GeneratorKind::Async(_)) = body.generator_kind { @@ -1802,6 +1815,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { .next() .unwrap() .def_id; + debug!("trait_ref_self_ty: {:?}", trait_ref.self_ty()); // `::Output` let projection_ty = ty::ProjectionTy { // `T` @@ -1813,7 +1827,6 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { item_def_id, }; - //let cause = ObligationCause::misc(span, body_hir_id); let mut selcx = SelectionContext::new(self); let mut obligations = vec![]; @@ -1826,7 +1839,10 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { &mut obligations, ); - debug!("suggest_await_befor_try: normalized_projection_type {:?}", normalized_ty); + debug!( + "suggest_await_befor_try: normalized_projection_type {:?}", + self.resolve_vars_if_possible(&normalized_ty) + ); let try_obligation = self.mk_obligation_for_def_id( trait_ref.def_id(), normalized_ty, @@ -1834,7 +1850,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { obligation.param_env, ); debug!("suggest_await_befor_try: try_trait_obligation {:?}", try_obligation); - if self.predicate_may_hold(&try_obligation) { + if self.predicate_may_hold(&try_obligation) && is_future { if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) { if snippet.ends_with('?') { err.span_suggestion( diff --git a/src/test/ui/async-await/await-keyword/incorrect-syntax-suggestions.stderr b/src/test/ui/async-await/await-keyword/incorrect-syntax-suggestions.stderr index 61f2570b2ff9..96158fc0e049 100644 --- a/src/test/ui/async-await/await-keyword/incorrect-syntax-suggestions.stderr +++ b/src/test/ui/async-await/await-keyword/incorrect-syntax-suggestions.stderr @@ -237,7 +237,10 @@ error[E0277]: the `?` operator can only be applied to values that implement `std --> $DIR/incorrect-syntax-suggestions.rs:16:19 | LL | let _ = await bar()?; - | ^^^^^^ the `?` operator cannot be applied to type `impl std::future::Future` + | ^^^^^^ + | | + | the `?` operator cannot be applied to type `impl std::future::Future` + | help: consider using `.await` here: `bar().await?` | = help: the trait `std::ops::Try` is not implemented for `impl std::future::Future` = note: required by `std::ops::Try::into_result` diff --git a/src/test/ui/async-await/issue-61076.rs b/src/test/ui/async-await/issue-61076.rs index 0c6c53119977..04a9148ae241 100644 --- a/src/test/ui/async-await/issue-61076.rs +++ b/src/test/ui/async-await/issue-61076.rs @@ -5,7 +5,7 @@ async fn foo() -> Result<(), ()> { } async fn bar() -> Result<(), ()> { - foo()?; + foo()?; //~ ERROR the `?` operator can only be applied to values that implement `std::ops::Try` Ok(()) } diff --git a/src/test/ui/async-await/issue-61076.stderr b/src/test/ui/async-await/issue-61076.stderr new file mode 100644 index 000000000000..fb1eead04e6b --- /dev/null +++ b/src/test/ui/async-await/issue-61076.stderr @@ -0,0 +1,15 @@ +error[E0277]: the `?` operator can only be applied to values that implement `std::ops::Try` + --> $DIR/issue-61076.rs:8:5 + | +LL | foo()?; + | ^^^^^^ + | | + | the `?` operator cannot be applied to type `impl std::future::Future` + | help: consider using `.await` here: `foo().await?` + | + = help: the trait `std::ops::Try` is not implemented for `impl std::future::Future` + = note: required by `std::ops::Try::into_result` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. From 42f70d503b9a6c87ebb84e44842e421ef01a0421 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 11 May 2020 12:13:53 +0200 Subject: [PATCH 112/203] update miri some more --- src/bootstrap/test.rs | 1 - src/tools/miri | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index ad3fd0d64a30..975650132652 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -436,7 +436,6 @@ impl Step for Miri { // miri tests need to know about the stage sysroot cargo.env("MIRI_SYSROOT", miri_sysroot); - cargo.env("RUSTC_TEST_SUITE", builder.rustc(compiler)); cargo.env("RUSTC_LIB_PATH", builder.rustc_libdir(compiler)); cargo.env("MIRI_PATH", miri); diff --git a/src/tools/miri b/src/tools/miri index 4c7847961031..10419b3f2fc6 160000 --- a/src/tools/miri +++ b/src/tools/miri @@ -1 +1 @@ -Subproject commit 4c784796103173c503e44fcdb12cb79ef0aba820 +Subproject commit 10419b3f2fc625bb9d746c16d768e433a894484d From 806f09cf21129ec92c975e99443850d376281e04 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 11 May 2020 13:22:56 +0200 Subject: [PATCH 113/203] Clean up E0579 explanation --- src/librustc_error_codes/error_codes/E0579.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/librustc_error_codes/error_codes/E0579.md b/src/librustc_error_codes/error_codes/E0579.md index 225e27f0cab8..f554242a3d46 100644 --- a/src/librustc_error_codes/error_codes/E0579.md +++ b/src/librustc_error_codes/error_codes/E0579.md @@ -1,7 +1,4 @@ -When matching against an exclusive range, the compiler verifies that the range -is non-empty. Exclusive range patterns include the start point but not the end -point, so this is equivalent to requiring the start of the range to be less -than the end of the range. +A lower range wasn't less than the upper range. Erroneous code example: @@ -17,3 +14,8 @@ fn main() { } } ``` + +When matching against an exclusive range, the compiler verifies that the range +is non-empty. Exclusive range patterns include the start point but not the end +point, so this is equivalent to requiring the start of the range to be less +than the end of the range. From 5e354932fe2e2b6b4f55f404148e6b5fa0a3392a Mon Sep 17 00:00:00 2001 From: Igor Matuszewski Date: Tue, 5 May 2020 13:26:02 +0200 Subject: [PATCH 114/203] cargo update -p serde_derive --- Cargo.lock | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 033ebc884a3e..012d3328f12c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4630,13 +4630,13 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.81" +version = "1.0.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "477b13b646f5b5b56fc95bedfc3b550d12141ce84f466f6c44b9a17589923885" +checksum = "9e549e3abf4fb8621bd1609f11dfc9f5e50320802273b12f3811a67e6716ea6c" dependencies = [ - "proc-macro2 0.4.30", - "quote 0.6.12", - "syn 0.15.35", + "proc-macro2 1.0.3", + "quote 1.0.2", + "syn 1.0.11", ] [[package]] From 403a9d0867ca01a5aecbe88b535ed902a9d4a633 Mon Sep 17 00:00:00 2001 From: Igor Matuszewski Date: Tue, 5 May 2020 13:26:16 +0200 Subject: [PATCH 115/203] cargo update -p failure_derive --- Cargo.lock | 30 +++++++++--------------------- 1 file changed, 9 insertions(+), 21 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 012d3328f12c..f05a1562d0df 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -438,7 +438,7 @@ dependencies = [ "proc-macro2 1.0.3", "quote 1.0.2", "syn 1.0.11", - "synstructure 0.12.1", + "synstructure", ] [[package]] @@ -1145,14 +1145,14 @@ dependencies = [ [[package]] name = "failure_derive" -version = "0.1.5" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea1063915fd7ef4309e222a5a07cf9c319fb9c7836b1f89b85458672dbb127e1" +checksum = "aa4da3c766cd7a0db8242e326e9e4e081edd567072893ed320008189715366a4" dependencies = [ - "proc-macro2 0.4.30", - "quote 0.6.12", - "syn 0.15.35", - "synstructure 0.10.2", + "proc-macro2 1.0.3", + "quote 1.0.2", + "syn 1.0.11", + "synstructure", ] [[package]] @@ -3449,7 +3449,7 @@ dependencies = [ "proc-macro2 1.0.3", "quote 1.0.2", "syn 1.0.11", - "synstructure 0.12.1", + "synstructure", ] [[package]] @@ -4059,7 +4059,7 @@ dependencies = [ "proc-macro2 1.0.3", "quote 1.0.2", "syn 1.0.11", - "synstructure 0.12.1", + "synstructure", ] [[package]] @@ -4932,18 +4932,6 @@ dependencies = [ "unicode-xid 0.2.0", ] -[[package]] -name = "synstructure" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02353edf96d6e4dc81aea2d8490a7e9db177bf8acb0e951c24940bf866cb313f" -dependencies = [ - "proc-macro2 0.4.30", - "quote 0.6.12", - "syn 0.15.35", - "unicode-xid 0.1.0", -] - [[package]] name = "synstructure" version = "0.12.1" From 8c6e568141977702a43d70e0bf0258d32ef71f76 Mon Sep 17 00:00:00 2001 From: Igor Matuszewski Date: Tue, 5 May 2020 13:26:29 +0200 Subject: [PATCH 116/203] cargo update -p pest_generator --- Cargo.lock | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f05a1562d0df..51a166890bd5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2557,15 +2557,15 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.1.0" +version = "2.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63120576c4efd69615b5537d3d052257328a4ca82876771d6944424ccfd9f646" +checksum = "99b8db626e31e5b81787b9783425769681b347011cc59471e33ea46d2ea0cf55" dependencies = [ "pest", "pest_meta", - "proc-macro2 0.4.30", - "quote 0.6.12", - "syn 0.15.35", + "proc-macro2 1.0.3", + "quote 1.0.2", + "syn 1.0.11", ] [[package]] From 3bdacedfd9264549b6368cc060da16993701ec14 Mon Sep 17 00:00:00 2001 From: Igor Matuszewski Date: Tue, 5 May 2020 13:30:49 +0200 Subject: [PATCH 117/203] cargo update -p derive-new --- Cargo.lock | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 51a166890bd5..43dcc6b9dae9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -938,13 +938,13 @@ checksum = "a0afaad2b26fa326569eb264b1363e8ae3357618c43982b3f285f0774ce76b69" [[package]] name = "derive-new" -version = "0.5.6" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ca414e896ae072546f4d789f452daaecf60ddee4c9df5dc6d5936d769e3d87c" +checksum = "71f31892cd5c62e414316f2963c5689242c43d8e7bbcaaeca97e5e28c95d91d9" dependencies = [ - "proc-macro2 0.4.30", - "quote 0.6.12", - "syn 0.15.35", + "proc-macro2 1.0.3", + "quote 1.0.2", + "syn 1.0.11", ] [[package]] From e26f35d343c1266012af31437a84e40eb33eaffb Mon Sep 17 00:00:00 2001 From: Igor Matuszewski Date: Tue, 5 May 2020 14:05:06 +0200 Subject: [PATCH 118/203] rustbook: Bump mdbook dependency --- Cargo.lock | 26 +++++++------------------- src/tools/rustbook/Cargo.toml | 2 +- 2 files changed, 8 insertions(+), 20 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 43dcc6b9dae9..cbdd43f75863 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1405,30 +1405,18 @@ dependencies = [ [[package]] name = "handlebars" -version = "2.0.1" +version = "3.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df044dd42cdb7e32f28557b661406fc0f2494be75199779998810dbc35030e0d" +checksum = "ba758d094d31274eb49d15da6f326b96bf3185239a6359bf684f3d5321148900" dependencies = [ - "hashbrown 0.5.0", - "lazy_static 1.4.0", "log", "pest", "pest_derive", "quick-error", - "regex", "serde", "serde_json", ] -[[package]] -name = "hashbrown" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1de41fb8dba9714efd92241565cdff73f78508c95697dd56787d3cba27e2353" -dependencies = [ - "serde", -] - [[package]] name = "hashbrown" version = "0.6.2" @@ -2055,9 +2043,9 @@ dependencies = [ [[package]] name = "mdbook" -version = "0.3.5" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "031bdd9d4893c983e2f69ebc4b59070feee8276a584c4aabdcb351235ea28016" +checksum = "e7ec525f7ebccc2dd935c263717250cd37f9a4b264a77c5dbc950ea2734d8159" dependencies = [ "ammonia", "chrono", @@ -2785,9 +2773,9 @@ checksum = "6ddd112cca70a4d30883b2d21568a1d376ff8be4758649f64f973c6845128ad3" [[package]] name = "quick-error" -version = "1.2.2" +version = "1.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0" +checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" [[package]] name = "quine-mc_cluskey" @@ -4800,7 +4788,7 @@ dependencies = [ "core", "dlmalloc", "fortanix-sgx-abi", - "hashbrown 0.6.2", + "hashbrown", "hermit-abi", "libc", "panic_abort", diff --git a/src/tools/rustbook/Cargo.toml b/src/tools/rustbook/Cargo.toml index e6e758dccdf0..ff41197faa1a 100644 --- a/src/tools/rustbook/Cargo.toml +++ b/src/tools/rustbook/Cargo.toml @@ -23,6 +23,6 @@ codespan-reporting = { version = "0.5", optional = true } rustc-workspace-hack = "1.0.0" [dependencies.mdbook] -version = "0.3.0" +version = "0.3.7" default-features = false features = ["search"] From 7bea58eeac3a5a5280810623f06eadb3a8b891a3 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 3 May 2020 12:34:53 +0200 Subject: [PATCH 119/203] fix test_weak_count_locked for Miri --- src/liballoc/sync/tests.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/liballoc/sync/tests.rs b/src/liballoc/sync/tests.rs index 4a5cc9aa5910..a2bb651e2b77 100644 --- a/src/liballoc/sync/tests.rs +++ b/src/liballoc/sync/tests.rs @@ -340,7 +340,9 @@ fn test_weak_count_locked() { let mut a = Arc::new(atomic::AtomicBool::new(false)); let a2 = a.clone(); let t = thread::spawn(move || { - for _i in 0..1000000 { + // Miri is too slow + let count = if cfg!(miri) { 1000 } else { 1000000 }; + for _i in 0..count { Arc::get_mut(&mut a); } a.store(true, SeqCst); @@ -349,6 +351,8 @@ fn test_weak_count_locked() { while !a2.load(SeqCst) { let n = Arc::weak_count(&a2); assert!(n < 2, "bad weak count: {}", n); + #[cfg(miri)] // Miri's scheduler does not guarantee liveness, and thus needs this hint. + atomic::spin_loop_hint(); } t.join().unwrap(); } From 9a4e7183d4a6c31b32beca1a82095480ea32e359 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Mon, 11 May 2020 10:50:53 -0400 Subject: [PATCH 120/203] Configure cache domain for GHA --- .github/workflows/ci.yml | 4 ++++ src/ci/github-actions/ci.yml | 2 ++ 2 files changed, 6 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 366ea0ebbe5c..291dbf603612 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -34,6 +34,7 @@ jobs: CI_JOB_NAME: "${{ matrix.name }}" SCCACHE_BUCKET: rust-lang-gha-caches TOOLSTATE_REPO: "https://github.com/pietroalbini/rust-toolstate" + CACHE_DOMAIN: ci-caches-gha.rust-lang.org if: "github.event_name == 'pull_request'" strategy: matrix: @@ -146,6 +147,7 @@ jobs: TOOLSTATE_PUBLISH: 1 CACHES_AWS_ACCESS_KEY_ID: AKIA46X5W6CZOMUQATD5 ARTIFACTS_AWS_ACCESS_KEY_ID: AKIA46X5W6CZH5AYXDVF + CACHE_DOMAIN: ci-caches-gha.rust-lang.org if: "github.event_name == 'push' && github.ref == 'refs/heads/try' && github.repository == 'rust-lang-ci/rust'" strategy: matrix: @@ -255,6 +257,7 @@ jobs: TOOLSTATE_PUBLISH: 1 CACHES_AWS_ACCESS_KEY_ID: AKIA46X5W6CZOMUQATD5 ARTIFACTS_AWS_ACCESS_KEY_ID: AKIA46X5W6CZH5AYXDVF + CACHE_DOMAIN: ci-caches-gha.rust-lang.org if: "github.event_name == 'push' && github.ref == 'refs/heads/auto' && github.repository == 'rust-lang-ci/rust'" strategy: matrix: @@ -606,6 +609,7 @@ jobs: TOOLSTATE_PUBLISH: 1 CACHES_AWS_ACCESS_KEY_ID: AKIA46X5W6CZOMUQATD5 ARTIFACTS_AWS_ACCESS_KEY_ID: AKIA46X5W6CZH5AYXDVF + CACHE_DOMAIN: ci-caches-gha.rust-lang.org if: "github.event_name == 'push' && github.ref == 'refs/heads/master' && github.repository == 'rust-lang-ci/rust'" steps: - name: checkout the source code diff --git a/src/ci/github-actions/ci.yml b/src/ci/github-actions/ci.yml index 647da7c8a7ea..1c120f816345 100644 --- a/src/ci/github-actions/ci.yml +++ b/src/ci/github-actions/ci.yml @@ -37,6 +37,7 @@ x--expand-yaml-anchors--remove: - &public-variables SCCACHE_BUCKET: rust-lang-gha-caches TOOLSTATE_REPO: https://github.com/pietroalbini/rust-toolstate + CACHE_DOMAIN: ci-caches-gha.rust-lang.org - &prod-variables SCCACHE_BUCKET: rust-lang-gha-caches @@ -51,6 +52,7 @@ x--expand-yaml-anchors--remove: # (caches, artifacts...). CACHES_AWS_ACCESS_KEY_ID: AKIA46X5W6CZOMUQATD5 ARTIFACTS_AWS_ACCESS_KEY_ID: AKIA46X5W6CZH5AYXDVF + CACHE_DOMAIN: ci-caches-gha.rust-lang.org - &base-job env: {} From 8bfd84539e847b9ac9d7c811a370a9c3840d6c3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Mon, 11 May 2020 13:01:37 +0200 Subject: [PATCH 121/203] Fix clippy warnings Fixes clippy::{cone_on_copy, filter_next, redundant_closure, single_char_pattern, len_zero,redundant_field_names, useless_format, identity_conversion, map_clone, into_iter_on_ref, needless_return, option_as_ref_deref, unused_unit, unnecessary_mut_passed} --- src/librustc_attr/builtin.rs | 2 +- src/librustc_data_structures/tiny_list.rs | 4 +- src/librustc_infer/traits/util.rs | 5 +- src/librustc_interface/queries.rs | 2 +- src/librustc_middle/dep_graph/mod.rs | 4 +- src/librustc_middle/hir/mod.rs | 3 +- src/librustc_middle/ty/mod.rs | 2 +- src/librustc_middle/ty/trait_def.rs | 5 +- .../hair/pattern/check_match.rs | 2 +- .../hair/pattern/const_to_pat.rs | 2 +- src/librustc_passes/liveness.rs | 4 +- src/librustc_passes/region.rs | 2 +- .../dep_graph/dep_node.rs | 2 +- src/librustc_query_system/dep_graph/mod.rs | 4 +- .../traits/chalk_fulfill.rs | 8 +-- .../traits/error_reporting/suggestions.rs | 2 +- src/librustc_traits/chalk/db.rs | 72 +++++++++---------- src/librustc_traits/chalk/lowering.rs | 4 +- src/librustdoc/config.rs | 2 +- src/librustdoc/core.rs | 2 +- src/librustdoc/html/render.rs | 5 +- src/librustdoc/test.rs | 3 +- src/libstd/thread/mod.rs | 2 +- src/libtest/cli.rs | 4 +- 24 files changed, 68 insertions(+), 79 deletions(-) diff --git a/src/librustc_attr/builtin.rs b/src/librustc_attr/builtin.rs index a592bbc2bf91..af09779d072c 100644 --- a/src/librustc_attr/builtin.rs +++ b/src/librustc_attr/builtin.rs @@ -634,7 +634,7 @@ pub fn eval_condition( [NestedMetaItem::Literal(Lit { span, .. }) | NestedMetaItem::MetaItem(MetaItem { span, .. })] => { sess.span_diagnostic - .struct_span_err(*span, &*format!("expected a version literal")) + .struct_span_err(*span, "expected a version literal") .emit(); return false; } diff --git a/src/librustc_data_structures/tiny_list.rs b/src/librustc_data_structures/tiny_list.rs index 78cbc1240b18..e94a0c6eb594 100644 --- a/src/librustc_data_structures/tiny_list.rs +++ b/src/librustc_data_structures/tiny_list.rs @@ -52,7 +52,7 @@ impl TinyList { if &e.data == data { return true; } - elem = e.next.as_ref().map(|e| &**e); + elem = e.next.as_deref(); } false } @@ -62,7 +62,7 @@ impl TinyList { let (mut elem, mut count) = (self.head.as_ref(), 0); while let Some(ref e) = elem { count += 1; - elem = e.next.as_ref().map(|e| &**e); + elem = e.next.as_deref(); } count } diff --git a/src/librustc_infer/traits/util.rs b/src/librustc_infer/traits/util.rs index 55bea57f3e24..b34685006e22 100644 --- a/src/librustc_infer/traits/util.rs +++ b/src/librustc_infer/traits/util.rs @@ -112,8 +112,7 @@ pub fn elaborate_predicates<'tcx>( tcx: TyCtxt<'tcx>, predicates: impl Iterator>, ) -> Elaborator<'tcx> { - let obligations = - predicates.into_iter().map(|predicate| predicate_obligation(predicate, None)).collect(); + let obligations = predicates.map(|predicate| predicate_obligation(predicate, None)).collect(); elaborate_obligations(tcx, obligations) } @@ -149,7 +148,7 @@ impl Elaborator<'tcx> { // Get predicates declared on the trait. let predicates = tcx.super_predicates_of(data.def_id()); - let obligations = predicates.predicates.into_iter().map(|(pred, span)| { + let obligations = predicates.predicates.iter().map(|(pred, span)| { predicate_obligation( pred.subst_supertrait(tcx, &data.to_poly_trait_ref()), Some(*span), diff --git a/src/librustc_interface/queries.rs b/src/librustc_interface/queries.rs index 9e8f3a84e20e..94cd4bcd4c62 100644 --- a/src/librustc_interface/queries.rs +++ b/src/librustc_interface/queries.rs @@ -137,7 +137,7 @@ impl<'tcx> Queries<'tcx> { let result = passes::register_plugins( self.session(), &*self.codegen_backend().metadata_loader(), - self.compiler.register_lints.as_ref().map(|p| &**p).unwrap_or_else(|| empty), + self.compiler.register_lints.as_deref().unwrap_or_else(|| empty), krate, &crate_name, ); diff --git a/src/librustc_middle/dep_graph/mod.rs b/src/librustc_middle/dep_graph/mod.rs index f997df25e991..682b335c5d07 100644 --- a/src/librustc_middle/dep_graph/mod.rs +++ b/src/librustc_middle/dep_graph/mod.rs @@ -72,9 +72,9 @@ impl rustc_query_system::dep_graph::DepKind for DepKind { }) } - fn read_deps(op: OP) -> () + fn read_deps(op: OP) where - OP: for<'a> FnOnce(Option<&'a Lock>) -> (), + OP: for<'a> FnOnce(Option<&'a Lock>), { ty::tls::with_context_opt(|icx| { let icx = if let Some(icx) = icx { icx } else { return }; diff --git a/src/librustc_middle/hir/mod.rs b/src/librustc_middle/hir/mod.rs index 7ab66411b210..1e3676496ce3 100644 --- a/src/librustc_middle/hir/mod.rs +++ b/src/librustc_middle/hir/mod.rs @@ -78,7 +78,6 @@ pub fn provide(providers: &mut Providers<'_>) { &tcx.untracked_crate.modules[&module] }; providers.hir_owner = |tcx, id| tcx.index_hir(LOCAL_CRATE).map[id].signature; - providers.hir_owner_nodes = - |tcx, id| tcx.index_hir(LOCAL_CRATE).map[id].with_bodies.as_ref().map(|nodes| &**nodes); + providers.hir_owner_nodes = |tcx, id| tcx.index_hir(LOCAL_CRATE).map[id].with_bodies.as_deref(); map::provide(providers); } diff --git a/src/librustc_middle/ty/mod.rs b/src/librustc_middle/ty/mod.rs index 02fe7adcd073..571e50f5ae26 100644 --- a/src/librustc_middle/ty/mod.rs +++ b/src/librustc_middle/ty/mod.rs @@ -280,7 +280,7 @@ impl<'tcx> AssociatedItems<'tcx> { &self, name: Symbol, ) -> impl '_ + Iterator { - self.items.get_by_key(&name).map(|v| *v) + self.items.get_by_key(&name).copied() } /// Returns an iterator over all associated items with the given name. diff --git a/src/librustc_middle/ty/trait_def.rs b/src/librustc_middle/ty/trait_def.rs index 89bcb240d901..8f125098ee68 100644 --- a/src/librustc_middle/ty/trait_def.rs +++ b/src/librustc_middle/ty/trait_def.rs @@ -171,10 +171,7 @@ impl<'tcx> TyCtxt<'tcx> { pub fn all_impls(self, def_id: DefId) -> impl Iterator + 'tcx { let TraitImpls { blanket_impls, non_blanket_impls } = self.trait_impls_of(def_id); - blanket_impls - .into_iter() - .chain(non_blanket_impls.into_iter().map(|(_, v)| v).flatten()) - .cloned() + blanket_impls.iter().chain(non_blanket_impls.iter().map(|(_, v)| v).flatten()).cloned() } } diff --git a/src/librustc_mir_build/hair/pattern/check_match.rs b/src/librustc_mir_build/hair/pattern/check_match.rs index 0f22288437ca..65ff311d1821 100644 --- a/src/librustc_mir_build/hair/pattern/check_match.rs +++ b/src/librustc_mir_build/hair/pattern/check_match.rs @@ -246,7 +246,7 @@ impl<'tcx> MatchVisitor<'_, 'tcx> { ); } - adt_defined_here(&mut cx, &mut err, pattern_ty, &witnesses); + adt_defined_here(&cx, &mut err, pattern_ty, &witnesses); err.note(&format!("the matched value is of type `{}`", pattern_ty)); err.emit(); } diff --git a/src/librustc_mir_build/hair/pattern/const_to_pat.rs b/src/librustc_mir_build/hair/pattern/const_to_pat.rs index 4cc6a27a6da9..854f8eeaf344 100644 --- a/src/librustc_mir_build/hair/pattern/const_to_pat.rs +++ b/src/librustc_mir_build/hair/pattern/const_to_pat.rs @@ -121,7 +121,7 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> { ) } traits::NonStructuralMatchTy::Dynamic => { - format!("trait objects cannot be used in patterns") + "trait objects cannot be used in patterns".to_string() } traits::NonStructuralMatchTy::Param => { bug!("use of constant whose type is a parameter inside a pattern") diff --git a/src/librustc_passes/liveness.rs b/src/librustc_passes/liveness.rs index 75ac8e731b5d..6e7d116ce1d7 100644 --- a/src/librustc_passes/liveness.rs +++ b/src/librustc_passes/liveness.rs @@ -931,7 +931,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { if blk.targeted_by_break { self.break_ln.insert(blk.hir_id, succ); } - let succ = self.propagate_through_opt_expr(blk.expr.as_ref().map(|e| &**e), succ); + let succ = self.propagate_through_opt_expr(blk.expr.as_deref(), succ); blk.stmts.iter().rev().fold(succ, |succ, stmt| self.propagate_through_stmt(stmt, succ)) } @@ -952,7 +952,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { // initialization, which is mildly more complex than checking // once at the func header but otherwise equivalent. - let succ = self.propagate_through_opt_expr(local.init.as_ref().map(|e| &**e), succ); + let succ = self.propagate_through_opt_expr(local.init.as_deref(), succ); self.define_bindings_in_pat(&local.pat, succ) } hir::StmtKind::Item(..) => succ, diff --git a/src/librustc_passes/region.rs b/src/librustc_passes/region.rs index 927e6a7e712b..a6fa677cbc0a 100644 --- a/src/librustc_passes/region.rs +++ b/src/librustc_passes/region.rs @@ -797,7 +797,7 @@ impl<'tcx> Visitor<'tcx> for RegionResolutionVisitor<'tcx> { resolve_expr(self, ex); } fn visit_local(&mut self, l: &'tcx Local<'tcx>) { - resolve_local(self, Some(&l.pat), l.init.as_ref().map(|e| &**e)); + resolve_local(self, Some(&l.pat), l.init.as_deref()); } } diff --git a/src/librustc_query_system/dep_graph/dep_node.rs b/src/librustc_query_system/dep_graph/dep_node.rs index 36343365ab6c..d8875f8ac64a 100644 --- a/src/librustc_query_system/dep_graph/dep_node.rs +++ b/src/librustc_query_system/dep_graph/dep_node.rs @@ -80,7 +80,7 @@ impl DepNode { } } - return dep_node; + dep_node } } diff --git a/src/librustc_query_system/dep_graph/mod.rs b/src/librustc_query_system/dep_graph/mod.rs index f85462eb78bd..e8d02692f37b 100644 --- a/src/librustc_query_system/dep_graph/mod.rs +++ b/src/librustc_query_system/dep_graph/mod.rs @@ -77,9 +77,9 @@ pub trait DepKind: Copy + fmt::Debug + Eq + Ord + Hash { OP: FnOnce() -> R; /// Access dependencies from current implicit context. - fn read_deps(op: OP) -> () + fn read_deps(op: OP) where - OP: for<'a> FnOnce(Option<&'a Lock>>) -> (); + OP: for<'a> FnOnce(Option<&'a Lock>>); fn can_reconstruct_query_key(&self) -> bool; } diff --git a/src/librustc_trait_selection/traits/chalk_fulfill.rs b/src/librustc_trait_selection/traits/chalk_fulfill.rs index 115e4a0e6296..be0512dcac95 100644 --- a/src/librustc_trait_selection/traits/chalk_fulfill.rs +++ b/src/librustc_trait_selection/traits/chalk_fulfill.rs @@ -39,7 +39,7 @@ fn environment<'tcx>( let ty::InstantiatedPredicates { predicates, .. } = tcx.predicates_of(def_id).instantiate_identity(tcx); - let clauses = predicates.into_iter().map(|pred| ChalkEnvironmentClause::Predicate(pred)); + let clauses = predicates.into_iter().map(ChalkEnvironmentClause::Predicate); let hir_id = tcx.hir().as_local_hir_id(def_id.expect_local()); let node = tcx.hir().get(hir_id); @@ -224,7 +224,7 @@ impl TraitEngine<'tcx> for FulfillmentContext<'tcx> { ), Err(_err) => errors.push(FulfillmentError { - obligation: obligation, + obligation, code: FulfillmentErrorCode::CodeSelectionError( SelectionError::Unimplemented, ), @@ -238,7 +238,7 @@ impl TraitEngine<'tcx> for FulfillmentContext<'tcx> { } Err(NoSolution) => errors.push(FulfillmentError { - obligation: obligation, + obligation, code: FulfillmentErrorCode::CodeSelectionError( SelectionError::Unimplemented, ), @@ -257,6 +257,6 @@ impl TraitEngine<'tcx> for FulfillmentContext<'tcx> { } fn pending_obligations(&self) -> Vec> { - self.obligations.iter().map(|obligation| obligation.clone()).collect() + self.obligations.iter().cloned().collect() } } diff --git a/src/librustc_trait_selection/traits/error_reporting/suggestions.rs b/src/librustc_trait_selection/traits/error_reporting/suggestions.rs index 74dd47a91c27..4228c2342cc6 100644 --- a/src/librustc_trait_selection/traits/error_reporting/suggestions.rs +++ b/src/librustc_trait_selection/traits/error_reporting/suggestions.rs @@ -1854,7 +1854,7 @@ impl NextTypeParamName for &[hir::GenericParam<'_>] { fn next_type_param_name(&self, name: Option<&str>) -> String { // This is the whitelist of possible parameter names that we might suggest. let name = name.and_then(|n| n.chars().next()).map(|c| c.to_string().to_uppercase()); - let name = name.as_ref().map(|s| s.as_str()); + let name = name.as_deref(); let possible_names = [name.unwrap_or("T"), "T", "U", "V", "X", "Y", "Z", "A", "B", "C"]; let used_names = self .iter() diff --git a/src/librustc_traits/chalk/db.rs b/src/librustc_traits/chalk/db.rs index 0cec583bb566..a2aee9b6ef74 100644 --- a/src/librustc_traits/chalk/db.rs +++ b/src/librustc_traits/chalk/db.rs @@ -59,7 +59,7 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t // clauses or bounds? let predicates = self.tcx.predicates_defined_on(def_id).predicates; let where_clauses: Vec<_> = predicates - .into_iter() + .iter() .map(|(wc, _)| wc.subst(self.tcx, &bound_vars)) .filter_map(|wc| LowerInto::>>>::lower_into(wc, &self.interner)).collect(); @@ -88,7 +88,7 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t let binders = binders_for(&self.interner, bound_vars); let predicates = self.tcx.predicates_defined_on(def_id).predicates; let where_clauses: Vec<_> = predicates - .into_iter() + .iter() .map(|(wc, _)| wc.subst(self.tcx, &bound_vars)) .filter_map(|wc| LowerInto::>>>::lower_into(wc, &self.interner)).collect(); @@ -134,7 +134,7 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t let predicates = self.tcx.predicates_of(adt_def_id).predicates; let where_clauses: Vec<_> = predicates - .into_iter() + .iter() .map(|(wc, _)| wc.subst(self.tcx, bound_vars)) .filter_map(|wc| LowerInto::>>>::lower_into(wc, &self.interner)) .collect(); @@ -166,46 +166,42 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t fundamental: adt_def.is_fundamental(), }, }); - return struct_datum; + struct_datum } - RustDefId::Ref(_) => { - return Arc::new(chalk_rust_ir::StructDatum { - id: struct_id, - binders: chalk_ir::Binders::new( - chalk_ir::ParameterKinds::from( - &self.interner, - vec![ - chalk_ir::ParameterKind::Lifetime(()), - chalk_ir::ParameterKind::Ty(()), - ], - ), - chalk_rust_ir::StructDatumBound { fields: vec![], where_clauses: vec![] }, + RustDefId::Ref(_) => Arc::new(chalk_rust_ir::StructDatum { + id: struct_id, + binders: chalk_ir::Binders::new( + chalk_ir::ParameterKinds::from( + &self.interner, + vec![ + chalk_ir::ParameterKind::Lifetime(()), + chalk_ir::ParameterKind::Ty(()), + ], ), - flags: chalk_rust_ir::StructFlags { upstream: false, fundamental: false }, - }); - } - RustDefId::Array | RustDefId::Slice => { - return Arc::new(chalk_rust_ir::StructDatum { - id: struct_id, - binders: chalk_ir::Binders::new( - chalk_ir::ParameterKinds::from( - &self.interner, - Some(chalk_ir::ParameterKind::Ty(())), - ), - chalk_rust_ir::StructDatumBound { fields: vec![], where_clauses: vec![] }, + chalk_rust_ir::StructDatumBound { fields: vec![], where_clauses: vec![] }, + ), + flags: chalk_rust_ir::StructFlags { upstream: false, fundamental: false }, + }), + RustDefId::Array | RustDefId::Slice => Arc::new(chalk_rust_ir::StructDatum { + id: struct_id, + binders: chalk_ir::Binders::new( + chalk_ir::ParameterKinds::from( + &self.interner, + Some(chalk_ir::ParameterKind::Ty(())), ), - flags: chalk_rust_ir::StructFlags { upstream: false, fundamental: false }, - }); - } + chalk_rust_ir::StructDatumBound { fields: vec![], where_clauses: vec![] }, + ), + flags: chalk_rust_ir::StructFlags { upstream: false, fundamental: false }, + }), RustDefId::Str | RustDefId::Never | RustDefId::FnDef(_) => { - return Arc::new(chalk_rust_ir::StructDatum { + Arc::new(chalk_rust_ir::StructDatum { id: struct_id, binders: chalk_ir::Binders::new( chalk_ir::ParameterKinds::new(&self.interner), chalk_rust_ir::StructDatumBound { fields: vec![], where_clauses: vec![] }, ), flags: chalk_rust_ir::StructFlags { upstream: false, fundamental: false }, - }); + }) } _ => bug!("Used not struct variant when expecting struct variant."), @@ -228,7 +224,7 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t let predicates = self.tcx.predicates_of(def_id).predicates; let where_clauses: Vec<_> = predicates - .into_iter() + .iter() .map(|(wc, _)| wc.subst(self.tcx, bound_vars)) .filter_map(|wc| LowerInto::>>>::lower_into(wc, &self.interner)).collect(); @@ -260,7 +256,7 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t // not there yet. let all_impls = self.tcx.all_impls(def_id); - let matched_impls = all_impls.into_iter().filter(|impl_def_id| { + let matched_impls = all_impls.filter(|impl_def_id| { use chalk_ir::could_match::CouldMatch; let trait_ref = self.tcx.impl_trait_ref(*impl_def_id).unwrap(); let bound_vars = bound_vars_for_item(self.tcx, *impl_def_id); @@ -304,7 +300,7 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t _ => {} } } - return false; + false } fn associated_ty_value( @@ -379,7 +375,7 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t ty::AdtKind::Struct | ty::AdtKind::Union => None, ty::AdtKind::Enum => { let constraint = self.tcx.adt_sized_constraint(adt_def_id); - if constraint.0.len() > 0 { + if !constraint.0.is_empty() { unimplemented!() } else { Some(true) @@ -412,7 +408,7 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t ty::AdtKind::Struct | ty::AdtKind::Union => None, ty::AdtKind::Enum => { let constraint = self.tcx.adt_sized_constraint(adt_def_id); - if constraint.0.len() > 0 { + if !constraint.0.is_empty() { unimplemented!() } else { Some(true) diff --git a/src/librustc_traits/chalk/lowering.rs b/src/librustc_traits/chalk/lowering.rs index 4dc15a6b2b65..14295810d552 100644 --- a/src/librustc_traits/chalk/lowering.rs +++ b/src/librustc_traits/chalk/lowering.rs @@ -274,7 +274,7 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::Ty>> for Ty<'tcx> { let uint = |i| apply(chalk_ir::TypeName::Scalar(chalk_ir::Scalar::Uint(i)), empty()); let float = |f| apply(chalk_ir::TypeName::Scalar(chalk_ir::Scalar::Float(f)), empty()); - return match self.kind { + match self.kind { Bool => apply(chalk_ir::TypeName::Scalar(chalk_ir::Scalar::Bool), empty()), Char => apply(chalk_ir::TypeName::Scalar(chalk_ir::Scalar::Char), empty()), Int(ty) => match ty { @@ -370,7 +370,7 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::Ty>> for Ty<'tcx> { .intern(interner), Infer(_infer) => unimplemented!(), Error => unimplemented!(), - }; + } } } diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs index a5a1e20396ca..5dbcc5c9ec8b 100644 --- a/src/librustdoc/config.rs +++ b/src/librustdoc/config.rs @@ -447,7 +447,7 @@ impl Options { None => return Err(3), }; - match matches.opt_str("r").as_ref().map(|s| &**s) { + match matches.opt_str("r").as_deref() { Some("rust") | None => {} Some(s) => { diag.struct_err(&format!("unknown input format: {}", s)).emit(); diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 51ad1f043404..bf59b3f25734 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -129,7 +129,7 @@ impl<'tcx> DocContext<'tcx> { ); MAX_DEF_ID.with(|m| { - m.borrow_mut().entry(def_id.krate.clone()).or_insert(start_def_id); + m.borrow_mut().entry(def_id.krate).or_insert(start_def_id); }); self.all_fake_def_ids.borrow_mut().insert(def_id); diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 4ad9651d5630..8ec158ff9382 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -796,7 +796,7 @@ themePicker.onblur = handleThemeButtonsBlur; if path.exists() { for line in BufReader::new(File::open(path)?).lines() { let line = line?; - if !line.starts_with("\"") { + if !line.starts_with('"') { continue; } if line.starts_with(&format!("\"{}\"", krate)) { @@ -810,8 +810,7 @@ themePicker.onblur = handleThemeButtonsBlur; } krates.push( line.split('"') - .filter(|s| !s.is_empty()) - .next() + .find(|s| !s.is_empty()) .map(|s| s.to_owned()) .unwrap_or_else(String::new), ); diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index 4a9ad39e2362..a00c9a0bcea6 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -255,8 +255,7 @@ fn run_test( let rustc_binary = options .test_builder - .as_ref() - .map(|v| &**v) + .as_deref() .unwrap_or_else(|| rustc_interface::util::rustc_path().expect("found rustc")); let mut compiler = Command::new(&rustc_binary); compiler.arg("--crate-type").arg("bin"); diff --git a/src/libstd/thread/mod.rs b/src/libstd/thread/mod.rs index 7a3cbbe4562f..738f07250b5b 100644 --- a/src/libstd/thread/mod.rs +++ b/src/libstd/thread/mod.rs @@ -1272,7 +1272,7 @@ impl Thread { } fn cname(&self) -> Option<&CStr> { - self.inner.name.as_ref().map(|s| &**s) + self.inner.name.as_deref() } } diff --git a/src/libtest/cli.rs b/src/libtest/cli.rs index aac454c023c8..0cec8050c279 100644 --- a/src/libtest/cli.rs +++ b/src/libtest/cli.rs @@ -331,7 +331,7 @@ fn get_format( quiet: bool, allow_unstable: bool, ) -> OptPartRes { - let format = match matches.opt_str("format").as_ref().map(|s| &**s) { + let format = match matches.opt_str("format").as_deref() { None if quiet => OutputFormat::Terse, Some("pretty") | None => OutputFormat::Pretty, Some("terse") => OutputFormat::Terse, @@ -355,7 +355,7 @@ fn get_format( } fn get_color_config(matches: &getopts::Matches) -> OptPartRes { - let color = match matches.opt_str("color").as_ref().map(|s| &**s) { + let color = match matches.opt_str("color").as_deref() { Some("auto") | None => ColorConfig::AutoColor, Some("always") => ColorConfig::AlwaysColor, Some("never") => ColorConfig::NeverColor, From 10f3cd9bea7fed1382a8c2dd56841179b5703846 Mon Sep 17 00:00:00 2001 From: flip1995 Date: Mon, 11 May 2020 21:18:42 +0200 Subject: [PATCH 122/203] Update Cargo.lock --- Cargo.lock | 1 - 1 file changed, 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index 033ebc884a3e..0ee46c842905 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -537,7 +537,6 @@ dependencies = [ "compiletest_rs", "derive-new", "lazy_static 1.4.0", - "regex", "rustc-workspace-hack", "rustc_tools_util 0.2.0", "semver", From e7b02046a0b34ec6d114a7ba5549db8457684ec4 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sun, 10 May 2020 21:09:56 +0100 Subject: [PATCH 123/203] Fix hang in lexical_region_resolve --- .../infer/lexical_region_resolve/mod.rs | 20 +++++++++++++++---- .../regions/issue-72051-member-region-hang.rs | 7 +++++++ 2 files changed, 23 insertions(+), 4 deletions(-) create mode 100644 src/test/ui/regions/issue-72051-member-region-hang.rs diff --git a/src/librustc_infer/infer/lexical_region_resolve/mod.rs b/src/librustc_infer/infer/lexical_region_resolve/mod.rs index 3ff0e26a4dc3..33a80fb74710 100644 --- a/src/librustc_infer/infer/lexical_region_resolve/mod.rs +++ b/src/librustc_infer/infer/lexical_region_resolve/mod.rs @@ -325,8 +325,21 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> { } } - debug!("enforce_member_constraint: final least choice = {:?}", least_choice); - if least_choice != member_lower_bound { + // (#72087) Different `ty::Regions` can be known to be equal, for + // example, we know that `'a` and `'static` are equal in a function + // with a parameter of type `&'static &'a ()`. + // + // When we have two equal regions like this `expansion` will use + // `lub_concrete_regions` to pick a canonical representative. The same + // choice is needed here so that we don't end up in a cycle of + // `expansion` changing the region one way and the code here changing + // it back. + let lub = self.lub_concrete_regions(least_choice, member_lower_bound); + debug!( + "enforce_member_constraint: final least choice = {:?}\nlub = {:?}", + least_choice, lub + ); + if lub != member_lower_bound { *var_values.value_mut(member_vid) = VarValue::Value(least_choice); true } else { @@ -578,8 +591,7 @@ impl<'cx, 'tcx> LexicalResolver<'cx, 'tcx> { self.tcx().mk_region(ReScope(lub)) } - (&ReEarlyBound(_), &ReEarlyBound(_) | &ReFree(_)) - | (&ReFree(_), &ReEarlyBound(_) | &ReFree(_)) => { + (&ReEarlyBound(_) | &ReFree(_), &ReEarlyBound(_) | &ReFree(_)) => { self.region_rels.lub_free_regions(a, b) } diff --git a/src/test/ui/regions/issue-72051-member-region-hang.rs b/src/test/ui/regions/issue-72051-member-region-hang.rs new file mode 100644 index 000000000000..b7340b79d682 --- /dev/null +++ b/src/test/ui/regions/issue-72051-member-region-hang.rs @@ -0,0 +1,7 @@ +// Regression test for #72051, hang when resolving regions. + +// check-pass +// edition:2018 + +pub async fn query<'a>(_: &(), _: &(), _: (&(dyn std::any::Any + 'a),) ) {} +fn main() {} From a3cc435f5755f5550d4235779de58b53a22f0f1e Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 11 May 2020 11:46:13 +1000 Subject: [PATCH 124/203] Remove `RawVec::double_in_place`. It's unused. --- src/liballoc/raw_vec.rs | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/src/liballoc/raw_vec.rs b/src/liballoc/raw_vec.rs index a8e19c9cbaa8..ac5399acddb9 100644 --- a/src/liballoc/raw_vec.rs +++ b/src/liballoc/raw_vec.rs @@ -269,24 +269,6 @@ impl RawVec { } } - /// Attempts to double the size of the type's backing allocation in place. This is common - /// enough to want to do that it's easiest to just have a dedicated method. Slightly - /// more efficient logic can be provided for this than the general case. - /// - /// Returns `true` if the reallocation attempt has succeeded. - /// - /// # Panics - /// - /// * Panics if `T` is zero-sized on the assumption that you managed to exhaust - /// all `usize::MAX` slots in your imaginary buffer. - /// * Panics on 32-bit platforms if the requested capacity exceeds - /// `isize::MAX` bytes. - #[inline(never)] - #[cold] - pub fn double_in_place(&mut self) -> bool { - self.grow(Double, InPlace, Uninitialized).is_ok() - } - /// Ensures that the buffer contains at least enough space to hold /// `used_capacity + needed_extra_capacity` elements. If it doesn't already have /// enough capacity, will reallocate enough space plus comfortable slack From 6de6d70ae0a21b779d63d885438c7214e17e7a6d Mon Sep 17 00:00:00 2001 From: Wesley Wiser Date: Mon, 11 May 2020 20:13:15 -0400 Subject: [PATCH 125/203] Modify SimplifyArmIdentity so it can trigger on mir-opt-level=1 I also added test cases to make sure the optimization can fire on all of these cases: ```rust fn case_1(o: Option) -> Option { match o { Some(u) => Some(u), None => None, } } fn case2(r: Result) -> Result { match r { Ok(u) => Ok(u), Err(i) => Err(i), } } fn case3(r: Result) -> Result { let u = r?; Ok(u) } ``` Without MIR inlining, this still does not completely optimize away the `?` operator because the `Try::into_result()`, `From::from()` and `Try::from_error()` calls still exist. This does move us a bit closer to that goal though because: - We can now run the pass on mir-opt-level=1 - We no longer depend on the copy propagation pass running which is unlikely to stabilize anytime soon. --- src/librustc_mir/transform/mod.rs | 4 +- src/librustc_mir/transform/simplify_try.rs | 356 ++++++++++++++++-- .../32bit/rustc.main.SimplifyArmIdentity.diff | 31 +- .../64bit/rustc.main.SimplifyArmIdentity.diff | 31 +- src/test/mir-opt/simplify-arm.rs | 32 ++ .../rustc.id.SimplifyArmIdentity.diff | 45 +++ .../rustc.id.SimplifyBranchSame.diff | 37 ++ .../rustc.id_result.SimplifyArmIdentity.diff | 58 +++ .../rustc.id_result.SimplifyBranchSame.diff | 45 +++ .../rustc.id_try.SimplifyArmIdentity.diff | 109 ++++++ .../rustc.id_try.SimplifyBranchSame.diff | 100 +++++ ...ustc.try_identity.SimplifyArmIdentity.diff | 53 ++- ....try_identity.SimplifyBranchSame.after.mir | 22 +- ...ustc.try_identity.SimplifyLocals.after.mir | 19 +- src/test/mir-opt/simplify_try_if_let.rs | 40 ++ ...c.{{impl}}-append.SimplifyArmIdentity.diff | 127 +++++++ 16 files changed, 1034 insertions(+), 75 deletions(-) create mode 100644 src/test/mir-opt/simplify-arm.rs create mode 100644 src/test/mir-opt/simplify-arm/rustc.id.SimplifyArmIdentity.diff create mode 100644 src/test/mir-opt/simplify-arm/rustc.id.SimplifyBranchSame.diff create mode 100644 src/test/mir-opt/simplify-arm/rustc.id_result.SimplifyArmIdentity.diff create mode 100644 src/test/mir-opt/simplify-arm/rustc.id_result.SimplifyBranchSame.diff create mode 100644 src/test/mir-opt/simplify-arm/rustc.id_try.SimplifyArmIdentity.diff create mode 100644 src/test/mir-opt/simplify-arm/rustc.id_try.SimplifyBranchSame.diff create mode 100644 src/test/mir-opt/simplify_try_if_let.rs create mode 100644 src/test/mir-opt/simplify_try_if_let/rustc.{{impl}}-append.SimplifyArmIdentity.diff diff --git a/src/librustc_mir/transform/mod.rs b/src/librustc_mir/transform/mod.rs index 220691c1570d..7ad5baac2051 100644 --- a/src/librustc_mir/transform/mod.rs +++ b/src/librustc_mir/transform/mod.rs @@ -317,12 +317,12 @@ fn run_optimization_passes<'tcx>( // 2. It creates additional possibilities for some MIR optimizations to trigger // FIXME(#70073): Why is this done here and not in `post_borrowck_cleanup`? &deaggregator::Deaggregator, + &simplify_try::SimplifyArmIdentity, + &simplify_try::SimplifyBranchSame, ©_prop::CopyPropagation, &simplify_branches::SimplifyBranches::new("after-copy-prop"), &remove_noop_landing_pads::RemoveNoopLandingPads, &simplify::SimplifyCfg::new("after-remove-noop-landing-pads"), - &simplify_try::SimplifyArmIdentity, - &simplify_try::SimplifyBranchSame, &simplify::SimplifyCfg::new("final"), &simplify::SimplifyLocals, ]; diff --git a/src/librustc_mir/transform/simplify_try.rs b/src/librustc_mir/transform/simplify_try.rs index d22c2d906003..41ffa6594418 100644 --- a/src/librustc_mir/transform/simplify_try.rs +++ b/src/librustc_mir/transform/simplify_try.rs @@ -11,9 +11,12 @@ use crate::transform::{simplify, MirPass, MirSource}; use itertools::Itertools as _; +use rustc_index::vec::IndexVec; use rustc_middle::mir::*; use rustc_middle::ty::{Ty, TyCtxt}; use rustc_target::abi::VariantIdx; +use std::iter::{Enumerate, Peekable}; +use std::slice::Iter; /// Simplifies arms of form `Variant(x) => Variant(x)` to just a move. /// @@ -21,7 +24,8 @@ use rustc_target::abi::VariantIdx; /// /// ```rust /// _LOCAL_TMP = ((_LOCAL_1 as Variant ).FIELD: TY ); -/// ((_LOCAL_0 as Variant).FIELD: TY) = move _LOCAL_TMP; +/// _TMP_2 = _LOCAL_TMP; +/// ((_LOCAL_0 as Variant).FIELD: TY) = move _TMP_2; /// discriminant(_LOCAL_0) = VAR_IDX; /// ``` /// @@ -32,50 +36,320 @@ use rustc_target::abi::VariantIdx; /// ``` pub struct SimplifyArmIdentity; +#[derive(Debug)] +struct ArmIdentityInfo<'tcx> { + /// Storage location for the variant's field + local_temp_0: Local, + /// Storage location holding the variant being read from + local_1: Local, + /// The variant field being read from + vf_s0: VarField<'tcx>, + /// Index of the statement which loads the variant being read + get_variant_field_stmt: usize, + + /// Tracks each assignment to a temporary of the variant's field + field_tmp_assignments: Vec<(Local, Local)>, + + /// Storage location holding the variant's field that was read from + local_tmp_s1: Local, + /// Storage location holding the enum that we are writing to + local_0: Local, + /// The variant field being written to + vf_s1: VarField<'tcx>, + + /// Storage location that the discriminant is being written to + set_discr_local: Local, + /// The variant being written + set_discr_var_idx: VariantIdx, + + /// Index of the statement that should be overwritten as a move + stmt_to_overwrite: usize, + /// SourceInfo for the new move + source_info: SourceInfo, + + /// Indices of matching Storage{Live,Dead} statements encountered. + /// (StorageLive index,, StorageDead index, Local) + storage_stmts: Vec<(usize, usize, Local)>, + + /// The statements that should be removed (turned into nops) + stmts_to_remove: Vec, +} + +fn get_arm_identity_info<'a, 'tcx>(stmts: &'a [Statement<'tcx>]) -> Option> { + // This can't possibly match unless there are at least 3 statements in the block + // so fail fast on tiny blocks. + if stmts.len() < 3 { + return None; + } + + let mut tmp_assigns = Vec::new(); + let mut nop_stmts = Vec::new(); + let mut storage_stmts = Vec::new(); + let mut storage_live_stmts = Vec::new(); + let mut storage_dead_stmts = Vec::new(); + + type StmtIter<'a, 'tcx> = Peekable>>>; + + fn is_storage_stmt<'tcx>(stmt: &Statement<'tcx>) -> bool { + matches!(stmt.kind, StatementKind::StorageLive(_) | StatementKind::StorageDead(_)) + } + + /// Eats consecutive Statements which match `test`, performing the specified `action` for each. + /// The iterator `stmt_iter` is not advanced if none were matched. + fn try_eat<'a, 'tcx>( + stmt_iter: &mut StmtIter<'a, 'tcx>, + test: impl Fn(&'a Statement<'tcx>) -> bool, + mut action: impl FnMut(usize, &'a Statement<'tcx>) -> (), + ) { + while stmt_iter.peek().map(|(_, stmt)| test(stmt)).unwrap_or(false) { + let (idx, stmt) = stmt_iter.next().unwrap(); + + action(idx, stmt); + } + } + + /// Eats consecutive `StorageLive` and `StorageDead` Statements. + /// The iterator `stmt_iter` is not advanced if none were found. + fn try_eat_storage_stmts<'a, 'tcx>( + stmt_iter: &mut StmtIter<'a, 'tcx>, + storage_live_stmts: &mut Vec<(usize, Local)>, + storage_dead_stmts: &mut Vec<(usize, Local)>, + ) { + try_eat(stmt_iter, is_storage_stmt, |idx, stmt| { + if let StatementKind::StorageLive(l) = stmt.kind { + storage_live_stmts.push((idx, l)); + } else if let StatementKind::StorageDead(l) = stmt.kind { + storage_dead_stmts.push((idx, l)); + } + }) + } + + fn is_tmp_storage_stmt<'tcx>(stmt: &Statement<'tcx>) -> bool { + use rustc_middle::mir::StatementKind::Assign; + if let Assign(box (place, Rvalue::Use(Operand::Copy(p) | Operand::Move(p)))) = &stmt.kind { + place.as_local().is_some() && p.as_local().is_some() + } else { + false + } + } + + /// Eats consecutive `Assign` Statements. + // The iterator `stmt_iter` is not advanced if none were found. + fn try_eat_assign_tmp_stmts<'a, 'tcx>( + stmt_iter: &mut StmtIter<'a, 'tcx>, + tmp_assigns: &mut Vec<(Local, Local)>, + nop_stmts: &mut Vec, + ) { + try_eat(stmt_iter, is_tmp_storage_stmt, |idx, stmt| { + use rustc_middle::mir::StatementKind::Assign; + if let Assign(box (place, Rvalue::Use(Operand::Copy(p) | Operand::Move(p)))) = + &stmt.kind + { + tmp_assigns.push((place.as_local().unwrap(), p.as_local().unwrap())); + nop_stmts.push(idx); + } + }) + } + + fn find_storage_live_dead_stmts_for_local<'tcx>( + local: Local, + stmts: &[Statement<'tcx>], + ) -> Option<(usize, usize)> { + trace!("looking for {:?}", local); + let mut storage_live_stmt = None; + let mut storage_dead_stmt = None; + for (idx, stmt) in stmts.iter().enumerate() { + if stmt.kind == StatementKind::StorageLive(local) { + storage_live_stmt = Some(idx); + } else if stmt.kind == StatementKind::StorageDead(local) { + storage_dead_stmt = Some(idx); + } + } + + Some((storage_live_stmt?, storage_dead_stmt.unwrap_or(usize::MAX))) + } + + // Try to match the expected MIR structure with the basic block we're processing. + // We want to see something that looks like: + // ``` + // (StorageLive(_) | StorageDead(_));* + // _LOCAL_INTO = ((_LOCAL_FROM as Variant).FIELD: TY); + // (StorageLive(_) | StorageDead(_));* + // (tmp_n+1 = tmp_n);* + // (StorageLive(_) | StorageDead(_));* + // (tmp_n+1 = tmp_n);* + // ((LOCAL_FROM as Variant).FIELD: TY) = move tmp; + // discriminant(LOCAL_FROM) = VariantIdx; + // (StorageLive(_) | StorageDead(_));* + // ``` + let mut stmt_iter = stmts.iter().enumerate().peekable(); + + try_eat_storage_stmts(&mut stmt_iter, &mut storage_live_stmts, &mut storage_dead_stmts); + + let (get_variant_field_stmt, stmt) = stmt_iter.next()?; + let (local_tmp_s0, local_1, vf_s0) = match_get_variant_field(stmt)?; + + try_eat_storage_stmts(&mut stmt_iter, &mut storage_live_stmts, &mut storage_dead_stmts); + + try_eat_assign_tmp_stmts(&mut stmt_iter, &mut tmp_assigns, &mut nop_stmts); + + try_eat_storage_stmts(&mut stmt_iter, &mut storage_live_stmts, &mut storage_dead_stmts); + + try_eat_assign_tmp_stmts(&mut stmt_iter, &mut tmp_assigns, &mut nop_stmts); + + let (idx, stmt) = stmt_iter.next()?; + let (local_tmp_s1, local_0, vf_s1) = match_set_variant_field(stmt)?; + nop_stmts.push(idx); + + let (idx, stmt) = stmt_iter.next()?; + let (set_discr_local, set_discr_var_idx) = match_set_discr(stmt)?; + let discr_stmt_source_info = stmt.source_info; + nop_stmts.push(idx); + + try_eat_storage_stmts(&mut stmt_iter, &mut storage_live_stmts, &mut storage_dead_stmts); + + for (live_idx, live_local) in storage_live_stmts { + if let Some(i) = storage_dead_stmts.iter().rposition(|(_, l)| *l == live_local) { + let (dead_idx, _) = storage_dead_stmts.swap_remove(i); + storage_stmts.push((live_idx, dead_idx, live_local)); + + if live_local == local_tmp_s0 { + nop_stmts.push(get_variant_field_stmt); + } + } + } + + nop_stmts.sort(); + + // Use one of the statements we're going to discard between the point + // where the storage location for the variant field becomes live and + // is killed. + let (live_idx, dead_idx) = find_storage_live_dead_stmts_for_local(local_tmp_s0, stmts)?; + let stmt_to_overwrite = + nop_stmts.iter().find(|stmt_idx| live_idx < **stmt_idx && **stmt_idx < dead_idx); + + Some(ArmIdentityInfo { + local_temp_0: local_tmp_s0, + local_1, + vf_s0, + get_variant_field_stmt, + field_tmp_assignments: tmp_assigns, + local_tmp_s1, + local_0, + vf_s1, + set_discr_local, + set_discr_var_idx, + stmt_to_overwrite: *stmt_to_overwrite?, + source_info: discr_stmt_source_info, + storage_stmts, + stmts_to_remove: nop_stmts, + }) +} + +fn optimization_applies<'tcx>( + opt_info: &ArmIdentityInfo<'tcx>, + local_decls: &IndexVec>, +) -> bool { + trace!("testing if optimization applies..."); + + // FIXME(wesleywiser): possibly relax this restriction? + if opt_info.local_0 == opt_info.local_1 { + trace!("NO: moving into ourselves"); + return false; + } else if opt_info.vf_s0 != opt_info.vf_s1 { + trace!("NO: the field-and-variant information do not match"); + return false; + } else if local_decls[opt_info.local_0].ty != local_decls[opt_info.local_1].ty { + // FIXME(Centril,oli-obk): possibly relax to same layout? + trace!("NO: source and target locals have different types"); + return false; + } else if (opt_info.local_0, opt_info.vf_s0.var_idx) + != (opt_info.set_discr_local, opt_info.set_discr_var_idx) + { + trace!("NO: the discriminants do not match"); + return false; + } + + // Verify the assigment chain consists of the form b = a; c = b; d = c; etc... + if opt_info.field_tmp_assignments.len() == 0 { + trace!("NO: no assignments found"); + } + let mut last_assigned_to = opt_info.field_tmp_assignments[0].1; + let source_local = last_assigned_to; + for (l, r) in &opt_info.field_tmp_assignments { + if *r != last_assigned_to { + trace!("NO: found unexpected assignment {:?} = {:?}", l, r); + return false; + } + + last_assigned_to = *l; + } + + if source_local != opt_info.local_temp_0 { + trace!( + "NO: start of assignment chain does not match enum variant temp: {:?} != {:?}", + source_local, + opt_info.local_temp_0 + ); + return false; + } else if last_assigned_to != opt_info.local_tmp_s1 { + trace!( + "NO: end of assignemnt chain does not match written enum temp: {:?} != {:?}", + last_assigned_to, + opt_info.local_tmp_s1 + ); + return false; + } + + trace!("SUCCESS: optimization applies!"); + return true; +} + impl<'tcx> MirPass<'tcx> for SimplifyArmIdentity { - fn run_pass(&self, _: TyCtxt<'tcx>, _: MirSource<'tcx>, body: &mut Body<'tcx>) { + fn run_pass(&self, _: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut Body<'tcx>) { + trace!("running SimplifyArmIdentity on {:?}", source); let (basic_blocks, local_decls) = body.basic_blocks_and_local_decls_mut(); for bb in basic_blocks { - // Need 3 statements: - let (s0, s1, s2) = match &mut *bb.statements { - [s0, s1, s2] => (s0, s1, s2), - _ => continue, - }; - - // Pattern match on the form we want: - let (local_tmp_s0, local_1, vf_s0) = match match_get_variant_field(s0) { - None => continue, - Some(x) => x, - }; - let (local_tmp_s1, local_0, vf_s1) = match match_set_variant_field(s1) { - None => continue, - Some(x) => x, - }; - if local_tmp_s0 != local_tmp_s1 - // Avoid moving into ourselves. - || local_0 == local_1 - // The field-and-variant information match up. - || vf_s0 != vf_s1 - // Source and target locals have the same type. - // FIXME(Centril | oli-obk): possibly relax to same layout? - || local_decls[local_0].ty != local_decls[local_1].ty - // We're setting the discriminant of `local_0` to this variant. - || Some((local_0, vf_s0.var_idx)) != match_set_discr(s2) - { - continue; - } - - // Right shape; transform! - s0.source_info = s2.source_info; - match &mut s0.kind { - StatementKind::Assign(box (place, rvalue)) => { - *place = local_0.into(); - *rvalue = Rvalue::Use(Operand::Move(local_1.into())); + if let Some(opt_info) = get_arm_identity_info(&bb.statements) { + trace!("got opt_info = {:#?}", opt_info); + if !optimization_applies(&opt_info, local_decls) { + debug!("optimization skipped for {:?}", source); + continue; } - _ => unreachable!(), + + // Also remove unused Storage{Live,Dead} statements which correspond + // to temps used previously. + for (live_idx, dead_idx, local) in &opt_info.storage_stmts { + // The temporary that we've read the variant field into is scoped to this block, + // so we can remove the assignment. + if *local == opt_info.local_temp_0 { + bb.statements[opt_info.get_variant_field_stmt].make_nop(); + } + + for (left, right) in &opt_info.field_tmp_assignments { + if local == left || local == right { + bb.statements[*live_idx].make_nop(); + bb.statements[*dead_idx].make_nop(); + } + } + } + + // Right shape; transform + for stmt_idx in opt_info.stmts_to_remove { + bb.statements[stmt_idx].make_nop(); + } + + let stmt = &mut bb.statements[opt_info.stmt_to_overwrite]; + stmt.source_info = opt_info.source_info; + stmt.kind = StatementKind::Assign(box ( + opt_info.local_0.into(), + Rvalue::Use(Operand::Move(opt_info.local_1.into())), + )); + + bb.statements.retain(|stmt| stmt.kind != StatementKind::Nop); + + trace!("block is now {:?}", bb.statements); } - s1.make_nop(); - s2.make_nop(); } } } @@ -129,7 +403,7 @@ fn match_set_discr<'tcx>(stmt: &Statement<'tcx>) -> Option<(Local, VariantIdx)> } } -#[derive(PartialEq)] +#[derive(PartialEq, Debug)] struct VarField<'tcx> { field: Field, field_ty: Ty<'tcx>, diff --git a/src/test/mir-opt/simplify-arm-identity/32bit/rustc.main.SimplifyArmIdentity.diff b/src/test/mir-opt/simplify-arm-identity/32bit/rustc.main.SimplifyArmIdentity.diff index bf24bfb2c574..6199e2c56625 100644 --- a/src/test/mir-opt/simplify-arm-identity/32bit/rustc.main.SimplifyArmIdentity.diff +++ b/src/test/mir-opt/simplify-arm-identity/32bit/rustc.main.SimplifyArmIdentity.diff @@ -35,9 +35,38 @@ // mir::Constant // + span: $DIR/simplify-arm-identity.rs:20:9: 20:20 // + literal: Const { ty: isize, val: Value(Scalar(0x00000000)) } + goto -> bb3; // scope 1 at $DIR/simplify-arm-identity.rs:20:9: 20:20 + } + + bb1: { + ((_2 as Foo).0: u8) = const 0u8; // scope 1 at $DIR/simplify-arm-identity.rs:21:21: 21:32 + // ty::Const + // + ty: u8 + // + val: Value(Scalar(0x00)) + // mir::Constant + // + span: $DIR/simplify-arm-identity.rs:21:30: 21:31 + // + literal: Const { ty: u8, val: Value(Scalar(0x00)) } + discriminant(_2) = 0; // scope 1 at $DIR/simplify-arm-identity.rs:21:21: 21:32 + goto -> bb4; // scope 1 at $DIR/simplify-arm-identity.rs:19:18: 22:6 + } + + bb2: { + unreachable; // scope 1 at $DIR/simplify-arm-identity.rs:19:24: 19:25 + } + + bb3: { + StorageLive(_4); // scope 1 at $DIR/simplify-arm-identity.rs:20:18: 20:19 _4 = ((_1 as Foo).0: u8); // scope 1 at $DIR/simplify-arm-identity.rs:20:18: 20:19 - ((_2 as Foo).0: u8) = move _4; // scope 3 at $DIR/simplify-arm-identity.rs:20:24: 20:35 + StorageLive(_5); // scope 3 at $DIR/simplify-arm-identity.rs:20:33: 20:34 + _5 = _4; // scope 3 at $DIR/simplify-arm-identity.rs:20:33: 20:34 + ((_2 as Foo).0: u8) = move _5; // scope 3 at $DIR/simplify-arm-identity.rs:20:24: 20:35 discriminant(_2) = 0; // scope 3 at $DIR/simplify-arm-identity.rs:20:24: 20:35 + StorageDead(_5); // scope 3 at $DIR/simplify-arm-identity.rs:20:34: 20:35 + StorageDead(_4); // scope 1 at $DIR/simplify-arm-identity.rs:20:35: 20:36 + goto -> bb4; // scope 1 at $DIR/simplify-arm-identity.rs:19:18: 22:6 + } + + bb4: { StorageDead(_2); // scope 1 at $DIR/simplify-arm-identity.rs:22:6: 22:7 _0 = const (); // scope 0 at $DIR/simplify-arm-identity.rs:17:11: 23:2 // ty::Const diff --git a/src/test/mir-opt/simplify-arm-identity/64bit/rustc.main.SimplifyArmIdentity.diff b/src/test/mir-opt/simplify-arm-identity/64bit/rustc.main.SimplifyArmIdentity.diff index ff7183e57d2c..bf875c6a555f 100644 --- a/src/test/mir-opt/simplify-arm-identity/64bit/rustc.main.SimplifyArmIdentity.diff +++ b/src/test/mir-opt/simplify-arm-identity/64bit/rustc.main.SimplifyArmIdentity.diff @@ -35,9 +35,38 @@ // mir::Constant // + span: $DIR/simplify-arm-identity.rs:20:9: 20:20 // + literal: Const { ty: isize, val: Value(Scalar(0x0000000000000000)) } + goto -> bb3; // scope 1 at $DIR/simplify-arm-identity.rs:20:9: 20:20 + } + + bb1: { + ((_2 as Foo).0: u8) = const 0u8; // scope 1 at $DIR/simplify-arm-identity.rs:21:21: 21:32 + // ty::Const + // + ty: u8 + // + val: Value(Scalar(0x00)) + // mir::Constant + // + span: $DIR/simplify-arm-identity.rs:21:30: 21:31 + // + literal: Const { ty: u8, val: Value(Scalar(0x00)) } + discriminant(_2) = 0; // scope 1 at $DIR/simplify-arm-identity.rs:21:21: 21:32 + goto -> bb4; // scope 1 at $DIR/simplify-arm-identity.rs:19:18: 22:6 + } + + bb2: { + unreachable; // scope 1 at $DIR/simplify-arm-identity.rs:19:24: 19:25 + } + + bb3: { + StorageLive(_4); // scope 1 at $DIR/simplify-arm-identity.rs:20:18: 20:19 _4 = ((_1 as Foo).0: u8); // scope 1 at $DIR/simplify-arm-identity.rs:20:18: 20:19 - ((_2 as Foo).0: u8) = move _4; // scope 3 at $DIR/simplify-arm-identity.rs:20:24: 20:35 + StorageLive(_5); // scope 3 at $DIR/simplify-arm-identity.rs:20:33: 20:34 + _5 = _4; // scope 3 at $DIR/simplify-arm-identity.rs:20:33: 20:34 + ((_2 as Foo).0: u8) = move _5; // scope 3 at $DIR/simplify-arm-identity.rs:20:24: 20:35 discriminant(_2) = 0; // scope 3 at $DIR/simplify-arm-identity.rs:20:24: 20:35 + StorageDead(_5); // scope 3 at $DIR/simplify-arm-identity.rs:20:34: 20:35 + StorageDead(_4); // scope 1 at $DIR/simplify-arm-identity.rs:20:35: 20:36 + goto -> bb4; // scope 1 at $DIR/simplify-arm-identity.rs:19:18: 22:6 + } + + bb4: { StorageDead(_2); // scope 1 at $DIR/simplify-arm-identity.rs:22:6: 22:7 _0 = const (); // scope 0 at $DIR/simplify-arm-identity.rs:17:11: 23:2 // ty::Const diff --git a/src/test/mir-opt/simplify-arm.rs b/src/test/mir-opt/simplify-arm.rs new file mode 100644 index 000000000000..0e3f86501bb4 --- /dev/null +++ b/src/test/mir-opt/simplify-arm.rs @@ -0,0 +1,32 @@ +// compile-flags: -Z mir-opt-level=1 +// EMIT_MIR rustc.id.SimplifyArmIdentity.diff +// EMIT_MIR rustc.id.SimplifyBranchSame.diff +// EMIT_MIR rustc.id_result.SimplifyArmIdentity.diff +// EMIT_MIR rustc.id_result.SimplifyBranchSame.diff +// EMIT_MIR rustc.id_try.SimplifyArmIdentity.diff +// EMIT_MIR rustc.id_try.SimplifyBranchSame.diff + +fn id(o: Option) -> Option { + match o { + Some(v) => Some(v), + None => None, + } +} + +fn id_result(r: Result) -> Result { + match r { + Ok(x) => Ok(x), + Err(y) => Err(y), + } +} + +fn id_try(r: Result) -> Result { + let x = r?; + Ok(x) +} + +fn main() { + id(None); + id_result(Ok(4)); + id_try(Ok(4)); +} diff --git a/src/test/mir-opt/simplify-arm/rustc.id.SimplifyArmIdentity.diff b/src/test/mir-opt/simplify-arm/rustc.id.SimplifyArmIdentity.diff new file mode 100644 index 000000000000..8d08267d75bf --- /dev/null +++ b/src/test/mir-opt/simplify-arm/rustc.id.SimplifyArmIdentity.diff @@ -0,0 +1,45 @@ +- // MIR for `id` before SimplifyArmIdentity ++ // MIR for `id` after SimplifyArmIdentity + + fn id(_1: std::option::Option) -> std::option::Option { + debug o => _1; // in scope 0 at $DIR/simplify-arm.rs:9:7: 9:8 + let mut _0: std::option::Option; // return place in scope 0 at $DIR/simplify-arm.rs:9:25: 9:35 + let mut _2: isize; // in scope 0 at $DIR/simplify-arm.rs:11:9: 11:16 + let _3: u8; // in scope 0 at $DIR/simplify-arm.rs:11:14: 11:15 + let mut _4: u8; // in scope 0 at $DIR/simplify-arm.rs:11:25: 11:26 + scope 1 { + debug v => _3; // in scope 1 at $DIR/simplify-arm.rs:11:14: 11:15 + } + + bb0: { + _2 = discriminant(_1); // scope 0 at $DIR/simplify-arm.rs:11:9: 11:16 + switchInt(move _2) -> [0isize: bb1, 1isize: bb3, otherwise: bb2]; // scope 0 at $DIR/simplify-arm.rs:11:9: 11:16 + } + + bb1: { + discriminant(_0) = 0; // scope 0 at $DIR/simplify-arm.rs:12:17: 12:21 + goto -> bb4; // scope 0 at $DIR/simplify-arm.rs:10:5: 13:6 + } + + bb2: { + unreachable; // scope 0 at $DIR/simplify-arm.rs:10:11: 10:12 + } + + bb3: { +- StorageLive(_3); // scope 0 at $DIR/simplify-arm.rs:11:14: 11:15 +- _3 = ((_1 as Some).0: u8); // scope 0 at $DIR/simplify-arm.rs:11:14: 11:15 +- StorageLive(_4); // scope 1 at $DIR/simplify-arm.rs:11:25: 11:26 +- _4 = _3; // scope 1 at $DIR/simplify-arm.rs:11:25: 11:26 +- ((_0 as Some).0: u8) = move _4; // scope 1 at $DIR/simplify-arm.rs:11:20: 11:27 +- discriminant(_0) = 1; // scope 1 at $DIR/simplify-arm.rs:11:20: 11:27 +- StorageDead(_4); // scope 1 at $DIR/simplify-arm.rs:11:26: 11:27 +- StorageDead(_3); // scope 0 at $DIR/simplify-arm.rs:11:27: 11:28 ++ _0 = move _1; // scope 1 at $DIR/simplify-arm.rs:11:20: 11:27 + goto -> bb4; // scope 0 at $DIR/simplify-arm.rs:10:5: 13:6 + } + + bb4: { + return; // scope 0 at $DIR/simplify-arm.rs:14:2: 14:2 + } + } + diff --git a/src/test/mir-opt/simplify-arm/rustc.id.SimplifyBranchSame.diff b/src/test/mir-opt/simplify-arm/rustc.id.SimplifyBranchSame.diff new file mode 100644 index 000000000000..23fa9817f80f --- /dev/null +++ b/src/test/mir-opt/simplify-arm/rustc.id.SimplifyBranchSame.diff @@ -0,0 +1,37 @@ +- // MIR for `id` before SimplifyBranchSame ++ // MIR for `id` after SimplifyBranchSame + + fn id(_1: std::option::Option) -> std::option::Option { + debug o => _1; // in scope 0 at $DIR/simplify-arm.rs:9:7: 9:8 + let mut _0: std::option::Option; // return place in scope 0 at $DIR/simplify-arm.rs:9:25: 9:35 + let mut _2: isize; // in scope 0 at $DIR/simplify-arm.rs:11:9: 11:16 + let _3: u8; // in scope 0 at $DIR/simplify-arm.rs:11:14: 11:15 + let mut _4: u8; // in scope 0 at $DIR/simplify-arm.rs:11:25: 11:26 + scope 1 { + debug v => _3; // in scope 1 at $DIR/simplify-arm.rs:11:14: 11:15 + } + + bb0: { + _2 = discriminant(_1); // scope 0 at $DIR/simplify-arm.rs:11:9: 11:16 + switchInt(move _2) -> [0isize: bb1, 1isize: bb3, otherwise: bb2]; // scope 0 at $DIR/simplify-arm.rs:11:9: 11:16 + } + + bb1: { + discriminant(_0) = 0; // scope 0 at $DIR/simplify-arm.rs:12:17: 12:21 + goto -> bb4; // scope 0 at $DIR/simplify-arm.rs:10:5: 13:6 + } + + bb2: { + unreachable; // scope 0 at $DIR/simplify-arm.rs:10:11: 10:12 + } + + bb3: { + _0 = move _1; // scope 1 at $DIR/simplify-arm.rs:11:20: 11:27 + goto -> bb4; // scope 0 at $DIR/simplify-arm.rs:10:5: 13:6 + } + + bb4: { + return; // scope 0 at $DIR/simplify-arm.rs:14:2: 14:2 + } + } + diff --git a/src/test/mir-opt/simplify-arm/rustc.id_result.SimplifyArmIdentity.diff b/src/test/mir-opt/simplify-arm/rustc.id_result.SimplifyArmIdentity.diff new file mode 100644 index 000000000000..e2a12ca5be26 --- /dev/null +++ b/src/test/mir-opt/simplify-arm/rustc.id_result.SimplifyArmIdentity.diff @@ -0,0 +1,58 @@ +- // MIR for `id_result` before SimplifyArmIdentity ++ // MIR for `id_result` after SimplifyArmIdentity + + fn id_result(_1: std::result::Result) -> std::result::Result { + debug r => _1; // in scope 0 at $DIR/simplify-arm.rs:16:14: 16:15 + let mut _0: std::result::Result; // return place in scope 0 at $DIR/simplify-arm.rs:16:37: 16:52 + let mut _2: isize; // in scope 0 at $DIR/simplify-arm.rs:18:9: 18:14 + let _3: u8; // in scope 0 at $DIR/simplify-arm.rs:18:12: 18:13 + let mut _4: u8; // in scope 0 at $DIR/simplify-arm.rs:18:21: 18:22 + let _5: i32; // in scope 0 at $DIR/simplify-arm.rs:19:13: 19:14 + let mut _6: i32; // in scope 0 at $DIR/simplify-arm.rs:19:23: 19:24 + scope 1 { + debug x => _3; // in scope 1 at $DIR/simplify-arm.rs:18:12: 18:13 + } + scope 2 { + debug y => _5; // in scope 2 at $DIR/simplify-arm.rs:19:13: 19:14 + } + + bb0: { + _2 = discriminant(_1); // scope 0 at $DIR/simplify-arm.rs:18:9: 18:14 + switchInt(move _2) -> [0isize: bb3, 1isize: bb1, otherwise: bb2]; // scope 0 at $DIR/simplify-arm.rs:18:9: 18:14 + } + + bb1: { +- StorageLive(_5); // scope 0 at $DIR/simplify-arm.rs:19:13: 19:14 +- _5 = ((_1 as Err).0: i32); // scope 0 at $DIR/simplify-arm.rs:19:13: 19:14 +- StorageLive(_6); // scope 2 at $DIR/simplify-arm.rs:19:23: 19:24 +- _6 = _5; // scope 2 at $DIR/simplify-arm.rs:19:23: 19:24 +- ((_0 as Err).0: i32) = move _6; // scope 2 at $DIR/simplify-arm.rs:19:19: 19:25 +- discriminant(_0) = 1; // scope 2 at $DIR/simplify-arm.rs:19:19: 19:25 +- StorageDead(_6); // scope 2 at $DIR/simplify-arm.rs:19:24: 19:25 +- StorageDead(_5); // scope 0 at $DIR/simplify-arm.rs:19:25: 19:26 ++ _0 = move _1; // scope 2 at $DIR/simplify-arm.rs:19:19: 19:25 + goto -> bb4; // scope 0 at $DIR/simplify-arm.rs:17:5: 20:6 + } + + bb2: { + unreachable; // scope 0 at $DIR/simplify-arm.rs:17:11: 17:12 + } + + bb3: { +- StorageLive(_3); // scope 0 at $DIR/simplify-arm.rs:18:12: 18:13 +- _3 = ((_1 as Ok).0: u8); // scope 0 at $DIR/simplify-arm.rs:18:12: 18:13 +- StorageLive(_4); // scope 1 at $DIR/simplify-arm.rs:18:21: 18:22 +- _4 = _3; // scope 1 at $DIR/simplify-arm.rs:18:21: 18:22 +- ((_0 as Ok).0: u8) = move _4; // scope 1 at $DIR/simplify-arm.rs:18:18: 18:23 +- discriminant(_0) = 0; // scope 1 at $DIR/simplify-arm.rs:18:18: 18:23 +- StorageDead(_4); // scope 1 at $DIR/simplify-arm.rs:18:22: 18:23 +- StorageDead(_3); // scope 0 at $DIR/simplify-arm.rs:18:23: 18:24 ++ _0 = move _1; // scope 1 at $DIR/simplify-arm.rs:18:18: 18:23 + goto -> bb4; // scope 0 at $DIR/simplify-arm.rs:17:5: 20:6 + } + + bb4: { + return; // scope 0 at $DIR/simplify-arm.rs:21:2: 21:2 + } + } + diff --git a/src/test/mir-opt/simplify-arm/rustc.id_result.SimplifyBranchSame.diff b/src/test/mir-opt/simplify-arm/rustc.id_result.SimplifyBranchSame.diff new file mode 100644 index 000000000000..9d1ff22dc510 --- /dev/null +++ b/src/test/mir-opt/simplify-arm/rustc.id_result.SimplifyBranchSame.diff @@ -0,0 +1,45 @@ +- // MIR for `id_result` before SimplifyBranchSame ++ // MIR for `id_result` after SimplifyBranchSame + + fn id_result(_1: std::result::Result) -> std::result::Result { + debug r => _1; // in scope 0 at $DIR/simplify-arm.rs:16:14: 16:15 + let mut _0: std::result::Result; // return place in scope 0 at $DIR/simplify-arm.rs:16:37: 16:52 + let mut _2: isize; // in scope 0 at $DIR/simplify-arm.rs:18:9: 18:14 + let _3: u8; // in scope 0 at $DIR/simplify-arm.rs:18:12: 18:13 + let mut _4: u8; // in scope 0 at $DIR/simplify-arm.rs:18:21: 18:22 + let _5: i32; // in scope 0 at $DIR/simplify-arm.rs:19:13: 19:14 + let mut _6: i32; // in scope 0 at $DIR/simplify-arm.rs:19:23: 19:24 + scope 1 { + debug x => _3; // in scope 1 at $DIR/simplify-arm.rs:18:12: 18:13 + } + scope 2 { + debug y => _5; // in scope 2 at $DIR/simplify-arm.rs:19:13: 19:14 + } + + bb0: { + _2 = discriminant(_1); // scope 0 at $DIR/simplify-arm.rs:18:9: 18:14 +- switchInt(move _2) -> [0isize: bb3, 1isize: bb1, otherwise: bb2]; // scope 0 at $DIR/simplify-arm.rs:18:9: 18:14 ++ goto -> bb1; // scope 0 at $DIR/simplify-arm.rs:18:9: 18:14 + } + + bb1: { +- _0 = move _1; // scope 2 at $DIR/simplify-arm.rs:19:19: 19:25 +- goto -> bb4; // scope 0 at $DIR/simplify-arm.rs:17:5: 20:6 +- } +- +- bb2: { +- unreachable; // scope 0 at $DIR/simplify-arm.rs:17:11: 17:12 +- } +- +- bb3: { + _0 = move _1; // scope 1 at $DIR/simplify-arm.rs:18:18: 18:23 +- goto -> bb4; // scope 0 at $DIR/simplify-arm.rs:17:5: 20:6 ++ goto -> bb2; // scope 0 at $DIR/simplify-arm.rs:17:5: 20:6 + } + +- bb4: { ++ bb2: { + return; // scope 0 at $DIR/simplify-arm.rs:21:2: 21:2 + } + } + diff --git a/src/test/mir-opt/simplify-arm/rustc.id_try.SimplifyArmIdentity.diff b/src/test/mir-opt/simplify-arm/rustc.id_try.SimplifyArmIdentity.diff new file mode 100644 index 000000000000..ba6e1ac24cb4 --- /dev/null +++ b/src/test/mir-opt/simplify-arm/rustc.id_try.SimplifyArmIdentity.diff @@ -0,0 +1,109 @@ +- // MIR for `id_try` before SimplifyArmIdentity ++ // MIR for `id_try` after SimplifyArmIdentity + + fn id_try(_1: std::result::Result) -> std::result::Result { + debug r => _1; // in scope 0 at $DIR/simplify-arm.rs:23:11: 23:12 + let mut _0: std::result::Result; // return place in scope 0 at $DIR/simplify-arm.rs:23:34: 23:49 + let _2: u8; // in scope 0 at $DIR/simplify-arm.rs:24:9: 24:10 + let mut _3: std::result::Result; // in scope 0 at $DIR/simplify-arm.rs:24:13: 24:15 + let mut _4: std::result::Result; // in scope 0 at $DIR/simplify-arm.rs:24:13: 24:14 + let mut _5: isize; // in scope 0 at $DIR/simplify-arm.rs:24:14: 24:15 + let _6: i32; // in scope 0 at $DIR/simplify-arm.rs:24:14: 24:15 + let mut _7: !; // in scope 0 at $DIR/simplify-arm.rs:24:14: 24:15 + let mut _8: i32; // in scope 0 at $DIR/simplify-arm.rs:24:14: 24:15 + let mut _9: i32; // in scope 0 at $DIR/simplify-arm.rs:24:14: 24:15 + let _10: u8; // in scope 0 at $DIR/simplify-arm.rs:24:13: 24:15 + let mut _11: u8; // in scope 0 at $DIR/simplify-arm.rs:25:8: 25:9 + scope 1 { + debug x => _2; // in scope 1 at $DIR/simplify-arm.rs:24:9: 24:10 + } + scope 2 { + debug err => _6; // in scope 2 at $DIR/simplify-arm.rs:24:14: 24:15 + scope 3 { + } + } + scope 4 { + debug val => _10; // in scope 4 at $DIR/simplify-arm.rs:24:13: 24:15 + scope 5 { + } + } + + bb0: { + StorageLive(_2); // scope 0 at $DIR/simplify-arm.rs:24:9: 24:10 + StorageLive(_3); // scope 0 at $DIR/simplify-arm.rs:24:13: 24:15 + StorageLive(_4); // scope 0 at $DIR/simplify-arm.rs:24:13: 24:14 + _4 = _1; // scope 0 at $DIR/simplify-arm.rs:24:13: 24:14 + _3 = const as std::ops::Try>::into_result(move _4) -> bb1; // scope 0 at $DIR/simplify-arm.rs:24:13: 24:15 + // ty::Const + // + ty: fn(std::result::Result) -> std::result::Result< as std::ops::Try>::Ok, as std::ops::Try>::Error> { as std::ops::Try>::into_result} + // + val: Value(Scalar()) + // mir::Constant + // + span: $DIR/simplify-arm.rs:24:13: 24:15 + // + literal: Const { ty: fn(std::result::Result) -> std::result::Result< as std::ops::Try>::Ok, as std::ops::Try>::Error> { as std::ops::Try>::into_result}, val: Value(Scalar()) } + } + + bb1: { + StorageDead(_4); // scope 0 at $DIR/simplify-arm.rs:24:14: 24:15 + _5 = discriminant(_3); // scope 0 at $DIR/simplify-arm.rs:24:14: 24:15 + switchInt(move _5) -> [0isize: bb2, 1isize: bb4, otherwise: bb3]; // scope 0 at $DIR/simplify-arm.rs:24:14: 24:15 + } + + bb2: { +- StorageLive(_10); // scope 0 at $DIR/simplify-arm.rs:24:13: 24:15 +- _10 = ((_3 as Ok).0: u8); // scope 0 at $DIR/simplify-arm.rs:24:13: 24:15 +- _2 = _10; // scope 5 at $DIR/simplify-arm.rs:24:13: 24:15 +- StorageDead(_10); // scope 0 at $DIR/simplify-arm.rs:24:14: 24:15 ++ _0 = move _3; // scope 1 at $DIR/simplify-arm.rs:25:5: 25:10 + StorageDead(_3); // scope 0 at $DIR/simplify-arm.rs:24:15: 24:16 +- StorageLive(_11); // scope 1 at $DIR/simplify-arm.rs:25:8: 25:9 +- _11 = _2; // scope 1 at $DIR/simplify-arm.rs:25:8: 25:9 +- ((_0 as Ok).0: u8) = move _11; // scope 1 at $DIR/simplify-arm.rs:25:5: 25:10 +- discriminant(_0) = 0; // scope 1 at $DIR/simplify-arm.rs:25:5: 25:10 +- StorageDead(_11); // scope 1 at $DIR/simplify-arm.rs:25:9: 25:10 + StorageDead(_2); // scope 0 at $DIR/simplify-arm.rs:26:1: 26:2 + goto -> bb7; // scope 0 at $DIR/simplify-arm.rs:26:2: 26:2 + } + + bb3: { + unreachable; // scope 0 at $DIR/simplify-arm.rs:24:13: 24:15 + } + + bb4: { + StorageLive(_6); // scope 0 at $DIR/simplify-arm.rs:24:14: 24:15 + _6 = ((_3 as Err).0: i32); // scope 0 at $DIR/simplify-arm.rs:24:14: 24:15 + StorageLive(_8); // scope 3 at $DIR/simplify-arm.rs:24:14: 24:15 + StorageLive(_9); // scope 3 at $DIR/simplify-arm.rs:24:14: 24:15 + _9 = _6; // scope 3 at $DIR/simplify-arm.rs:24:14: 24:15 + _8 = const >::from(move _9) -> bb5; // scope 3 at $DIR/simplify-arm.rs:24:14: 24:15 + // ty::Const + // + ty: fn(i32) -> i32 {>::from} + // + val: Value(Scalar()) + // mir::Constant + // + span: $DIR/simplify-arm.rs:24:14: 24:15 + // + literal: Const { ty: fn(i32) -> i32 {>::from}, val: Value(Scalar()) } + } + + bb5: { + StorageDead(_9); // scope 3 at $DIR/simplify-arm.rs:24:14: 24:15 + _0 = const as std::ops::Try>::from_error(move _8) -> bb6; // scope 3 at $DIR/simplify-arm.rs:24:14: 24:15 + // ty::Const + // + ty: fn( as std::ops::Try>::Error) -> std::result::Result { as std::ops::Try>::from_error} + // + val: Value(Scalar()) + // mir::Constant + // + span: $DIR/simplify-arm.rs:24:13: 24:15 + // + literal: Const { ty: fn( as std::ops::Try>::Error) -> std::result::Result { as std::ops::Try>::from_error}, val: Value(Scalar()) } + } + + bb6: { + StorageDead(_8); // scope 3 at $DIR/simplify-arm.rs:24:14: 24:15 + StorageDead(_6); // scope 0 at $DIR/simplify-arm.rs:24:14: 24:15 + StorageDead(_3); // scope 0 at $DIR/simplify-arm.rs:24:15: 24:16 + StorageDead(_2); // scope 0 at $DIR/simplify-arm.rs:26:1: 26:2 + goto -> bb7; // scope 0 at $DIR/simplify-arm.rs:26:2: 26:2 + } + + bb7: { + return; // scope 0 at $DIR/simplify-arm.rs:26:2: 26:2 + } + } + diff --git a/src/test/mir-opt/simplify-arm/rustc.id_try.SimplifyBranchSame.diff b/src/test/mir-opt/simplify-arm/rustc.id_try.SimplifyBranchSame.diff new file mode 100644 index 000000000000..4061c5e74ac6 --- /dev/null +++ b/src/test/mir-opt/simplify-arm/rustc.id_try.SimplifyBranchSame.diff @@ -0,0 +1,100 @@ +- // MIR for `id_try` before SimplifyBranchSame ++ // MIR for `id_try` after SimplifyBranchSame + + fn id_try(_1: std::result::Result) -> std::result::Result { + debug r => _1; // in scope 0 at $DIR/simplify-arm.rs:23:11: 23:12 + let mut _0: std::result::Result; // return place in scope 0 at $DIR/simplify-arm.rs:23:34: 23:49 + let _2: u8; // in scope 0 at $DIR/simplify-arm.rs:24:9: 24:10 + let mut _3: std::result::Result; // in scope 0 at $DIR/simplify-arm.rs:24:13: 24:15 + let mut _4: std::result::Result; // in scope 0 at $DIR/simplify-arm.rs:24:13: 24:14 + let mut _5: isize; // in scope 0 at $DIR/simplify-arm.rs:24:14: 24:15 + let _6: i32; // in scope 0 at $DIR/simplify-arm.rs:24:14: 24:15 + let mut _7: !; // in scope 0 at $DIR/simplify-arm.rs:24:14: 24:15 + let mut _8: i32; // in scope 0 at $DIR/simplify-arm.rs:24:14: 24:15 + let mut _9: i32; // in scope 0 at $DIR/simplify-arm.rs:24:14: 24:15 + let _10: u8; // in scope 0 at $DIR/simplify-arm.rs:24:13: 24:15 + let mut _11: u8; // in scope 0 at $DIR/simplify-arm.rs:25:8: 25:9 + scope 1 { + debug x => _2; // in scope 1 at $DIR/simplify-arm.rs:24:9: 24:10 + } + scope 2 { + debug err => _6; // in scope 2 at $DIR/simplify-arm.rs:24:14: 24:15 + scope 3 { + } + } + scope 4 { + debug val => _10; // in scope 4 at $DIR/simplify-arm.rs:24:13: 24:15 + scope 5 { + } + } + + bb0: { + StorageLive(_2); // scope 0 at $DIR/simplify-arm.rs:24:9: 24:10 + StorageLive(_3); // scope 0 at $DIR/simplify-arm.rs:24:13: 24:15 + StorageLive(_4); // scope 0 at $DIR/simplify-arm.rs:24:13: 24:14 + _4 = _1; // scope 0 at $DIR/simplify-arm.rs:24:13: 24:14 + _3 = const as std::ops::Try>::into_result(move _4) -> bb1; // scope 0 at $DIR/simplify-arm.rs:24:13: 24:15 + // ty::Const + // + ty: fn(std::result::Result) -> std::result::Result< as std::ops::Try>::Ok, as std::ops::Try>::Error> { as std::ops::Try>::into_result} + // + val: Value(Scalar()) + // mir::Constant + // + span: $DIR/simplify-arm.rs:24:13: 24:15 + // + literal: Const { ty: fn(std::result::Result) -> std::result::Result< as std::ops::Try>::Ok, as std::ops::Try>::Error> { as std::ops::Try>::into_result}, val: Value(Scalar()) } + } + + bb1: { + StorageDead(_4); // scope 0 at $DIR/simplify-arm.rs:24:14: 24:15 + _5 = discriminant(_3); // scope 0 at $DIR/simplify-arm.rs:24:14: 24:15 + switchInt(move _5) -> [0isize: bb2, 1isize: bb4, otherwise: bb3]; // scope 0 at $DIR/simplify-arm.rs:24:14: 24:15 + } + + bb2: { + _0 = move _3; // scope 1 at $DIR/simplify-arm.rs:25:5: 25:10 + StorageDead(_3); // scope 0 at $DIR/simplify-arm.rs:24:15: 24:16 + StorageDead(_2); // scope 0 at $DIR/simplify-arm.rs:26:1: 26:2 + goto -> bb7; // scope 0 at $DIR/simplify-arm.rs:26:2: 26:2 + } + + bb3: { + unreachable; // scope 0 at $DIR/simplify-arm.rs:24:13: 24:15 + } + + bb4: { + StorageLive(_6); // scope 0 at $DIR/simplify-arm.rs:24:14: 24:15 + _6 = ((_3 as Err).0: i32); // scope 0 at $DIR/simplify-arm.rs:24:14: 24:15 + StorageLive(_8); // scope 3 at $DIR/simplify-arm.rs:24:14: 24:15 + StorageLive(_9); // scope 3 at $DIR/simplify-arm.rs:24:14: 24:15 + _9 = _6; // scope 3 at $DIR/simplify-arm.rs:24:14: 24:15 + _8 = const >::from(move _9) -> bb5; // scope 3 at $DIR/simplify-arm.rs:24:14: 24:15 + // ty::Const + // + ty: fn(i32) -> i32 {>::from} + // + val: Value(Scalar()) + // mir::Constant + // + span: $DIR/simplify-arm.rs:24:14: 24:15 + // + literal: Const { ty: fn(i32) -> i32 {>::from}, val: Value(Scalar()) } + } + + bb5: { + StorageDead(_9); // scope 3 at $DIR/simplify-arm.rs:24:14: 24:15 + _0 = const as std::ops::Try>::from_error(move _8) -> bb6; // scope 3 at $DIR/simplify-arm.rs:24:14: 24:15 + // ty::Const + // + ty: fn( as std::ops::Try>::Error) -> std::result::Result { as std::ops::Try>::from_error} + // + val: Value(Scalar()) + // mir::Constant + // + span: $DIR/simplify-arm.rs:24:13: 24:15 + // + literal: Const { ty: fn( as std::ops::Try>::Error) -> std::result::Result { as std::ops::Try>::from_error}, val: Value(Scalar()) } + } + + bb6: { + StorageDead(_8); // scope 3 at $DIR/simplify-arm.rs:24:14: 24:15 + StorageDead(_6); // scope 0 at $DIR/simplify-arm.rs:24:14: 24:15 + StorageDead(_3); // scope 0 at $DIR/simplify-arm.rs:24:15: 24:16 + StorageDead(_2); // scope 0 at $DIR/simplify-arm.rs:26:1: 26:2 + goto -> bb7; // scope 0 at $DIR/simplify-arm.rs:26:2: 26:2 + } + + bb7: { + return; // scope 0 at $DIR/simplify-arm.rs:26:2: 26:2 + } + } + diff --git a/src/test/mir-opt/simplify_try/rustc.try_identity.SimplifyArmIdentity.diff b/src/test/mir-opt/simplify_try/rustc.try_identity.SimplifyArmIdentity.diff index 009153cfd49f..58c5313909f6 100644 --- a/src/test/mir-opt/simplify_try/rustc.try_identity.SimplifyArmIdentity.diff +++ b/src/test/mir-opt/simplify_try/rustc.try_identity.SimplifyArmIdentity.diff @@ -15,16 +15,16 @@ let _10: u32; // in scope 0 at $DIR/simplify_try.rs:6:13: 6:15 let mut _11: u32; // in scope 0 at $DIR/simplify_try.rs:7:8: 7:9 scope 1 { - debug y => _10; // in scope 1 at $DIR/simplify_try.rs:6:9: 6:10 + debug y => _2; // in scope 1 at $DIR/simplify_try.rs:6:9: 6:10 } scope 2 { debug err => _6; // in scope 2 at $DIR/simplify_try.rs:6:14: 6:15 scope 3 { scope 7 { - debug t => _6; // in scope 7 at $SRC_DIR/libcore/convert/mod.rs:LL:COL + debug t => _9; // in scope 7 at $SRC_DIR/libcore/convert/mod.rs:LL:COL } scope 8 { - debug v => _6; // in scope 8 at $SRC_DIR/libcore/result.rs:LL:COL + debug v => _8; // in scope 8 at $SRC_DIR/libcore/result.rs:LL:COL let mut _12: i32; // in scope 8 at $DIR/simplify_try.rs:6:14: 6:15 } } @@ -35,31 +35,54 @@ } } scope 6 { - debug self => _1; // in scope 6 at $SRC_DIR/libcore/result.rs:LL:COL + debug self => _4; // in scope 6 at $SRC_DIR/libcore/result.rs:LL:COL } bb0: { - _5 = discriminant(_1); // scope 0 at $DIR/simplify_try.rs:6:14: 6:15 + StorageLive(_2); // scope 0 at $DIR/simplify_try.rs:6:9: 6:10 + StorageLive(_3); // scope 0 at $DIR/simplify_try.rs:6:13: 6:15 + StorageLive(_4); // scope 0 at $DIR/simplify_try.rs:6:13: 6:14 + _4 = _1; // scope 0 at $DIR/simplify_try.rs:6:13: 6:14 + _3 = move _4; // scope 6 at $SRC_DIR/libcore/result.rs:LL:COL + StorageDead(_4); // scope 0 at $DIR/simplify_try.rs:6:14: 6:15 + _5 = discriminant(_3); // scope 0 at $DIR/simplify_try.rs:6:14: 6:15 switchInt(move _5) -> [0isize: bb1, otherwise: bb2]; // scope 0 at $DIR/simplify_try.rs:6:14: 6:15 } bb1: { -- _10 = ((_1 as Ok).0: u32); // scope 0 at $DIR/simplify_try.rs:6:13: 6:15 -- ((_0 as Ok).0: u32) = move _10; // scope 1 at $DIR/simplify_try.rs:7:5: 7:10 +- StorageLive(_10); // scope 0 at $DIR/simplify_try.rs:6:13: 6:15 +- _10 = ((_3 as Ok).0: u32); // scope 0 at $DIR/simplify_try.rs:6:13: 6:15 +- _2 = _10; // scope 5 at $DIR/simplify_try.rs:6:13: 6:15 +- StorageDead(_10); // scope 0 at $DIR/simplify_try.rs:6:14: 6:15 ++ _0 = move _3; // scope 1 at $DIR/simplify_try.rs:7:5: 7:10 + StorageDead(_3); // scope 0 at $DIR/simplify_try.rs:6:15: 6:16 +- StorageLive(_11); // scope 1 at $DIR/simplify_try.rs:7:8: 7:9 +- _11 = _2; // scope 1 at $DIR/simplify_try.rs:7:8: 7:9 +- ((_0 as Ok).0: u32) = move _11; // scope 1 at $DIR/simplify_try.rs:7:5: 7:10 - discriminant(_0) = 0; // scope 1 at $DIR/simplify_try.rs:7:5: 7:10 -+ _0 = move _1; // scope 1 at $DIR/simplify_try.rs:7:5: 7:10 -+ nop; // scope 1 at $DIR/simplify_try.rs:7:5: 7:10 -+ nop; // scope 1 at $DIR/simplify_try.rs:7:5: 7:10 +- StorageDead(_11); // scope 1 at $DIR/simplify_try.rs:7:9: 7:10 + StorageDead(_2); // scope 0 at $DIR/simplify_try.rs:8:1: 8:2 goto -> bb3; // scope 0 at $DIR/simplify_try.rs:8:2: 8:2 } bb2: { -- _6 = ((_1 as Err).0: i32); // scope 0 at $DIR/simplify_try.rs:6:14: 6:15 -- ((_0 as Err).0: i32) = move _6; // scope 8 at $SRC_DIR/libcore/result.rs:LL:COL +- StorageLive(_6); // scope 0 at $DIR/simplify_try.rs:6:14: 6:15 +- _6 = ((_3 as Err).0: i32); // scope 0 at $DIR/simplify_try.rs:6:14: 6:15 +- StorageLive(_8); // scope 3 at $DIR/simplify_try.rs:6:14: 6:15 +- StorageLive(_9); // scope 3 at $DIR/simplify_try.rs:6:14: 6:15 +- _9 = _6; // scope 3 at $DIR/simplify_try.rs:6:14: 6:15 +- _8 = move _9; // scope 7 at $SRC_DIR/libcore/convert/mod.rs:LL:COL +- StorageDead(_9); // scope 3 at $DIR/simplify_try.rs:6:14: 6:15 +- StorageLive(_12); // scope 8 at $SRC_DIR/libcore/result.rs:LL:COL +- _12 = move _8; // scope 8 at $SRC_DIR/libcore/result.rs:LL:COL +- ((_0 as Err).0: i32) = move _12; // scope 8 at $SRC_DIR/libcore/result.rs:LL:COL - discriminant(_0) = 1; // scope 8 at $SRC_DIR/libcore/result.rs:LL:COL -+ _0 = move _1; // scope 8 at $SRC_DIR/libcore/result.rs:LL:COL -+ nop; // scope 8 at $SRC_DIR/libcore/result.rs:LL:COL -+ nop; // scope 8 at $SRC_DIR/libcore/result.rs:LL:COL +- StorageDead(_12); // scope 8 at $SRC_DIR/libcore/result.rs:LL:COL +- StorageDead(_8); // scope 3 at $DIR/simplify_try.rs:6:14: 6:15 +- StorageDead(_6); // scope 0 at $DIR/simplify_try.rs:6:14: 6:15 ++ _0 = move _3; // scope 8 at $SRC_DIR/libcore/result.rs:LL:COL + StorageDead(_3); // scope 0 at $DIR/simplify_try.rs:6:15: 6:16 + StorageDead(_2); // scope 0 at $DIR/simplify_try.rs:8:1: 8:2 goto -> bb3; // scope 0 at $DIR/simplify_try.rs:8:2: 8:2 } diff --git a/src/test/mir-opt/simplify_try/rustc.try_identity.SimplifyBranchSame.after.mir b/src/test/mir-opt/simplify_try/rustc.try_identity.SimplifyBranchSame.after.mir index e5661a47201d..be61e5e2a9ff 100644 --- a/src/test/mir-opt/simplify_try/rustc.try_identity.SimplifyBranchSame.after.mir +++ b/src/test/mir-opt/simplify_try/rustc.try_identity.SimplifyBranchSame.after.mir @@ -14,16 +14,16 @@ fn try_identity(_1: std::result::Result) -> std::result::Result _10; // in scope 1 at $DIR/simplify_try.rs:6:9: 6:10 + debug y => _2; // in scope 1 at $DIR/simplify_try.rs:6:9: 6:10 } scope 2 { debug err => _6; // in scope 2 at $DIR/simplify_try.rs:6:14: 6:15 scope 3 { scope 7 { - debug t => _6; // in scope 7 at $SRC_DIR/libcore/convert/mod.rs:LL:COL + debug t => _9; // in scope 7 at $SRC_DIR/libcore/convert/mod.rs:LL:COL } scope 8 { - debug v => _6; // in scope 8 at $SRC_DIR/libcore/result.rs:LL:COL + debug v => _8; // in scope 8 at $SRC_DIR/libcore/result.rs:LL:COL let mut _12: i32; // in scope 8 at $DIR/simplify_try.rs:6:14: 6:15 } } @@ -34,18 +34,24 @@ fn try_identity(_1: std::result::Result) -> std::result::Result _1; // in scope 6 at $SRC_DIR/libcore/result.rs:LL:COL + debug self => _4; // in scope 6 at $SRC_DIR/libcore/result.rs:LL:COL } bb0: { - _5 = discriminant(_1); // scope 0 at $DIR/simplify_try.rs:6:14: 6:15 + StorageLive(_2); // scope 0 at $DIR/simplify_try.rs:6:9: 6:10 + StorageLive(_3); // scope 0 at $DIR/simplify_try.rs:6:13: 6:15 + StorageLive(_4); // scope 0 at $DIR/simplify_try.rs:6:13: 6:14 + _4 = _1; // scope 0 at $DIR/simplify_try.rs:6:13: 6:14 + _3 = move _4; // scope 6 at $SRC_DIR/libcore/result.rs:LL:COL + StorageDead(_4); // scope 0 at $DIR/simplify_try.rs:6:14: 6:15 + _5 = discriminant(_3); // scope 0 at $DIR/simplify_try.rs:6:14: 6:15 goto -> bb1; // scope 0 at $DIR/simplify_try.rs:6:14: 6:15 } bb1: { - _0 = move _1; // scope 1 at $DIR/simplify_try.rs:7:5: 7:10 - nop; // scope 1 at $DIR/simplify_try.rs:7:5: 7:10 - nop; // scope 1 at $DIR/simplify_try.rs:7:5: 7:10 + _0 = move _3; // scope 1 at $DIR/simplify_try.rs:7:5: 7:10 + StorageDead(_3); // scope 0 at $DIR/simplify_try.rs:6:15: 6:16 + StorageDead(_2); // scope 0 at $DIR/simplify_try.rs:8:1: 8:2 goto -> bb2; // scope 0 at $DIR/simplify_try.rs:8:2: 8:2 } diff --git a/src/test/mir-opt/simplify_try/rustc.try_identity.SimplifyLocals.after.mir b/src/test/mir-opt/simplify_try/rustc.try_identity.SimplifyLocals.after.mir index 989931ed0eaf..b12036f6a03e 100644 --- a/src/test/mir-opt/simplify_try/rustc.try_identity.SimplifyLocals.after.mir +++ b/src/test/mir-opt/simplify_try/rustc.try_identity.SimplifyLocals.after.mir @@ -3,24 +3,27 @@ fn try_identity(_1: std::result::Result) -> std::result::Result { debug x => _1; // in scope 0 at $DIR/simplify_try.rs:5:17: 5:18 let mut _0: std::result::Result; // return place in scope 0 at $DIR/simplify_try.rs:5:41: 5:57 - let _2: i32; // in scope 0 at $DIR/simplify_try.rs:6:14: 6:15 - let _3: u32; // in scope 0 at $DIR/simplify_try.rs:6:13: 6:15 + let _2: u32; // in scope 0 at $DIR/simplify_try.rs:6:9: 6:10 + let _3: i32; // in scope 0 at $DIR/simplify_try.rs:6:14: 6:15 + let mut _4: i32; // in scope 0 at $DIR/simplify_try.rs:6:14: 6:15 + let mut _5: i32; // in scope 0 at $DIR/simplify_try.rs:6:14: 6:15 + let _6: u32; // in scope 0 at $DIR/simplify_try.rs:6:13: 6:15 scope 1 { - debug y => _3; // in scope 1 at $DIR/simplify_try.rs:6:9: 6:10 + debug y => _2; // in scope 1 at $DIR/simplify_try.rs:6:9: 6:10 } scope 2 { - debug err => _2; // in scope 2 at $DIR/simplify_try.rs:6:14: 6:15 + debug err => _3; // in scope 2 at $DIR/simplify_try.rs:6:14: 6:15 scope 3 { scope 7 { - debug t => _2; // in scope 7 at $SRC_DIR/libcore/convert/mod.rs:LL:COL + debug t => _5; // in scope 7 at $SRC_DIR/libcore/convert/mod.rs:LL:COL } scope 8 { - debug v => _2; // in scope 8 at $SRC_DIR/libcore/result.rs:LL:COL + debug v => _4; // in scope 8 at $SRC_DIR/libcore/result.rs:LL:COL } } } scope 4 { - debug val => _3; // in scope 4 at $DIR/simplify_try.rs:6:13: 6:15 + debug val => _6; // in scope 4 at $DIR/simplify_try.rs:6:13: 6:15 scope 5 { } } @@ -29,7 +32,9 @@ fn try_identity(_1: std::result::Result) -> std::result::Result>, + tail: Option>, +} + +pub struct Node { + next: Option>, +} + +impl LinkedList { + pub fn new() -> Self { + Self { head: None, tail: None } + } + + pub fn append(&mut self, other: &mut Self) { + match self.tail { + None => { }, + Some(mut tail) => { + // `as_mut` is okay here because we have exclusive access to the entirety + // of both lists. + if let Some(other_head) = other.head.take() { + unsafe { + tail.as_mut().next = Some(other_head); + } + } + } + } + } +} + +fn main() { + let mut one = LinkedList::new(); + let mut two = LinkedList::new(); + one.append(&mut two); +} diff --git a/src/test/mir-opt/simplify_try_if_let/rustc.{{impl}}-append.SimplifyArmIdentity.diff b/src/test/mir-opt/simplify_try_if_let/rustc.{{impl}}-append.SimplifyArmIdentity.diff new file mode 100644 index 000000000000..6ccec937b9b9 --- /dev/null +++ b/src/test/mir-opt/simplify_try_if_let/rustc.{{impl}}-append.SimplifyArmIdentity.diff @@ -0,0 +1,127 @@ +- // MIR for `::append` before SimplifyArmIdentity ++ // MIR for `::append` after SimplifyArmIdentity + + fn ::append(_1: &mut LinkedList, _2: &mut LinkedList) -> () { + debug self => _1; // in scope 0 at $DIR/simplify_try_if_let.rs:20:19: 20:28 + debug other => _2; // in scope 0 at $DIR/simplify_try_if_let.rs:20:30: 20:35 + let mut _0: (); // return place in scope 0 at $DIR/simplify_try_if_let.rs:20:48: 20:48 + let mut _3: isize; // in scope 0 at $DIR/simplify_try_if_let.rs:22:13: 22:17 + let mut _4: std::ptr::NonNull; // in scope 0 at $DIR/simplify_try_if_let.rs:23:18: 23:26 + let mut _5: std::option::Option>; // in scope 0 at $DIR/simplify_try_if_let.rs:26:43: 26:60 + let mut _6: &mut std::option::Option>; // in scope 0 at $DIR/simplify_try_if_let.rs:26:43: 26:53 + let mut _7: isize; // in scope 0 at $DIR/simplify_try_if_let.rs:26:24: 26:40 + let mut _9: std::option::Option>; // in scope 0 at $DIR/simplify_try_if_let.rs:28:46: 28:62 + let mut _10: std::ptr::NonNull; // in scope 0 at $DIR/simplify_try_if_let.rs:28:51: 28:61 + let mut _11: &mut Node; // in scope 0 at $DIR/simplify_try_if_let.rs:28:25: 28:38 + let mut _12: &mut std::ptr::NonNull; // in scope 0 at $DIR/simplify_try_if_let.rs:28:25: 28:29 + scope 1 { + debug tail => _4; // in scope 1 at $DIR/simplify_try_if_let.rs:23:18: 23:26 + let _8: std::ptr::NonNull; // in scope 1 at $DIR/simplify_try_if_let.rs:26:29: 26:39 + scope 2 { + debug other_head => _8; // in scope 2 at $DIR/simplify_try_if_let.rs:26:29: 26:39 + scope 3 { + } + } + } + + bb0: { + _3 = discriminant(((*_1).1: std::option::Option>)); // scope 0 at $DIR/simplify_try_if_let.rs:22:13: 22:17 + switchInt(move _3) -> [0isize: bb3, 1isize: bb1, otherwise: bb2]; // scope 0 at $DIR/simplify_try_if_let.rs:22:13: 22:17 + } + + bb1: { + StorageLive(_4); // scope 0 at $DIR/simplify_try_if_let.rs:23:18: 23:26 + _4 = ((((*_1).1: std::option::Option>) as Some).0: std::ptr::NonNull); // scope 0 at $DIR/simplify_try_if_let.rs:23:18: 23:26 + StorageLive(_5); // scope 1 at $DIR/simplify_try_if_let.rs:26:43: 26:60 + StorageLive(_6); // scope 1 at $DIR/simplify_try_if_let.rs:26:43: 26:53 + _6 = &mut ((*_2).0: std::option::Option>); // scope 1 at $DIR/simplify_try_if_let.rs:26:43: 26:53 + _5 = const std::option::Option::>::take(move _6) -> bb4; // scope 1 at $DIR/simplify_try_if_let.rs:26:43: 26:60 + // ty::Const + // + ty: for<'r> fn(&'r mut std::option::Option>) -> std::option::Option> {std::option::Option::>::take} + // + val: Value(Scalar()) + // mir::Constant + // + span: $DIR/simplify_try_if_let.rs:26:54: 26:58 + // + literal: Const { ty: for<'r> fn(&'r mut std::option::Option>) -> std::option::Option> {std::option::Option::>::take}, val: Value(Scalar()) } + } + + bb2: { + unreachable; // scope 0 at $DIR/simplify_try_if_let.rs:21:15: 21:24 + } + + bb3: { + _0 = const (); // scope 0 at $DIR/simplify_try_if_let.rs:22:21: 22:24 + // ty::Const + // + ty: () + // + val: Value(Scalar()) + // mir::Constant + // + span: $DIR/simplify_try_if_let.rs:22:21: 22:24 + // + literal: Const { ty: (), val: Value(Scalar()) } + goto -> bb9; // scope 0 at $DIR/simplify_try_if_let.rs:21:9: 32:10 + } + + bb4: { + StorageDead(_6); // scope 1 at $DIR/simplify_try_if_let.rs:26:59: 26:60 + _7 = discriminant(_5); // scope 1 at $DIR/simplify_try_if_let.rs:26:24: 26:40 + switchInt(move _7) -> [1isize: bb6, otherwise: bb5]; // scope 1 at $DIR/simplify_try_if_let.rs:26:24: 26:40 + } + + bb5: { + _0 = const (); // scope 1 at $DIR/simplify_try_if_let.rs:26:17: 30:18 + // ty::Const + // + ty: () + // + val: Value(Scalar()) + // mir::Constant + // + span: $DIR/simplify_try_if_let.rs:26:17: 30:18 + // + literal: Const { ty: (), val: Value(Scalar()) } + goto -> bb8; // scope 1 at $DIR/simplify_try_if_let.rs:26:17: 30:18 + } + + bb6: { + StorageLive(_8); // scope 1 at $DIR/simplify_try_if_let.rs:26:29: 26:39 + _8 = ((_5 as Some).0: std::ptr::NonNull); // scope 1 at $DIR/simplify_try_if_let.rs:26:29: 26:39 + StorageLive(_9); // scope 3 at $DIR/simplify_try_if_let.rs:28:46: 28:62 +- StorageLive(_10); // scope 3 at $DIR/simplify_try_if_let.rs:28:51: 28:61 +- _10 = _8; // scope 3 at $DIR/simplify_try_if_let.rs:28:51: 28:61 +- ((_9 as Some).0: std::ptr::NonNull) = move _10; // scope 3 at $DIR/simplify_try_if_let.rs:28:46: 28:62 +- discriminant(_9) = 1; // scope 3 at $DIR/simplify_try_if_let.rs:28:46: 28:62 +- StorageDead(_10); // scope 3 at $DIR/simplify_try_if_let.rs:28:61: 28:62 ++ _9 = move _5; // scope 3 at $DIR/simplify_try_if_let.rs:28:46: 28:62 + StorageLive(_11); // scope 3 at $DIR/simplify_try_if_let.rs:28:25: 28:38 + StorageLive(_12); // scope 3 at $DIR/simplify_try_if_let.rs:28:25: 28:29 + _12 = &mut _4; // scope 3 at $DIR/simplify_try_if_let.rs:28:25: 28:29 + _11 = const std::ptr::NonNull::::as_mut(move _12) -> bb7; // scope 3 at $DIR/simplify_try_if_let.rs:28:25: 28:38 + // ty::Const + // + ty: for<'r> unsafe fn(&'r mut std::ptr::NonNull) -> &'r mut Node {std::ptr::NonNull::::as_mut} + // + val: Value(Scalar()) + // mir::Constant + // + span: $DIR/simplify_try_if_let.rs:28:30: 28:36 + // + literal: Const { ty: for<'r> unsafe fn(&'r mut std::ptr::NonNull) -> &'r mut Node {std::ptr::NonNull::::as_mut}, val: Value(Scalar()) } + } + + bb7: { + StorageDead(_12); // scope 3 at $DIR/simplify_try_if_let.rs:28:37: 28:38 + ((*_11).0: std::option::Option>) = move _9; // scope 3 at $DIR/simplify_try_if_let.rs:28:25: 28:62 + StorageDead(_9); // scope 3 at $DIR/simplify_try_if_let.rs:28:61: 28:62 + StorageDead(_11); // scope 3 at $DIR/simplify_try_if_let.rs:28:62: 28:63 + _0 = const (); // scope 3 at $DIR/simplify_try_if_let.rs:27:21: 29:22 + // ty::Const + // + ty: () + // + val: Value(Scalar()) + // mir::Constant + // + span: $DIR/simplify_try_if_let.rs:27:21: 29:22 + // + literal: Const { ty: (), val: Value(Scalar()) } + StorageDead(_8); // scope 1 at $DIR/simplify_try_if_let.rs:30:17: 30:18 + goto -> bb8; // scope 1 at $DIR/simplify_try_if_let.rs:26:17: 30:18 + } + + bb8: { + StorageDead(_5); // scope 1 at $DIR/simplify_try_if_let.rs:31:13: 31:14 + StorageDead(_4); // scope 0 at $DIR/simplify_try_if_let.rs:32:9: 32:10 + goto -> bb9; // scope 0 at $DIR/simplify_try_if_let.rs:21:9: 32:10 + } + + bb9: { + return; // scope 0 at $DIR/simplify_try_if_let.rs:33:6: 33:6 + } + } + From f420726566587862ef4da9153fbc2800ed444033 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 11 May 2020 12:26:59 +1000 Subject: [PATCH 126/203] Remove `RawVec::double`. It's only used once, for `VecDeque`, and can easily be replaced by something else. The commit changes `grow_if_necessary` to `grow` to avoid some small regressions caused by changed inlining. The commit also removes `Strategy::Double`, and streamlines the remaining variants of `Strategy`. It's a compile time win on some benchmarks because the many instantations of `RawVec::grow` are a little smaller. --- src/liballoc/collections/vec_deque.rs | 20 ++++-- src/liballoc/raw_vec.rs | 91 +++------------------------ 2 files changed, 23 insertions(+), 88 deletions(-) diff --git a/src/liballoc/collections/vec_deque.rs b/src/liballoc/collections/vec_deque.rs index 2f50234b6d58..540649c61b33 100644 --- a/src/liballoc/collections/vec_deque.rs +++ b/src/liballoc/collections/vec_deque.rs @@ -1354,7 +1354,9 @@ impl VecDeque { /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn push_front(&mut self, value: T) { - self.grow_if_necessary(); + if self.is_full() { + self.grow(); + } self.tail = self.wrap_sub(self.tail, 1); let tail = self.tail; @@ -1377,7 +1379,9 @@ impl VecDeque { /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn push_back(&mut self, value: T) { - self.grow_if_necessary(); + if self.is_full() { + self.grow(); + } let head = self.head; self.head = self.wrap_add(self.head, 1); @@ -1485,7 +1489,9 @@ impl VecDeque { #[stable(feature = "deque_extras_15", since = "1.5.0")] pub fn insert(&mut self, index: usize, value: T) { assert!(index <= self.len(), "index out of bounds"); - self.grow_if_necessary(); + if self.is_full() { + self.grow(); + } // Move the least number of elements in the ring buffer and insert // the given object @@ -2003,11 +2009,13 @@ impl VecDeque { } // This may panic or abort - #[inline] - fn grow_if_necessary(&mut self) { + #[inline(never)] + fn grow(&mut self) { if self.is_full() { let old_cap = self.cap(); - self.buf.double(); + // Double the buffer size. + self.buf.reserve_exact(old_cap, old_cap); + assert!(self.cap() == old_cap * 2); unsafe { self.handle_capacity_increase(old_cap); } diff --git a/src/liballoc/raw_vec.rs b/src/liballoc/raw_vec.rs index ac5399acddb9..921ef447be05 100644 --- a/src/liballoc/raw_vec.rs +++ b/src/liballoc/raw_vec.rs @@ -211,64 +211,6 @@ impl RawVec { } } - /// Doubles the size of the type's backing allocation. This is common enough - /// to want to do that it's easiest to just have a dedicated method. Slightly - /// more efficient logic can be provided for this than the general case. - /// - /// This function is ideal for when pushing elements one-at-a-time because - /// you don't need to incur the costs of the more general computations - /// reserve needs to do to guard against overflow. You do however need to - /// manually check if your `len == capacity`. - /// - /// # Panics - /// - /// * Panics if `T` is zero-sized on the assumption that you managed to exhaust - /// all `usize::MAX` slots in your imaginary buffer. - /// * Panics on 32-bit platforms if the requested capacity exceeds - /// `isize::MAX` bytes. - /// - /// # Aborts - /// - /// Aborts on OOM - /// - /// # Examples - /// - /// ``` - /// # #![feature(raw_vec_internals)] - /// # extern crate alloc; - /// # use std::ptr; - /// # use alloc::raw_vec::RawVec; - /// struct MyVec { - /// buf: RawVec, - /// len: usize, - /// } - /// - /// impl MyVec { - /// pub fn push(&mut self, elem: T) { - /// if self.len == self.buf.capacity() { self.buf.double(); } - /// // double would have aborted or panicked if the len exceeded - /// // `isize::MAX` so this is safe to do unchecked now. - /// unsafe { - /// ptr::write(self.buf.ptr().add(self.len), elem); - /// } - /// self.len += 1; - /// } - /// } - /// # fn main() { - /// # let mut vec = MyVec { buf: RawVec::new(), len: 0 }; - /// # vec.push(1); - /// # } - /// ``` - #[inline(never)] - #[cold] - pub fn double(&mut self) { - match self.grow(Double, MayMove, Uninitialized) { - Err(CapacityOverflow) => capacity_overflow(), - Err(AllocError { layout, .. }) => handle_alloc_error(layout), - Ok(()) => { /* yay */ } - } - } - /// Ensures that the buffer contains at least enough space to hold /// `used_capacity + needed_extra_capacity` elements. If it doesn't already have /// enough capacity, will reallocate enough space plus comfortable slack @@ -336,7 +278,7 @@ impl RawVec { needed_extra_capacity: usize, ) -> Result<(), TryReserveError> { if self.needs_to_grow(used_capacity, needed_extra_capacity) { - self.grow(Amortized { used_capacity, needed_extra_capacity }, MayMove, Uninitialized) + self.grow(Amortized, used_capacity, needed_extra_capacity, MayMove, Uninitialized) } else { Ok(()) } @@ -363,7 +305,7 @@ impl RawVec { // This is more readable than putting this in one line: // `!self.needs_to_grow(...) || self.grow(...).is_ok()` if self.needs_to_grow(used_capacity, needed_extra_capacity) { - self.grow(Amortized { used_capacity, needed_extra_capacity }, InPlace, Uninitialized) + self.grow(Amortized, used_capacity, needed_extra_capacity, InPlace, Uninitialized) .is_ok() } else { true @@ -405,7 +347,7 @@ impl RawVec { needed_extra_capacity: usize, ) -> Result<(), TryReserveError> { if self.needs_to_grow(used_capacity, needed_extra_capacity) { - self.grow(Exact { used_capacity, needed_extra_capacity }, MayMove, Uninitialized) + self.grow(Exact, used_capacity, needed_extra_capacity, MayMove, Uninitialized) } else { Ok(()) } @@ -432,9 +374,8 @@ impl RawVec { #[derive(Copy, Clone)] enum Strategy { - Double, - Amortized { used_capacity: usize, needed_extra_capacity: usize }, - Exact { used_capacity: usize, needed_extra_capacity: usize }, + Amortized, + Exact, } use Strategy::*; @@ -459,6 +400,8 @@ impl RawVec { fn grow( &mut self, strategy: Strategy, + used_capacity: usize, + needed_extra_capacity: usize, placement: ReallocPlacement, init: AllocInit, ) -> Result<(), TryReserveError> { @@ -469,23 +412,7 @@ impl RawVec { return Err(CapacityOverflow); } let new_layout = match strategy { - Double => unsafe { - // Since we guarantee that we never allocate more than `isize::MAX` bytes, - // `elem_size * self.cap <= isize::MAX` as a precondition, so this can't overflow. - // Additionally the alignment will never be too large as to "not be satisfiable", - // so `Layout::from_size_align` will always return `Some`. - // - // TL;DR, we bypass runtime checks due to dynamic assertions in this module, - // allowing us to use `from_size_align_unchecked`. - let cap = if self.cap == 0 { - // Skip to 4 because tiny `Vec`'s are dumb; but not if that would cause overflow. - if elem_size > usize::MAX / 8 { 1 } else { 4 } - } else { - self.cap * 2 - }; - Layout::from_size_align_unchecked(cap * elem_size, mem::align_of::()) - }, - Amortized { used_capacity, needed_extra_capacity } => { + Amortized => { // Nothing we can really do about these checks, sadly. let required_cap = used_capacity.checked_add(needed_extra_capacity).ok_or(CapacityOverflow)?; @@ -495,7 +422,7 @@ impl RawVec { let cap = cmp::max(double_cap, required_cap); Layout::array::(cap).map_err(|_| CapacityOverflow)? } - Exact { used_capacity, needed_extra_capacity } => { + Exact => { let cap = used_capacity.checked_add(needed_extra_capacity).ok_or(CapacityOverflow)?; Layout::array::(cap).map_err(|_| CapacityOverflow)? From 68b75033ad78d88872450a81745cacfc11e58178 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 11 May 2020 13:17:28 +1000 Subject: [PATCH 127/203] Split `RawVec::grow` up. The amortized case is much more common than the exact case, and it is typically instantiated many times. Also, we can put a chunk of the code into a function that isn't generic over T, which reduces the amount of LLVM IR generated quite a lot, improving compile times. --- src/liballoc/raw_vec.rs | 129 ++++++++++++++++++++++++---------------- 1 file changed, 79 insertions(+), 50 deletions(-) diff --git a/src/liballoc/raw_vec.rs b/src/liballoc/raw_vec.rs index 921ef447be05..d46bf81f996f 100644 --- a/src/liballoc/raw_vec.rs +++ b/src/liballoc/raw_vec.rs @@ -1,7 +1,7 @@ #![unstable(feature = "raw_vec_internals", reason = "implementation detail", issue = "none")] #![doc(hidden)] -use core::alloc::MemoryBlock; +use core::alloc::{LayoutErr, MemoryBlock}; use core::cmp; use core::mem::{self, ManuallyDrop, MaybeUninit}; use core::ops::Drop; @@ -278,7 +278,7 @@ impl RawVec { needed_extra_capacity: usize, ) -> Result<(), TryReserveError> { if self.needs_to_grow(used_capacity, needed_extra_capacity) { - self.grow(Amortized, used_capacity, needed_extra_capacity, MayMove, Uninitialized) + self.grow_amortized(used_capacity, needed_extra_capacity, MayMove) } else { Ok(()) } @@ -305,8 +305,7 @@ impl RawVec { // This is more readable than putting this in one line: // `!self.needs_to_grow(...) || self.grow(...).is_ok()` if self.needs_to_grow(used_capacity, needed_extra_capacity) { - self.grow(Amortized, used_capacity, needed_extra_capacity, InPlace, Uninitialized) - .is_ok() + self.grow_amortized(used_capacity, needed_extra_capacity, InPlace).is_ok() } else { true } @@ -347,7 +346,7 @@ impl RawVec { needed_extra_capacity: usize, ) -> Result<(), TryReserveError> { if self.needs_to_grow(used_capacity, needed_extra_capacity) { - self.grow(Exact, used_capacity, needed_extra_capacity, MayMove, Uninitialized) + self.grow_exact(used_capacity, needed_extra_capacity) } else { Ok(()) } @@ -372,13 +371,6 @@ impl RawVec { } } -#[derive(Copy, Clone)] -enum Strategy { - Amortized, - Exact, -} -use Strategy::*; - impl RawVec { /// Returns if the buffer needs to grow to fulfill the needed extra capacity. /// Mainly used to make inlining reserve-calls possible without inlining `grow`. @@ -396,54 +388,59 @@ impl RawVec { self.cap = Self::capacity_from_bytes(memory.size); } - /// Single method to handle all possibilities of growing the buffer. - fn grow( + // This method is usually instantiated many times. So we want it to be as + // small as possible, to improve compile times. But we also want as much of + // its contents to be statically computable as possible, to make the + // generated code run faster. Therefore, this method is carefully written + // so that all of the code that depends on `T` is within it, while as much + // of the code that doesn't depend on `T` as possible is in functions that + // are non-generic over `T`. + fn grow_amortized( &mut self, - strategy: Strategy, used_capacity: usize, needed_extra_capacity: usize, placement: ReallocPlacement, - init: AllocInit, ) -> Result<(), TryReserveError> { - let elem_size = mem::size_of::(); - if elem_size == 0 { + if mem::size_of::() == 0 { // Since we return a capacity of `usize::MAX` when `elem_size` is // 0, getting to here necessarily means the `RawVec` is overfull. return Err(CapacityOverflow); } - let new_layout = match strategy { - Amortized => { - // Nothing we can really do about these checks, sadly. - let required_cap = - used_capacity.checked_add(needed_extra_capacity).ok_or(CapacityOverflow)?; - // Cannot overflow, because `cap <= isize::MAX`, and type of `cap` is `usize`. - let double_cap = self.cap * 2; - // `double_cap` guarantees exponential growth. - let cap = cmp::max(double_cap, required_cap); - Layout::array::(cap).map_err(|_| CapacityOverflow)? - } - Exact => { - let cap = - used_capacity.checked_add(needed_extra_capacity).ok_or(CapacityOverflow)?; - Layout::array::(cap).map_err(|_| CapacityOverflow)? - } - }; - alloc_guard(new_layout.size())?; - let memory = if let Some((ptr, old_layout)) = self.current_memory() { - debug_assert_eq!(old_layout.align(), new_layout.align()); - unsafe { - self.alloc - .grow(ptr, old_layout, new_layout.size(), placement, init) - .map_err(|_| AllocError { layout: new_layout, non_exhaustive: () })? - } - } else { - match placement { - MayMove => self.alloc.alloc(new_layout, init), - InPlace => Err(AllocErr), - } - .map_err(|_| AllocError { layout: new_layout, non_exhaustive: () })? - }; + // Nothing we can really do about these checks, sadly. + let required_cap = + used_capacity.checked_add(needed_extra_capacity).ok_or(CapacityOverflow)?; + // Cannot overflow, because `cap <= isize::MAX`, and type of `cap` is `usize`. + let double_cap = self.cap * 2; + // `double_cap` guarantees exponential growth. + let cap = cmp::max(double_cap, required_cap); + let new_layout = Layout::array::(cap); + + // `finish_grow` is non-generic over `T`. + let memory = finish_grow(new_layout, placement, self.current_memory(), &mut self.alloc)?; + self.set_memory(memory); + Ok(()) + } + + // The constraints on this method are much the same as those on + // `grow_amortized`, but this method is usually instantiated less often so + // it's less critical. + fn grow_exact( + &mut self, + used_capacity: usize, + needed_extra_capacity: usize, + ) -> Result<(), TryReserveError> { + if mem::size_of::() == 0 { + // Since we return a capacity of `usize::MAX` when the type size is + // 0, getting to here necessarily means the `RawVec` is overfull. + return Err(CapacityOverflow); + } + + let cap = used_capacity.checked_add(needed_extra_capacity).ok_or(CapacityOverflow)?; + let new_layout = Layout::array::(cap); + + // `finish_grow` is non-generic over `T`. + let memory = finish_grow(new_layout, MayMove, self.current_memory(), &mut self.alloc)?; self.set_memory(memory); Ok(()) } @@ -471,6 +468,38 @@ impl RawVec { } } +// This function is outside `RawVec` to minimize compile times. See the comment +// above `RawVec::grow_amortized` for details. (The `A` parameter isn't +// significant, because the number of different `A` types seen in practice is +// much smaller than the number of `T` types.) +fn finish_grow( + new_layout: Result, + placement: ReallocPlacement, + current_memory: Option<(NonNull, Layout)>, + alloc: &mut A, +) -> Result +where + A: AllocRef, +{ + // Check for the error here to minimize the size of `RawVec::grow_*`. + let new_layout = new_layout.map_err(|_| CapacityOverflow)?; + + alloc_guard(new_layout.size())?; + + let memory = if let Some((ptr, old_layout)) = current_memory { + debug_assert_eq!(old_layout.align(), new_layout.align()); + unsafe { alloc.grow(ptr, old_layout, new_layout.size(), placement, Uninitialized) } + } else { + match placement { + MayMove => alloc.alloc(new_layout, Uninitialized), + InPlace => Err(AllocErr), + } + } + .map_err(|_| AllocError { layout: new_layout, non_exhaustive: () })?; + + Ok(memory) +} + impl RawVec { /// Converts the entire buffer into `Box<[MaybeUninit]>` with the specified `len`. /// From 41f6b958d502b3e3d4de1b787a3981c9d752dd78 Mon Sep 17 00:00:00 2001 From: Jack Huey Date: Tue, 12 May 2020 01:56:29 -0400 Subject: [PATCH 128/203] Remove ty::UnnormalizedProjection --- .../debuginfo/type_names.rs | 1 - .../infer/canonical/canonicalizer.rs | 1 - .../infer/error_reporting/need_type_info.rs | 2 +- src/librustc_infer/infer/freshen.rs | 1 - src/librustc_lint/types.rs | 1 - src/librustc_middle/traits/query.rs | 2 -- src/librustc_middle/ty/context.rs | 1 - src/librustc_middle/ty/error.rs | 2 -- src/librustc_middle/ty/fast_reject.rs | 1 - src/librustc_middle/ty/flags.rs | 5 ----- src/librustc_middle/ty/layout.rs | 9 +++----- src/librustc_middle/ty/mod.rs | 2 +- src/librustc_middle/ty/outlives.rs | 2 -- src/librustc_middle/ty/print/mod.rs | 1 - src/librustc_middle/ty/print/obsolete.rs | 1 - src/librustc_middle/ty/print/pretty.rs | 3 --- src/librustc_middle/ty/relate.rs | 5 ----- src/librustc_middle/ty/structural_impls.rs | 7 +----- src/librustc_middle/ty/sty.rs | 7 ------ src/librustc_middle/ty/util.rs | 4 +--- src/librustc_middle/ty/walk.rs | 2 +- .../interpret/intrinsics/type_name.rs | 1 - src/librustc_mir/interpret/validity.rs | 1 - src/librustc_privacy/lib.rs | 2 +- src/librustc_symbol_mangling/legacy.rs | 2 -- src/librustc_symbol_mangling/v0.rs | 1 - .../traits/coherence.rs | 7 +++--- .../traits/error_reporting/mod.rs | 1 - .../traits/query/dropck_outlives.rs | 2 -- src/librustc_trait_selection/traits/select.rs | 9 +++----- src/librustc_trait_selection/traits/wf.rs | 2 -- src/librustc_traits/chalk/lowering.rs | 1 - src/librustc_traits/dropck_outlives.rs | 2 -- src/librustc_ty/ty.rs | 2 -- src/librustc_typeck/check/cast.rs | 1 - src/librustc_typeck/variance/constraints.rs | 6 +---- src/librustdoc/clean/mod.rs | 1 - .../internal-lints/ty_tykind_usage.rs | 1 - .../internal-lints/ty_tykind_usage.stderr | 22 +++++++------------ 39 files changed, 24 insertions(+), 100 deletions(-) diff --git a/src/librustc_codegen_ssa/debuginfo/type_names.rs b/src/librustc_codegen_ssa/debuginfo/type_names.rs index 6c0e4128e30f..1d8730db5460 100644 --- a/src/librustc_codegen_ssa/debuginfo/type_names.rs +++ b/src/librustc_codegen_ssa/debuginfo/type_names.rs @@ -198,7 +198,6 @@ pub fn push_debuginfo_type_name<'tcx>( ty::Error | ty::Infer(_) | ty::Placeholder(..) - | ty::UnnormalizedProjection(..) | ty::Projection(..) | ty::Bound(..) | ty::Opaque(..) diff --git a/src/librustc_infer/infer/canonical/canonicalizer.rs b/src/librustc_infer/infer/canonical/canonicalizer.rs index a0b5dd45a0e2..5551b56ab797 100644 --- a/src/librustc_infer/infer/canonical/canonicalizer.rs +++ b/src/librustc_infer/infer/canonical/canonicalizer.rs @@ -415,7 +415,6 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for Canonicalizer<'cx, 'tcx> { | ty::Never | ty::Tuple(..) | ty::Projection(..) - | ty::UnnormalizedProjection(..) | ty::Foreign(..) | ty::Param(..) | ty::Opaque(..) => { diff --git a/src/librustc_infer/infer/error_reporting/need_type_info.rs b/src/librustc_infer/infer/error_reporting/need_type_info.rs index d8133c58df7e..0141ba827377 100644 --- a/src/librustc_infer/infer/error_reporting/need_type_info.rs +++ b/src/librustc_infer/infer/error_reporting/need_type_info.rs @@ -554,7 +554,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { let output = bound_output.skip_binder(); err.span_label(e.span, &format!("this method call resolves to `{:?}`", output)); let kind = &output.kind; - if let ty::Projection(proj) | ty::UnnormalizedProjection(proj) = kind { + if let ty::Projection(proj) = kind { if let Some(span) = self.tcx.hir().span_if_local(proj.item_def_id) { err.span_label(span, &format!("`{:?}` defined here", output)); } diff --git a/src/librustc_infer/infer/freshen.rs b/src/librustc_infer/infer/freshen.rs index 47346c3a8566..c9ed687eaf25 100644 --- a/src/librustc_infer/infer/freshen.rs +++ b/src/librustc_infer/infer/freshen.rs @@ -204,7 +204,6 @@ impl<'a, 'tcx> TypeFolder<'tcx> for TypeFreshener<'a, 'tcx> { | ty::Never | ty::Tuple(..) | ty::Projection(..) - | ty::UnnormalizedProjection(..) | ty::Foreign(..) | ty::Param(..) | ty::Closure(..) diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs index 1d97b2860247..703c2a7a443a 100644 --- a/src/librustc_lint/types.rs +++ b/src/librustc_lint/types.rs @@ -888,7 +888,6 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { | ty::Generator(..) | ty::GeneratorWitness(..) | ty::Placeholder(..) - | ty::UnnormalizedProjection(..) | ty::Projection(..) | ty::Opaque(..) | ty::FnDef(..) => bug!("unexpected type in foreign function: {:?}", ty), diff --git a/src/librustc_middle/traits/query.rs b/src/librustc_middle/traits/query.rs index 67f4b15f9194..e030125b5b15 100644 --- a/src/librustc_middle/traits/query.rs +++ b/src/librustc_middle/traits/query.rs @@ -255,8 +255,6 @@ pub fn trivial_dropck_outlives<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> bool { | ty::Infer(_) | ty::Bound(..) | ty::Generator(..) => false, - - ty::UnnormalizedProjection(..) => bug!("only used with chalk-engine"), } } diff --git a/src/librustc_middle/ty/context.rs b/src/librustc_middle/ty/context.rs index 86b740b8503b..7feb080d4b8d 100644 --- a/src/librustc_middle/ty/context.rs +++ b/src/librustc_middle/ty/context.rs @@ -1878,7 +1878,6 @@ impl<'tcx> TyCtxt<'tcx> { Bound, Param, Infer, - UnnormalizedProjection, Projection, Opaque, Foreign diff --git a/src/librustc_middle/ty/error.rs b/src/librustc_middle/ty/error.rs index f3b6a53dfeb8..cf63a659e6c0 100644 --- a/src/librustc_middle/ty/error.rs +++ b/src/librustc_middle/ty/error.rs @@ -284,7 +284,6 @@ impl<'tcx> ty::TyS<'tcx> { ty::Infer(ty::FreshIntTy(_)) => "fresh integral type".into(), ty::Infer(ty::FreshFloatTy(_)) => "fresh floating-point type".into(), ty::Projection(_) => "associated type".into(), - ty::UnnormalizedProjection(_) => "non-normalized associated type".into(), ty::Param(p) => format!("type parameter `{}`", p).into(), ty::Opaque(..) => "opaque type".into(), ty::Error => "type error".into(), @@ -323,7 +322,6 @@ impl<'tcx> ty::TyS<'tcx> { ty::Placeholder(..) => "higher-ranked type".into(), ty::Bound(..) => "bound type variable".into(), ty::Projection(_) => "associated type".into(), - ty::UnnormalizedProjection(_) => "associated type".into(), ty::Param(_) => "type parameter".into(), ty::Opaque(..) => "opaque type".into(), } diff --git a/src/librustc_middle/ty/fast_reject.rs b/src/librustc_middle/ty/fast_reject.rs index 2a937d6581d6..16d8e3794076 100644 --- a/src/librustc_middle/ty/fast_reject.rs +++ b/src/librustc_middle/ty/fast_reject.rs @@ -90,7 +90,6 @@ pub fn simplify_type( ty::Never => Some(NeverSimplifiedType), ty::Tuple(ref tys) => Some(TupleSimplifiedType(tys.len())), ty::FnPtr(ref f) => Some(FunctionSimplifiedType(f.skip_binder().inputs().len())), - ty::UnnormalizedProjection(..) => bug!("only used with chalk-engine"), ty::Projection(_) | ty::Param(_) => { if can_simplify_params { // In normalized types, projections don't unify with diff --git a/src/librustc_middle/ty/flags.rs b/src/librustc_middle/ty/flags.rs index a88f36281099..042ffc4d1e55 100644 --- a/src/librustc_middle/ty/flags.rs +++ b/src/librustc_middle/ty/flags.rs @@ -121,11 +121,6 @@ impl FlagComputation { self.add_projection_ty(data); } - &ty::UnnormalizedProjection(ref data) => { - self.add_flags(TypeFlags::HAS_TY_PROJECTION); - self.add_projection_ty(data); - } - &ty::Opaque(_, substs) => { self.add_flags(TypeFlags::HAS_TY_OPAQUE); self.add_substs(substs); diff --git a/src/librustc_middle/ty/layout.rs b/src/librustc_middle/ty/layout.rs index 7c4e4d095bc5..1339281667e7 100644 --- a/src/librustc_middle/ty/layout.rs +++ b/src/librustc_middle/ty/layout.rs @@ -1241,11 +1241,9 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { tcx.layout_raw(param_env.and(normalized))? } - ty::Bound(..) - | ty::Placeholder(..) - | ty::UnnormalizedProjection(..) - | ty::GeneratorWitness(..) - | ty::Infer(_) => bug!("Layout::compute: unexpected type `{}`", ty), + ty::Bound(..) | ty::Placeholder(..) | ty::GeneratorWitness(..) | ty::Infer(_) => { + bug!("Layout::compute: unexpected type `{}`", ty) + } ty::Param(_) | ty::Error => { return Err(LayoutError::Unknown(ty)); @@ -2138,7 +2136,6 @@ where } ty::Projection(_) - | ty::UnnormalizedProjection(..) | ty::Bound(..) | ty::Placeholder(..) | ty::Opaque(..) diff --git a/src/librustc_middle/ty/mod.rs b/src/librustc_middle/ty/mod.rs index 02fe7adcd073..5ed3c3dab934 100644 --- a/src/librustc_middle/ty/mod.rs +++ b/src/librustc_middle/ty/mod.rs @@ -555,7 +555,7 @@ bitflags! { | TypeFlags::HAS_CT_PLACEHOLDER.bits | TypeFlags::HAS_FREE_LOCAL_REGIONS.bits; - /// Does this have [Projection] or [UnnormalizedProjection]? + /// Does this have [Projection]? const HAS_TY_PROJECTION = 1 << 10; /// Does this have [Opaque]? const HAS_TY_OPAQUE = 1 << 11; diff --git a/src/librustc_middle/ty/outlives.rs b/src/librustc_middle/ty/outlives.rs index 4fd4d0d1f062..afd670b85775 100644 --- a/src/librustc_middle/ty/outlives.rs +++ b/src/librustc_middle/ty/outlives.rs @@ -135,8 +135,6 @@ fn compute_components(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, out: &mut SmallVec<[Compo } } - ty::UnnormalizedProjection(..) => bug!("only used with chalk-engine"), - // We assume that inference variables are fully resolved. // So, if we encounter an inference variable, just record // the unresolved variable as a component. diff --git a/src/librustc_middle/ty/print/mod.rs b/src/librustc_middle/ty/print/mod.rs index 6bdc65eb0564..69b36980bd73 100644 --- a/src/librustc_middle/ty/print/mod.rs +++ b/src/librustc_middle/ty/print/mod.rs @@ -294,7 +294,6 @@ pub fn characteristic_def_id_of_type(ty: Ty<'_>) -> Option { | ty::FnPtr(_) | ty::Projection(_) | ty::Placeholder(..) - | ty::UnnormalizedProjection(..) | ty::Param(_) | ty::Opaque(..) | ty::Infer(_) diff --git a/src/librustc_middle/ty/print/obsolete.rs b/src/librustc_middle/ty/print/obsolete.rs index 757a8bd23f62..41a6cd5466f5 100644 --- a/src/librustc_middle/ty/print/obsolete.rs +++ b/src/librustc_middle/ty/print/obsolete.rs @@ -148,7 +148,6 @@ impl DefPathBasedNames<'tcx> { | ty::Bound(..) | ty::Infer(_) | ty::Placeholder(..) - | ty::UnnormalizedProjection(..) | ty::Projection(..) | ty::Param(_) | ty::GeneratorWitness(_) diff --git a/src/librustc_middle/ty/print/pretty.rs b/src/librustc_middle/ty/print/pretty.rs index 2684492a4069..06ad90a147ad 100644 --- a/src/librustc_middle/ty/print/pretty.rs +++ b/src/librustc_middle/ty/print/pretty.rs @@ -540,9 +540,6 @@ pub trait PrettyPrinter<'tcx>: p!(print_def_path(def_id, &[])); } ty::Projection(ref data) => p!(print(data)), - ty::UnnormalizedProjection(ref data) => { - p!(write("Unnormalized("), print(data), write(")")) - } ty::Placeholder(placeholder) => p!(write("Placeholder({:?})", placeholder)), ty::Opaque(def_id, substs) => { // FIXME(eddyb) print this with `print_def_path`. diff --git a/src/librustc_middle/ty/relate.rs b/src/librustc_middle/ty/relate.rs index 9c198dd556ac..d68bc7221f92 100644 --- a/src/librustc_middle/ty/relate.rs +++ b/src/librustc_middle/ty/relate.rs @@ -477,11 +477,6 @@ pub fn super_relate_tys>( Ok(tcx.mk_fn_ptr(fty)) } - (ty::UnnormalizedProjection(a_data), ty::UnnormalizedProjection(b_data)) => { - let projection_ty = relation.relate(a_data, b_data)?; - Ok(tcx.mk_ty(ty::UnnormalizedProjection(projection_ty))) - } - // these two are already handled downstream in case of lazy normalization (ty::Projection(a_data), ty::Projection(b_data)) => { let projection_ty = relation.relate(a_data, b_data)?; diff --git a/src/librustc_middle/ty/structural_impls.rs b/src/librustc_middle/ty/structural_impls.rs index c8406a024ecf..680b71879219 100644 --- a/src/librustc_middle/ty/structural_impls.rs +++ b/src/librustc_middle/ty/structural_impls.rs @@ -888,9 +888,6 @@ impl<'tcx> TypeFoldable<'tcx> for Ty<'tcx> { ty::GeneratorWitness(types) => ty::GeneratorWitness(types.fold_with(folder)), ty::Closure(did, substs) => ty::Closure(did, substs.fold_with(folder)), ty::Projection(ref data) => ty::Projection(data.fold_with(folder)), - ty::UnnormalizedProjection(ref data) => { - ty::UnnormalizedProjection(data.fold_with(folder)) - } ty::Opaque(did, substs) => ty::Opaque(did, substs.fold_with(folder)), ty::Bool @@ -931,9 +928,7 @@ impl<'tcx> TypeFoldable<'tcx> for Ty<'tcx> { ty::Generator(_did, ref substs, _) => substs.visit_with(visitor), ty::GeneratorWitness(ref types) => types.visit_with(visitor), ty::Closure(_did, ref substs) => substs.visit_with(visitor), - ty::Projection(ref data) | ty::UnnormalizedProjection(ref data) => { - data.visit_with(visitor) - } + ty::Projection(ref data) => data.visit_with(visitor), ty::Opaque(_, ref substs) => substs.visit_with(visitor), ty::Bool diff --git a/src/librustc_middle/ty/sty.rs b/src/librustc_middle/ty/sty.rs index a6cf3b7e2ee7..2ad673b2c194 100644 --- a/src/librustc_middle/ty/sty.rs +++ b/src/librustc_middle/ty/sty.rs @@ -181,11 +181,6 @@ pub enum TyKind<'tcx> { /// `>::N`. Projection(ProjectionTy<'tcx>), - /// A placeholder type used when we do not have enough information - /// to normalize the projection of an associated type to an - /// existing concrete type. Currently only used with chalk-engine. - UnnormalizedProjection(ProjectionTy<'tcx>), - /// Opaque (`impl Trait`) type found in a return type. /// The `DefId` comes either from /// * the `impl Trait` ast::Ty node, @@ -2186,8 +2181,6 @@ impl<'tcx> TyS<'tcx> { ty::Projection(_) | ty::Param(_) | ty::Opaque(..) => false, - ty::UnnormalizedProjection(..) => bug!("only used with chalk-engine"), - ty::Infer(ty::TyVar(_)) => false, ty::Bound(..) diff --git a/src/librustc_middle/ty/util.rs b/src/librustc_middle/ty/util.rs index a89927ecfb72..f9c10488ffbc 100644 --- a/src/librustc_middle/ty/util.rs +++ b/src/librustc_middle/ty/util.rs @@ -745,8 +745,7 @@ impl<'tcx> ty::TyS<'tcx> { | ty::Opaque(..) | ty::Param(_) | ty::Placeholder(_) - | ty::Projection(_) - | ty::UnnormalizedProjection(_) => false, + | ty::Projection(_) => false, } } @@ -1077,7 +1076,6 @@ pub fn needs_drop_components( // These require checking for `Copy` bounds or `Adt` destructors. ty::Adt(..) | ty::Projection(..) - | ty::UnnormalizedProjection(..) | ty::Param(_) | ty::Bound(..) | ty::Placeholder(..) diff --git a/src/librustc_middle/ty/walk.rs b/src/librustc_middle/ty/walk.rs index b6cadd009965..0093c60d7689 100644 --- a/src/librustc_middle/ty/walk.rs +++ b/src/librustc_middle/ty/walk.rs @@ -127,7 +127,7 @@ fn push_inner<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent: GenericArg<'tcx>) stack.push(ty.into()); stack.push(lt.into()); } - ty::Projection(data) | ty::UnnormalizedProjection(data) => { + ty::Projection(data) => { stack.extend(data.substs.iter().copied().rev()); } ty::Dynamic(obj, lt) => { diff --git a/src/librustc_mir/interpret/intrinsics/type_name.rs b/src/librustc_mir/interpret/intrinsics/type_name.rs index b81a454cac40..71cca725982f 100644 --- a/src/librustc_mir/interpret/intrinsics/type_name.rs +++ b/src/librustc_mir/interpret/intrinsics/type_name.rs @@ -60,7 +60,6 @@ impl<'tcx> Printer<'tcx> for AbsolutePathPrinter<'tcx> { | ty::FnDef(def_id, substs) | ty::Opaque(def_id, substs) | ty::Projection(ty::ProjectionTy { item_def_id: def_id, substs }) - | ty::UnnormalizedProjection(ty::ProjectionTy { item_def_id: def_id, substs }) | ty::Closure(def_id, substs) | ty::Generator(def_id, substs, _) => self.print_def_path(def_id, substs), ty::Foreign(def_id) => self.print_def_path(def_id, &[]), diff --git a/src/librustc_mir/interpret/validity.rs b/src/librustc_mir/interpret/validity.rs index 4f90f83b735d..748cb8d9d1a4 100644 --- a/src/librustc_mir/interpret/validity.rs +++ b/src/librustc_mir/interpret/validity.rs @@ -566,7 +566,6 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, ' | ty::Bound(..) | ty::Param(..) | ty::Opaque(..) - | ty::UnnormalizedProjection(..) | ty::Projection(..) | ty::GeneratorWitness(..) => bug!("Encountered invalid type {:?}", ty), } diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index 917e2f548302..b474b23ac4f5 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -160,7 +160,7 @@ where } } } - ty::Projection(proj) | ty::UnnormalizedProjection(proj) => { + ty::Projection(proj) => { if self.def_id_visitor.skip_assoc_tys() { // Visitors searching for minimal visibility/reachability want to // conservatively approximate associated types like `::Alias` diff --git a/src/librustc_symbol_mangling/legacy.rs b/src/librustc_symbol_mangling/legacy.rs index 01e9356b42f4..3038b0c6bd7e 100644 --- a/src/librustc_symbol_mangling/legacy.rs +++ b/src/librustc_symbol_mangling/legacy.rs @@ -216,7 +216,6 @@ impl Printer<'tcx> for SymbolPrinter<'tcx> { ty::FnDef(def_id, substs) | ty::Opaque(def_id, substs) | ty::Projection(ty::ProjectionTy { item_def_id: def_id, substs }) - | ty::UnnormalizedProjection(ty::ProjectionTy { item_def_id: def_id, substs }) | ty::Closure(def_id, substs) | ty::Generator(def_id, substs, _) => self.print_def_path(def_id, substs), _ => self.pretty_print_type(ty), @@ -264,7 +263,6 @@ impl Printer<'tcx> for SymbolPrinter<'tcx> { ty::FnDef(..) | ty::Opaque(..) | ty::Projection(_) - | ty::UnnormalizedProjection(_) | ty::Closure(..) | ty::Generator(..) if trait_ref.is_none() => diff --git a/src/librustc_symbol_mangling/v0.rs b/src/librustc_symbol_mangling/v0.rs index 53df140e0b5a..3b439e09a9d1 100644 --- a/src/librustc_symbol_mangling/v0.rs +++ b/src/librustc_symbol_mangling/v0.rs @@ -413,7 +413,6 @@ impl Printer<'tcx> for SymbolMangler<'tcx> { | ty::FnDef(def_id, substs) | ty::Opaque(def_id, substs) | ty::Projection(ty::ProjectionTy { item_def_id: def_id, substs }) - | ty::UnnormalizedProjection(ty::ProjectionTy { item_def_id: def_id, substs }) | ty::Closure(def_id, substs) | ty::Generator(def_id, substs, _) => { self = self.print_def_path(def_id, substs)?; diff --git a/src/librustc_trait_selection/traits/coherence.rs b/src/librustc_trait_selection/traits/coherence.rs index f9ff772900bb..85c2f9246afc 100644 --- a/src/librustc_trait_selection/traits/coherence.rs +++ b/src/librustc_trait_selection/traits/coherence.rs @@ -567,9 +567,8 @@ fn ty_is_non_local_constructor(ty: Ty<'_>, in_crate: InCrate) -> Option> ty::Error => None, - ty::UnnormalizedProjection(..) - | ty::Closure(..) - | ty::Generator(..) - | ty::GeneratorWitness(..) => bug!("ty_is_local invoked on unexpected type: {:?}", ty), + ty::Closure(..) | ty::Generator(..) | ty::GeneratorWitness(..) => { + bug!("ty_is_local invoked on unexpected type: {:?}", ty) + } } } diff --git a/src/librustc_trait_selection/traits/error_reporting/mod.rs b/src/librustc_trait_selection/traits/error_reporting/mod.rs index 405c656bad56..1620bdfa66e1 100644 --- a/src/librustc_trait_selection/traits/error_reporting/mod.rs +++ b/src/librustc_trait_selection/traits/error_reporting/mod.rs @@ -1194,7 +1194,6 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> { ty::Foreign(..) => Some(19), ty::GeneratorWitness(..) => Some(20), ty::Placeholder(..) | ty::Bound(..) | ty::Infer(..) | ty::Error => None, - ty::UnnormalizedProjection(..) => bug!("only used with chalk-engine"), } } diff --git a/src/librustc_trait_selection/traits/query/dropck_outlives.rs b/src/librustc_trait_selection/traits/query/dropck_outlives.rs index 64cc5fadeab0..856a2111fc82 100644 --- a/src/librustc_trait_selection/traits/query/dropck_outlives.rs +++ b/src/librustc_trait_selection/traits/query/dropck_outlives.rs @@ -135,7 +135,5 @@ pub fn trivial_dropck_outlives<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> bool { | ty::Infer(_) | ty::Bound(..) | ty::Generator(..) => false, - - ty::UnnormalizedProjection(..) => bug!("only used with chalk-engine"), } } diff --git a/src/librustc_trait_selection/traits/select.rs b/src/librustc_trait_selection/traits/select.rs index b595f77e4d6f..f0ff30232b96 100644 --- a/src/librustc_trait_selection/traits/select.rs +++ b/src/librustc_trait_selection/traits/select.rs @@ -2178,8 +2178,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { ty::Projection(_) | ty::Param(_) | ty::Opaque(..) => None, ty::Infer(ty::TyVar(_)) => Ambiguous, - ty::UnnormalizedProjection(..) - | ty::Placeholder(..) + ty::Placeholder(..) | ty::Bound(..) | ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => { bug!("asked to assemble builtin bounds of unexpected type: {:?}", self_ty); @@ -2250,8 +2249,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { Ambiguous } - ty::UnnormalizedProjection(..) - | ty::Placeholder(..) + ty::Placeholder(..) | ty::Bound(..) | ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => { bug!("asked to assemble builtin bounds of unexpected type: {:?}", self_ty); @@ -2284,8 +2282,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { | ty::Never | ty::Char => Vec::new(), - ty::UnnormalizedProjection(..) - | ty::Placeholder(..) + ty::Placeholder(..) | ty::Dynamic(..) | ty::Param(..) | ty::Foreign(..) diff --git a/src/librustc_trait_selection/traits/wf.rs b/src/librustc_trait_selection/traits/wf.rs index 1d4afeaae42c..ba7ec96775c0 100644 --- a/src/librustc_trait_selection/traits/wf.rs +++ b/src/librustc_trait_selection/traits/wf.rs @@ -389,8 +389,6 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { self.compute_projection(data); } - ty::UnnormalizedProjection(..) => bug!("only used with chalk-engine"), - ty::Adt(def, substs) => { // WfNominalType let obligations = self.nominal_obligations(def.did, substs); diff --git a/src/librustc_traits/chalk/lowering.rs b/src/librustc_traits/chalk/lowering.rs index 4dc15a6b2b65..6ba8e63886b0 100644 --- a/src/librustc_traits/chalk/lowering.rs +++ b/src/librustc_traits/chalk/lowering.rs @@ -353,7 +353,6 @@ impl<'tcx> LowerInto<'tcx, chalk_ir::Ty>> for Ty<'tcx> { apply(chalk_ir::TypeName::Tuple(substs.len()), substs.lower_into(interner)) } Projection(proj) => TyData::Alias(proj.lower_into(interner)).intern(interner), - UnnormalizedProjection(_proj) => unimplemented!(), Opaque(_def_id, _substs) => unimplemented!(), // This should have been done eagerly prior to this, and all Params // should have been substituted to placeholders diff --git a/src/librustc_traits/dropck_outlives.rs b/src/librustc_traits/dropck_outlives.rs index 76ff58d61a25..08475d6a09db 100644 --- a/src/librustc_traits/dropck_outlives.rs +++ b/src/librustc_traits/dropck_outlives.rs @@ -271,8 +271,6 @@ fn dtorck_constraint_for_ty<'tcx>( constraints.dtorck_types.push(ty); } - ty::UnnormalizedProjection(..) => bug!("only used with chalk-engine"), - ty::Placeholder(..) | ty::Bound(..) | ty::Infer(..) | ty::Error => { // By the time this code runs, all type variables ought to // be fully resolved. diff --git a/src/librustc_ty/ty.rs b/src/librustc_ty/ty.rs index 6add099e75bd..1aa11a761c82 100644 --- a/src/librustc_ty/ty.rs +++ b/src/librustc_ty/ty.rs @@ -47,8 +47,6 @@ fn sized_constraint_for_ty<'tcx>( vec![ty] } - UnnormalizedProjection(..) => bug!("only used with chalk-engine"), - Param(..) => { // perf hack: if there is a `T: Sized` bound, then // we know that `T` is Sized and do not need to check diff --git a/src/librustc_typeck/check/cast.rs b/src/librustc_typeck/check/cast.rs index 981e6d2c47ee..46d6706cbf42 100644 --- a/src/librustc_typeck/check/cast.rs +++ b/src/librustc_typeck/check/cast.rs @@ -115,7 +115,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ty::Foreign(..) => Some(PointerKind::Thin), // We should really try to normalize here. ty::Projection(ref pi) => Some(PointerKind::OfProjection(pi)), - ty::UnnormalizedProjection(..) => bug!("only used with chalk-engine"), ty::Opaque(def_id, substs) => Some(PointerKind::OfOpaque(def_id, substs)), ty::Param(ref p) => Some(PointerKind::OfParam(p)), // Insufficient type information. diff --git a/src/librustc_typeck/variance/constraints.rs b/src/librustc_typeck/variance/constraints.rs index 01d077d47f03..3a680f55c8c3 100644 --- a/src/librustc_typeck/variance/constraints.rs +++ b/src/librustc_typeck/variance/constraints.rs @@ -344,11 +344,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { // types, where we use Error as the Self type } - ty::Placeholder(..) - | ty::UnnormalizedProjection(..) - | ty::GeneratorWitness(..) - | ty::Bound(..) - | ty::Infer(..) => { + ty::Placeholder(..) | ty::GeneratorWitness(..) | ty::Bound(..) | ty::Infer(..) => { bug!( "unexpected type encountered in \ variance inference: {}", diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 8cd9ab41aa40..6c001bc54841 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1722,7 +1722,6 @@ impl<'tcx> Clean for Ty<'tcx> { ty::Bound(..) => panic!("Bound"), ty::Placeholder(..) => panic!("Placeholder"), - ty::UnnormalizedProjection(..) => panic!("UnnormalizedProjection"), ty::GeneratorWitness(..) => panic!("GeneratorWitness"), ty::Infer(..) => panic!("Infer"), ty::Error => panic!("Error"), diff --git a/src/test/ui-fulldeps/internal-lints/ty_tykind_usage.rs b/src/test/ui-fulldeps/internal-lints/ty_tykind_usage.rs index 66b594a1b095..27fe432e96de 100644 --- a/src/test/ui-fulldeps/internal-lints/ty_tykind_usage.rs +++ b/src/test/ui-fulldeps/internal-lints/ty_tykind_usage.rs @@ -32,7 +32,6 @@ fn main() { TyKind::Never => (), //~ ERROR usage of `ty::TyKind::` TyKind::Tuple(..) => (), //~ ERROR usage of `ty::TyKind::` TyKind::Projection(..) => (), //~ ERROR usage of `ty::TyKind::` - TyKind::UnnormalizedProjection(..) => (), //~ ERROR usage of `ty::TyKind::` TyKind::Opaque(..) => (), //~ ERROR usage of `ty::TyKind::` TyKind::Param(..) => (), //~ ERROR usage of `ty::TyKind::` TyKind::Bound(..) => (), //~ ERROR usage of `ty::TyKind::` diff --git a/src/test/ui-fulldeps/internal-lints/ty_tykind_usage.stderr b/src/test/ui-fulldeps/internal-lints/ty_tykind_usage.stderr index ee9f1ff10f88..0486c90a5a07 100644 --- a/src/test/ui-fulldeps/internal-lints/ty_tykind_usage.stderr +++ b/src/test/ui-fulldeps/internal-lints/ty_tykind_usage.stderr @@ -139,58 +139,52 @@ LL | TyKind::Projection(..) => (), error: usage of `ty::TyKind::` --> $DIR/ty_tykind_usage.rs:35:9 | -LL | TyKind::UnnormalizedProjection(..) => (), +LL | TyKind::Opaque(..) => (), | ^^^^^^ help: try using ty:: directly: `ty` error: usage of `ty::TyKind::` --> $DIR/ty_tykind_usage.rs:36:9 | -LL | TyKind::Opaque(..) => (), +LL | TyKind::Param(..) => (), | ^^^^^^ help: try using ty:: directly: `ty` error: usage of `ty::TyKind::` --> $DIR/ty_tykind_usage.rs:37:9 | -LL | TyKind::Param(..) => (), +LL | TyKind::Bound(..) => (), | ^^^^^^ help: try using ty:: directly: `ty` error: usage of `ty::TyKind::` --> $DIR/ty_tykind_usage.rs:38:9 | -LL | TyKind::Bound(..) => (), +LL | TyKind::Placeholder(..) => (), | ^^^^^^ help: try using ty:: directly: `ty` error: usage of `ty::TyKind::` --> $DIR/ty_tykind_usage.rs:39:9 | -LL | TyKind::Placeholder(..) => (), +LL | TyKind::Infer(..) => (), | ^^^^^^ help: try using ty:: directly: `ty` error: usage of `ty::TyKind::` --> $DIR/ty_tykind_usage.rs:40:9 | -LL | TyKind::Infer(..) => (), - | ^^^^^^ help: try using ty:: directly: `ty` - -error: usage of `ty::TyKind::` - --> $DIR/ty_tykind_usage.rs:41:9 - | LL | TyKind::Error => (), | ^^^^^^ help: try using ty:: directly: `ty` error: usage of `ty::TyKind::` - --> $DIR/ty_tykind_usage.rs:46:12 + --> $DIR/ty_tykind_usage.rs:45:12 | LL | if let TyKind::Int(int_ty) = kind {} | ^^^^^^ help: try using ty:: directly: `ty` error: usage of `ty::TyKind` - --> $DIR/ty_tykind_usage.rs:48:24 + --> $DIR/ty_tykind_usage.rs:47:24 | LL | fn ty_kind(ty_bad: TyKind<'_>, ty_good: Ty<'_>) {} | ^^^^^^^^^^ | = help: try using `Ty` instead -error: aborting due to 31 previous errors +error: aborting due to 30 previous errors From 6f9810c981f43cab6f4598d2d3b3e6e9b82d56ee Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 12 May 2020 09:46:41 +0200 Subject: [PATCH 129/203] strings do not have to be valid UTF-8 any more --- src/librustc_mir/interpret/validity.rs | 7 ++++--- src/test/ui/consts/const-eval/ub-wide-ptr.rs | 8 ++++---- src/test/ui/consts/const-eval/ub-wide-ptr.stderr | 8 ++++---- 3 files changed, 12 insertions(+), 11 deletions(-) diff --git a/src/librustc_mir/interpret/validity.rs b/src/librustc_mir/interpret/validity.rs index 4f90f83b735d..7eb05ba2d2c5 100644 --- a/src/librustc_mir/interpret/validity.rs +++ b/src/librustc_mir/interpret/validity.rs @@ -15,7 +15,7 @@ use rustc_middle::mir::interpret::{InterpError, InterpErrorInfo}; use rustc_middle::ty; use rustc_middle::ty::layout::TyAndLayout; use rustc_span::symbol::{sym, Symbol}; -use rustc_target::abi::{Abi, LayoutOf, Scalar, VariantIdx, Variants}; +use rustc_target::abi::{Abi, LayoutOf, Scalar, Size, VariantIdx, Variants}; use std::hash::Hash; @@ -744,10 +744,11 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M> match op.layout.ty.kind { ty::Str => { let mplace = op.assert_mem_place(self.ecx); // strings are never immediate + let len = mplace.len(self.ecx)?; try_validation!( - self.ecx.read_str(mplace), + self.ecx.memory.read_bytes(mplace.ptr, Size::from_bytes(len)), self.path, - err_ub!(InvalidStr(..)) => { "uninitialized or non-UTF-8 data in str" }, + err_ub!(InvalidUninitBytes(..)) => { "uninitialized data in `str`" }, ); } ty::Array(tys, ..) | ty::Slice(tys) diff --git a/src/test/ui/consts/const-eval/ub-wide-ptr.rs b/src/test/ui/consts/const-eval/ub-wide-ptr.rs index 29ac32fcf220..f69f6a1109f7 100644 --- a/src/test/ui/consts/const-eval/ub-wide-ptr.rs +++ b/src/test/ui/consts/const-eval/ub-wide-ptr.rs @@ -42,11 +42,11 @@ const MY_STR_LENGTH_PTR: &MyStr = unsafe { mem::transmute((&42u8, &3)) }; const MY_STR_MUCH_TOO_LONG: &MyStr = unsafe { mem::transmute((&42u8, usize::MAX)) }; //~^ ERROR it is undefined behavior to use this value -// invalid UTF-8 -const STR_NO_UTF8: &str = unsafe { mem::transmute::<&[u8], _>(&[0xFF]) }; +// uninitialized byte +const STR_NO_INIT: &str = unsafe { mem::transmute::<&[_], _>(&[MaybeUninit:: { uninit: () }]) }; //~^ ERROR it is undefined behavior to use this value -// invalid UTF-8 in user-defined str-like -const MYSTR_NO_UTF8: &MyStr = unsafe { mem::transmute::<&[u8], _>(&[0xFF]) }; +// uninitialized byte in user-defined str-like +const MYSTR_NO_INIT: &MyStr = unsafe { mem::transmute::<&[_], _>(&[MaybeUninit:: { uninit: () }]) }; //~^ ERROR it is undefined behavior to use this value // # slice diff --git a/src/test/ui/consts/const-eval/ub-wide-ptr.stderr b/src/test/ui/consts/const-eval/ub-wide-ptr.stderr index 063ea81036b6..47d29ffc9b3c 100644 --- a/src/test/ui/consts/const-eval/ub-wide-ptr.stderr +++ b/src/test/ui/consts/const-eval/ub-wide-ptr.stderr @@ -41,16 +41,16 @@ LL | const MY_STR_MUCH_TOO_LONG: &MyStr = unsafe { mem::transmute((&42u8, usize: error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:46:1 | -LL | const STR_NO_UTF8: &str = unsafe { mem::transmute::<&[u8], _>(&[0xFF]) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized or non-UTF-8 data in str at . +LL | const STR_NO_INIT: &str = unsafe { mem::transmute::<&[_], _>(&[MaybeUninit:: { uninit: () }]) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized data in `str` at . | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value --> $DIR/ub-wide-ptr.rs:49:1 | -LL | const MYSTR_NO_UTF8: &MyStr = unsafe { mem::transmute::<&[u8], _>(&[0xFF]) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized or non-UTF-8 data in str at ..0 +LL | const MYSTR_NO_INIT: &MyStr = unsafe { mem::transmute::<&[_], _>(&[MaybeUninit:: { uninit: () }]) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered uninitialized data in `str` at ..0 | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. From 98d625441501aa23284a1897c4a6511a46a86ce5 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 12 May 2020 15:56:02 +1000 Subject: [PATCH 130/203] Change `WorkProduct::saved_files` to an `Option`. Because there is at most one file. --- src/librustc_codegen_ssa/back/write.rs | 14 ++---- src/librustc_incremental/lib.rs | 2 +- src/librustc_incremental/persist/load.rs | 2 +- src/librustc_incremental/persist/mod.rs | 2 +- src/librustc_incremental/persist/save.rs | 8 ++-- .../persist/work_product.rs | 46 +++++++++---------- src/librustc_query_system/dep_graph/graph.rs | 4 +- 7 files changed, 36 insertions(+), 42 deletions(-) diff --git a/src/librustc_codegen_ssa/back/write.rs b/src/librustc_codegen_ssa/back/write.rs index 6210559251de..46e17d66d61d 100644 --- a/src/librustc_codegen_ssa/back/write.rs +++ b/src/librustc_codegen_ssa/back/write.rs @@ -21,7 +21,7 @@ use rustc_errors::{DiagnosticId, FatalError, Handler, Level}; use rustc_fs_util::link_or_copy; use rustc_hir::def_id::{CrateNum, LOCAL_CRATE}; use rustc_incremental::{ - copy_cgu_workproducts_to_incr_comp_cache_dir, in_incr_comp_dir, in_incr_comp_dir_sess, + copy_cgu_workproduct_to_incr_comp_cache_dir, in_incr_comp_dir, in_incr_comp_dir_sess, }; use rustc_middle::dep_graph::{WorkProduct, WorkProductId}; use rustc_middle::middle::cstore::EncodedMetadata; @@ -465,17 +465,13 @@ fn copy_all_cgu_workproducts_to_incr_comp_cache_dir( return work_products; } - let _timer = sess.timer("incr_comp_copy_cgu_workproducts"); + let _timer = sess.timer("copy_all_cgu_workproducts_to_incr_comp_cache_dir"); for module in compiled_modules.modules.iter().filter(|m| m.kind == ModuleKind::Regular) { - let mut files = vec![]; - - if let Some(ref path) = module.object { - files.push(path.clone()); - } + let path = module.object.as_ref().map(|path| path.clone()); if let Some((id, product)) = - copy_cgu_workproducts_to_incr_comp_cache_dir(sess, &module.name, &files) + copy_cgu_workproduct_to_incr_comp_cache_dir(sess, &module.name, &path) { work_products.insert(id, product); } @@ -817,7 +813,7 @@ fn execute_copy_from_cache_work_item( ) -> Result, FatalError> { let incr_comp_session_dir = cgcx.incr_comp_session_dir.as_ref().unwrap(); let mut object = None; - for saved_file in &module.source.saved_files { + if let Some(saved_file) = module.source.saved_file { let obj_out = cgcx.output_filenames.temp_path(OutputType::Object, Some(&module.name)); object = Some(obj_out.clone()); let source_file = in_incr_comp_dir(&incr_comp_session_dir, &saved_file); diff --git a/src/librustc_incremental/lib.rs b/src/librustc_incremental/lib.rs index dd715c6c81d5..7fd4b3c2554f 100644 --- a/src/librustc_incremental/lib.rs +++ b/src/librustc_incremental/lib.rs @@ -15,7 +15,7 @@ pub mod assert_module_sources; mod persist; pub use assert_dep_graph::assert_dep_graph; -pub use persist::copy_cgu_workproducts_to_incr_comp_cache_dir; +pub use persist::copy_cgu_workproduct_to_incr_comp_cache_dir; pub use persist::delete_workproduct_files; pub use persist::dep_graph_tcx_init; pub use persist::finalize_session_directory; diff --git a/src/librustc_incremental/persist/load.rs b/src/librustc_incremental/persist/load.rs index 99c799950c06..966faa9639d7 100644 --- a/src/librustc_incremental/persist/load.rs +++ b/src/librustc_incremental/persist/load.rs @@ -134,7 +134,7 @@ pub fn load_dep_graph(sess: &Session) -> DepGraphFuture { for swp in work_products { let mut all_files_exist = true; - for file_name in swp.work_product.saved_files.iter() { + if let Some(ref file_name) = swp.work_product.saved_file { let path = in_incr_comp_dir_sess(sess, file_name); if !path.exists() { all_files_exist = false; diff --git a/src/librustc_incremental/persist/mod.rs b/src/librustc_incremental/persist/mod.rs index 6a03a01430b0..7bc3b47e15ad 100644 --- a/src/librustc_incremental/persist/mod.rs +++ b/src/librustc_incremental/persist/mod.rs @@ -21,5 +21,5 @@ pub use load::LoadResult; pub use load::{load_dep_graph, DepGraphFuture}; pub use save::save_dep_graph; pub use save::save_work_product_index; -pub use work_product::copy_cgu_workproducts_to_incr_comp_cache_dir; +pub use work_product::copy_cgu_workproduct_to_incr_comp_cache_dir; pub use work_product::delete_workproduct_files; diff --git a/src/librustc_incremental/persist/save.rs b/src/librustc_incremental/persist/save.rs index 4db6297712c5..c43d4ad4049c 100644 --- a/src/librustc_incremental/persist/save.rs +++ b/src/librustc_incremental/persist/save.rs @@ -74,9 +74,9 @@ pub fn save_work_product_index( if !new_work_products.contains_key(id) { work_product::delete_workproduct_files(sess, wp); debug_assert!( - wp.saved_files - .iter() - .all(|file_name| { !in_incr_comp_dir_sess(sess, file_name).exists() }) + wp.saved_file.as_ref().map_or(true, |file_name| { + !in_incr_comp_dir_sess(sess, &file_name).exists() + }) ); } } @@ -85,7 +85,7 @@ pub fn save_work_product_index( debug_assert!({ new_work_products .iter() - .flat_map(|(_, wp)| wp.saved_files.iter()) + .flat_map(|(_, wp)| wp.saved_file.iter()) .map(|name| in_incr_comp_dir_sess(sess, name)) .all(|path| path.exists()) }); diff --git a/src/librustc_incremental/persist/work_product.rs b/src/librustc_incremental/persist/work_product.rs index a15ee6d81dbb..19d64bda56d6 100644 --- a/src/librustc_incremental/persist/work_product.rs +++ b/src/librustc_incremental/persist/work_product.rs @@ -7,43 +7,41 @@ use rustc_session::Session; use std::fs as std_fs; use std::path::PathBuf; -pub fn copy_cgu_workproducts_to_incr_comp_cache_dir( +pub fn copy_cgu_workproduct_to_incr_comp_cache_dir( sess: &Session, cgu_name: &str, - files: &[PathBuf], + path: &Option, ) -> Option<(WorkProductId, WorkProduct)> { - debug!("copy_cgu_workproducts_to_incr_comp_cache_dir({:?},{:?})", cgu_name, files); + debug!("copy_cgu_workproduct_to_incr_comp_cache_dir({:?},{:?})", cgu_name, path); sess.opts.incremental.as_ref()?; - let saved_files = files - .iter() - .map(|path| { - let file_name = format!("{}.o", cgu_name); - let path_in_incr_dir = in_incr_comp_dir_sess(sess, &file_name); - match link_or_copy(path, &path_in_incr_dir) { - Ok(_) => Some(file_name), - Err(err) => { - sess.warn(&format!( - "error copying object file `{}` \ - to incremental directory as `{}`: {}", - path.display(), - path_in_incr_dir.display(), - err - )); - None - } + let saved_file = if let Some(path) = path { + let file_name = format!("{}.o", cgu_name); + let path_in_incr_dir = in_incr_comp_dir_sess(sess, &file_name); + match link_or_copy(path, &path_in_incr_dir) { + Ok(_) => Some(file_name), + Err(err) => { + sess.warn(&format!( + "error copying object file `{}` to incremental directory as `{}`: {}", + path.display(), + path_in_incr_dir.display(), + err + )); + return None; } - }) - .collect::>>()?; + } + } else { + None + }; - let work_product = WorkProduct { cgu_name: cgu_name.to_string(), saved_files }; + let work_product = WorkProduct { cgu_name: cgu_name.to_string(), saved_file }; let work_product_id = WorkProductId::from_cgu_name(cgu_name); Some((work_product_id, work_product)) } pub fn delete_workproduct_files(sess: &Session, work_product: &WorkProduct) { - for file_name in &work_product.saved_files { + if let Some(ref file_name) = work_product.saved_file { let path = in_incr_comp_dir_sess(sess, file_name); match std_fs::remove_file(&path) { Ok(()) => {} diff --git a/src/librustc_query_system/dep_graph/graph.rs b/src/librustc_query_system/dep_graph/graph.rs index 5f14a09b24da..04a45090b722 100644 --- a/src/librustc_query_system/dep_graph/graph.rs +++ b/src/librustc_query_system/dep_graph/graph.rs @@ -860,8 +860,8 @@ impl DepGraph { #[derive(Clone, Debug, RustcEncodable, RustcDecodable)] pub struct WorkProduct { pub cgu_name: String, - /// Saved files associated with this CGU. - pub saved_files: Vec, + /// Saved file associated with this CGU. + pub saved_file: Option, } #[derive(Clone)] From c849a0d087546d9ef5a47593287b2bc1ec5bfcaf Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Tue, 12 May 2020 12:55:55 +0200 Subject: [PATCH 131/203] Add a repro example for not propagating constants of partially const initialized variables --- ...mutable_variable_aggregate_partial_read.rs | 14 +++++ .../rustc.main.ConstProp.diff | 55 +++++++++++++++++++ 2 files changed, 69 insertions(+) create mode 100644 src/test/mir-opt/const_prop/mutable_variable_aggregate_partial_read.rs create mode 100644 src/test/mir-opt/const_prop/mutable_variable_aggregate_partial_read/rustc.main.ConstProp.diff diff --git a/src/test/mir-opt/const_prop/mutable_variable_aggregate_partial_read.rs b/src/test/mir-opt/const_prop/mutable_variable_aggregate_partial_read.rs new file mode 100644 index 000000000000..4f43ec8c9470 --- /dev/null +++ b/src/test/mir-opt/const_prop/mutable_variable_aggregate_partial_read.rs @@ -0,0 +1,14 @@ +// compile-flags: -O + +// EMIT_MIR rustc.main.ConstProp.diff +fn main() { + let mut x: (i32, i32) = foo(); + x.1 = 99; + x.0 = 42; + let y = x.1; +} + +#[inline(never)] +fn foo() -> (i32, i32) { + unimplemented!() +} diff --git a/src/test/mir-opt/const_prop/mutable_variable_aggregate_partial_read/rustc.main.ConstProp.diff b/src/test/mir-opt/const_prop/mutable_variable_aggregate_partial_read/rustc.main.ConstProp.diff new file mode 100644 index 000000000000..b88bb9b49156 --- /dev/null +++ b/src/test/mir-opt/const_prop/mutable_variable_aggregate_partial_read/rustc.main.ConstProp.diff @@ -0,0 +1,55 @@ +- // MIR for `main` before ConstProp ++ // MIR for `main` after ConstProp + + fn main() -> () { + let mut _0: (); // return place in scope 0 at $DIR/mutable_variable_aggregate_partial_read.rs:4:11: 4:11 + let mut _1: (i32, i32) as UserTypeProjection { base: UserType(0), projs: [] }; // in scope 0 at $DIR/mutable_variable_aggregate_partial_read.rs:5:9: 5:14 + scope 1 { + debug x => _1; // in scope 1 at $DIR/mutable_variable_aggregate_partial_read.rs:5:9: 5:14 + let _2: i32; // in scope 1 at $DIR/mutable_variable_aggregate_partial_read.rs:8:9: 8:10 + scope 2 { + debug y => _2; // in scope 2 at $DIR/mutable_variable_aggregate_partial_read.rs:8:9: 8:10 + } + } + + bb0: { + StorageLive(_1); // scope 0 at $DIR/mutable_variable_aggregate_partial_read.rs:5:9: 5:14 + _1 = const foo() -> bb1; // scope 0 at $DIR/mutable_variable_aggregate_partial_read.rs:5:29: 5:34 + // ty::Const + // + ty: fn() -> (i32, i32) {foo} + // + val: Value(Scalar()) + // mir::Constant + // + span: $DIR/mutable_variable_aggregate_partial_read.rs:5:29: 5:32 + // + literal: Const { ty: fn() -> (i32, i32) {foo}, val: Value(Scalar()) } + } + + bb1: { + (_1.1: i32) = const 99i32; // scope 1 at $DIR/mutable_variable_aggregate_partial_read.rs:6:5: 6:13 + // ty::Const + // + ty: i32 + // + val: Value(Scalar(0x00000063)) + // mir::Constant + // + span: $DIR/mutable_variable_aggregate_partial_read.rs:6:11: 6:13 + // + literal: Const { ty: i32, val: Value(Scalar(0x00000063)) } + (_1.0: i32) = const 42i32; // scope 1 at $DIR/mutable_variable_aggregate_partial_read.rs:7:5: 7:13 + // ty::Const + // + ty: i32 + // + val: Value(Scalar(0x0000002a)) + // mir::Constant + // + span: $DIR/mutable_variable_aggregate_partial_read.rs:7:11: 7:13 + // + literal: Const { ty: i32, val: Value(Scalar(0x0000002a)) } + StorageLive(_2); // scope 1 at $DIR/mutable_variable_aggregate_partial_read.rs:8:9: 8:10 + _2 = (_1.1: i32); // scope 1 at $DIR/mutable_variable_aggregate_partial_read.rs:8:13: 8:16 + _0 = const (); // scope 0 at $DIR/mutable_variable_aggregate_partial_read.rs:4:11: 9:2 + // ty::Const + // + ty: () + // + val: Value(Scalar()) + // mir::Constant + // + span: $DIR/mutable_variable_aggregate_partial_read.rs:4:11: 9:2 + // + literal: Const { ty: (), val: Value(Scalar()) } + StorageDead(_2); // scope 1 at $DIR/mutable_variable_aggregate_partial_read.rs:9:1: 9:2 + StorageDead(_1); // scope 0 at $DIR/mutable_variable_aggregate_partial_read.rs:9:1: 9:2 + return; // scope 0 at $DIR/mutable_variable_aggregate_partial_read.rs:9:2: 9:2 + } + } + From de434d8e44b40451eff0020832bb9a9303b32067 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Tue, 12 May 2020 13:14:47 +0200 Subject: [PATCH 132/203] Propagate locals, even if they have unpropagatable assignments somewhere. --- src/librustc_mir/transform/const_prop.rs | 20 ++++++++++++++++++- .../rustc.main.ConstProp.diff | 15 +++++++++++--- 2 files changed, 31 insertions(+), 4 deletions(-) diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index e898f22ec230..d66c909fe6cc 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -775,6 +775,10 @@ impl<'tcx> Visitor<'tcx> for CanConstProp { // Projections are fine, because `&mut foo.x` will be caught by // `MutatingUseContext::Borrow` elsewhere. MutatingUse(MutatingUseContext::Projection) + // These are just stores, where the storing is not propagatable, but there may be later + // mutations of the same local via `Store` + | MutatingUse(MutatingUseContext::Call) + // Actual store that can possibly even propagate a value | MutatingUse(MutatingUseContext::Store) => { if !self.found_assignment.insert(local) { match &mut self.can_const_prop[local] { @@ -799,7 +803,21 @@ impl<'tcx> Visitor<'tcx> for CanConstProp { | NonMutatingUse(NonMutatingUseContext::Inspect) | NonMutatingUse(NonMutatingUseContext::Projection) | NonUse(_) => {} - _ => { + + // These could be propagated with a smarter analysis or just some careful thinking about + // whether they'd be fine right now. + MutatingUse(MutatingUseContext::AsmOutput) + | MutatingUse(MutatingUseContext::Yield) + | MutatingUse(MutatingUseContext::Drop) + | MutatingUse(MutatingUseContext::Retag) + // These can't ever be propagated under any scheme, as we can't reason about indirect + // mutation. + | NonMutatingUse(NonMutatingUseContext::SharedBorrow) + | NonMutatingUse(NonMutatingUseContext::ShallowBorrow) + | NonMutatingUse(NonMutatingUseContext::UniqueBorrow) + | NonMutatingUse(NonMutatingUseContext::AddressOf) + | MutatingUse(MutatingUseContext::Borrow) + | MutatingUse(MutatingUseContext::AddressOf) => { trace!("local {:?} can't be propagaged because it's used: {:?}", local, context); self.can_const_prop[local] = ConstPropMode::NoPropagation; } diff --git a/src/test/mir-opt/const_prop/mutable_variable_aggregate_partial_read/rustc.main.ConstProp.diff b/src/test/mir-opt/const_prop/mutable_variable_aggregate_partial_read/rustc.main.ConstProp.diff index b88bb9b49156..3cf05f135783 100644 --- a/src/test/mir-opt/const_prop/mutable_variable_aggregate_partial_read/rustc.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/mutable_variable_aggregate_partial_read/rustc.main.ConstProp.diff @@ -29,17 +29,26 @@ // + ty: i32 // + val: Value(Scalar(0x00000063)) // mir::Constant - // + span: $DIR/mutable_variable_aggregate_partial_read.rs:6:11: 6:13 +- // + span: $DIR/mutable_variable_aggregate_partial_read.rs:6:11: 6:13 ++ // + span: $DIR/mutable_variable_aggregate_partial_read.rs:6:5: 6:13 // + literal: Const { ty: i32, val: Value(Scalar(0x00000063)) } (_1.0: i32) = const 42i32; // scope 1 at $DIR/mutable_variable_aggregate_partial_read.rs:7:5: 7:13 // ty::Const // + ty: i32 // + val: Value(Scalar(0x0000002a)) // mir::Constant - // + span: $DIR/mutable_variable_aggregate_partial_read.rs:7:11: 7:13 +- // + span: $DIR/mutable_variable_aggregate_partial_read.rs:7:11: 7:13 ++ // + span: $DIR/mutable_variable_aggregate_partial_read.rs:7:5: 7:13 // + literal: Const { ty: i32, val: Value(Scalar(0x0000002a)) } StorageLive(_2); // scope 1 at $DIR/mutable_variable_aggregate_partial_read.rs:8:9: 8:10 - _2 = (_1.1: i32); // scope 1 at $DIR/mutable_variable_aggregate_partial_read.rs:8:13: 8:16 +- _2 = (_1.1: i32); // scope 1 at $DIR/mutable_variable_aggregate_partial_read.rs:8:13: 8:16 ++ _2 = const 99i32; // scope 1 at $DIR/mutable_variable_aggregate_partial_read.rs:8:13: 8:16 ++ // ty::Const ++ // + ty: i32 ++ // + val: Value(Scalar(0x00000063)) ++ // mir::Constant ++ // + span: $DIR/mutable_variable_aggregate_partial_read.rs:8:13: 8:16 ++ // + literal: Const { ty: i32, val: Value(Scalar(0x00000063)) } _0 = const (); // scope 0 at $DIR/mutable_variable_aggregate_partial_read.rs:4:11: 9:2 // ty::Const // + ty: () From 0a785cdf34e2eba2200677aa2a397bc3ddeed270 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Tue, 12 May 2020 13:23:01 +0200 Subject: [PATCH 133/203] Add some more sanity tests and add a debug log message for it --- src/librustc_mir/transform/const_prop.rs | 5 ++ .../mutable_variable_unprop_assign.rs | 15 ++++ .../rustc.main.ConstProp.diff | 74 +++++++++++++++++++ 3 files changed, 94 insertions(+) create mode 100644 src/test/mir-opt/const_prop/mutable_variable_unprop_assign.rs create mode 100644 src/test/mir-opt/const_prop/mutable_variable_unprop_assign/rustc.main.ConstProp.diff diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index d66c909fe6cc..88dfa90ac21d 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -893,6 +893,11 @@ impl<'mir, 'tcx> MutVisitor<'tcx> for ConstPropagator<'mir, 'tcx> { // ``` // FIXME: we overzealously erase the entire local, because that's easier to // implement. + trace!( + "propagation into {:?} failed. + Nuking the entire site from orbit, it's the only way to be sure", + place, + ); Self::remove_const(&mut self.ecx, place.local); } } diff --git a/src/test/mir-opt/const_prop/mutable_variable_unprop_assign.rs b/src/test/mir-opt/const_prop/mutable_variable_unprop_assign.rs new file mode 100644 index 000000000000..40f801b1b5e5 --- /dev/null +++ b/src/test/mir-opt/const_prop/mutable_variable_unprop_assign.rs @@ -0,0 +1,15 @@ +// compile-flags: -O + +// EMIT_MIR rustc.main.ConstProp.diff +fn main() { + let a = foo(); + let mut x: (i32, i32) = (1, 2); + x.1 = a; + let y = x.1; + let z = x.0; // this could theoretically be allowed, but we can't handle it right now +} + +#[inline(never)] +fn foo() -> i32 { + unimplemented!() +} diff --git a/src/test/mir-opt/const_prop/mutable_variable_unprop_assign/rustc.main.ConstProp.diff b/src/test/mir-opt/const_prop/mutable_variable_unprop_assign/rustc.main.ConstProp.diff new file mode 100644 index 000000000000..738343c655e3 --- /dev/null +++ b/src/test/mir-opt/const_prop/mutable_variable_unprop_assign/rustc.main.ConstProp.diff @@ -0,0 +1,74 @@ +- // MIR for `main` before ConstProp ++ // MIR for `main` after ConstProp + + fn main() -> () { + let mut _0: (); // return place in scope 0 at $DIR/mutable_variable_unprop_assign.rs:4:11: 4:11 + let _1: i32; // in scope 0 at $DIR/mutable_variable_unprop_assign.rs:5:9: 5:10 + let mut _3: i32; // in scope 0 at $DIR/mutable_variable_unprop_assign.rs:7:11: 7:12 + scope 1 { + debug a => _1; // in scope 1 at $DIR/mutable_variable_unprop_assign.rs:5:9: 5:10 + let mut _2: (i32, i32) as UserTypeProjection { base: UserType(0), projs: [] }; // in scope 1 at $DIR/mutable_variable_unprop_assign.rs:6:9: 6:14 + scope 2 { + debug x => _2; // in scope 2 at $DIR/mutable_variable_unprop_assign.rs:6:9: 6:14 + let _4: i32; // in scope 2 at $DIR/mutable_variable_unprop_assign.rs:8:9: 8:10 + scope 3 { + debug y => _4; // in scope 3 at $DIR/mutable_variable_unprop_assign.rs:8:9: 8:10 + let _5: i32; // in scope 3 at $DIR/mutable_variable_unprop_assign.rs:9:9: 9:10 + scope 4 { + debug z => _5; // in scope 4 at $DIR/mutable_variable_unprop_assign.rs:9:9: 9:10 + } + } + } + } + + bb0: { + StorageLive(_1); // scope 0 at $DIR/mutable_variable_unprop_assign.rs:5:9: 5:10 + _1 = const foo() -> bb1; // scope 0 at $DIR/mutable_variable_unprop_assign.rs:5:13: 5:18 + // ty::Const + // + ty: fn() -> i32 {foo} + // + val: Value(Scalar()) + // mir::Constant + // + span: $DIR/mutable_variable_unprop_assign.rs:5:13: 5:16 + // + literal: Const { ty: fn() -> i32 {foo}, val: Value(Scalar()) } + } + + bb1: { + StorageLive(_2); // scope 1 at $DIR/mutable_variable_unprop_assign.rs:6:9: 6:14 + _2 = (const 1i32, const 2i32); // scope 1 at $DIR/mutable_variable_unprop_assign.rs:6:29: 6:35 + // ty::Const + // + ty: i32 + // + val: Value(Scalar(0x00000001)) + // mir::Constant +- // + span: $DIR/mutable_variable_unprop_assign.rs:6:30: 6:31 ++ // + span: $DIR/mutable_variable_unprop_assign.rs:6:29: 6:35 + // + literal: Const { ty: i32, val: Value(Scalar(0x00000001)) } + // ty::Const + // + ty: i32 + // + val: Value(Scalar(0x00000002)) + // mir::Constant +- // + span: $DIR/mutable_variable_unprop_assign.rs:6:33: 6:34 ++ // + span: $DIR/mutable_variable_unprop_assign.rs:6:29: 6:35 + // + literal: Const { ty: i32, val: Value(Scalar(0x00000002)) } + StorageLive(_3); // scope 2 at $DIR/mutable_variable_unprop_assign.rs:7:11: 7:12 + _3 = _1; // scope 2 at $DIR/mutable_variable_unprop_assign.rs:7:11: 7:12 + (_2.1: i32) = move _3; // scope 2 at $DIR/mutable_variable_unprop_assign.rs:7:5: 7:12 + StorageDead(_3); // scope 2 at $DIR/mutable_variable_unprop_assign.rs:7:11: 7:12 + StorageLive(_4); // scope 2 at $DIR/mutable_variable_unprop_assign.rs:8:9: 8:10 + _4 = (_2.1: i32); // scope 2 at $DIR/mutable_variable_unprop_assign.rs:8:13: 8:16 + StorageLive(_5); // scope 3 at $DIR/mutable_variable_unprop_assign.rs:9:9: 9:10 + _5 = (_2.0: i32); // scope 3 at $DIR/mutable_variable_unprop_assign.rs:9:13: 9:16 + _0 = const (); // scope 0 at $DIR/mutable_variable_unprop_assign.rs:4:11: 10:2 + // ty::Const + // + ty: () + // + val: Value(Scalar()) + // mir::Constant + // + span: $DIR/mutable_variable_unprop_assign.rs:4:11: 10:2 + // + literal: Const { ty: (), val: Value(Scalar()) } + StorageDead(_5); // scope 3 at $DIR/mutable_variable_unprop_assign.rs:10:1: 10:2 + StorageDead(_4); // scope 2 at $DIR/mutable_variable_unprop_assign.rs:10:1: 10:2 + StorageDead(_2); // scope 1 at $DIR/mutable_variable_unprop_assign.rs:10:1: 10:2 + StorageDead(_1); // scope 0 at $DIR/mutable_variable_unprop_assign.rs:10:1: 10:2 + return; // scope 0 at $DIR/mutable_variable_unprop_assign.rs:10:2: 10:2 + } + } + From 3fccdb3ded1aea60b699cc3d11dcd886f70fbb0e Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 1 May 2020 12:10:06 +0200 Subject: [PATCH 134/203] Pointer printing: do not print 0 offset --- src/librustc_middle/mir/interpret/pointer.rs | 28 ++++++++++++------- ...main.SimplifyCfg-elaborate-drops.after.mir | 4 +-- .../rustc.BAR-promoted[0].ConstProp.after.mir | 6 ++-- .../rustc.BAR.PromoteTemps.diff | 6 ++-- .../rustc.FOO-promoted[0].ConstProp.after.mir | 6 ++-- .../rustc.FOO.PromoteTemps.diff | 6 ++-- .../32bit/rustc.main.ConstProp.after.mir | 20 ++++++------- .../64bit/rustc.main.ConstProp.after.mir | 24 ++++++++-------- .../32bit/rustc.main.ConstProp.after.mir | 18 ++++++------ .../64bit/rustc.main.ConstProp.after.mir | 18 ++++++------ .../32bit/rustc.main.ConstProp.after.mir | 12 ++++---- .../64bit/rustc.main.ConstProp.after.mir | 12 ++++---- .../rustc.main.ConstProp.diff | 6 ++-- .../rustc.main.ConstProp.diff | 12 ++++---- ...nst-pointer-values-in-various-types.stderr | 14 +++++----- .../consts/const-eval/ref_to_int_match.stderr | 2 +- src/test/ui/consts/const-eval/ub-enum.stderr | 10 +++---- src/test/ui/consts/const-eval/ub-ref.stderr | 2 +- 18 files changed, 107 insertions(+), 99 deletions(-) diff --git a/src/librustc_middle/mir/interpret/pointer.rs b/src/librustc_middle/mir/interpret/pointer.rs index 0b0600564997..70cc546199b7 100644 --- a/src/librustc_middle/mir/interpret/pointer.rs +++ b/src/librustc_middle/mir/interpret/pointer.rs @@ -89,27 +89,35 @@ pub struct Pointer { static_assert_size!(Pointer, 16); +/// Print the address of a pointer (without the tag) +fn print_ptr_addr(ptr: &Pointer, f: &mut fmt::Formatter<'_>) -> fmt::Result { + // Forward `alternate` flag to `alloc_id` printing. + if f.alternate() { + write!(f, "{:#?}", ptr.alloc_id)?; + } else { + write!(f, "{:?}", ptr.alloc_id)?; + } + // Print offset only if it is non-zero. + if ptr.offset.bytes() > 0 { + write!(f, "+0x{:x}", ptr.offset.bytes())?; + } + Ok(()) +} + // We want the `Debug` output to be readable as it is used by `derive(Debug)` for // all the Miri types. // We have to use `Debug` output for the tag, because `()` does not implement // `Display` so we cannot specialize that. impl fmt::Debug for Pointer { default fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - if f.alternate() { - write!(f, "{:#?}+0x{:x}[{:?}]", self.alloc_id, self.offset.bytes(), self.tag) - } else { - write!(f, "{:?}+0x{:x}[{:?}]", self.alloc_id, self.offset.bytes(), self.tag) - } + print_ptr_addr(self, f)?; + write!(f, "[{:?}]", self.tag) } } // Specialization for no tag impl fmt::Debug for Pointer<()> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - if f.alternate() { - write!(f, "{:#?}+0x{:x}", self.alloc_id, self.offset.bytes()) - } else { - write!(f, "{:?}+0x{:x}", self.alloc_id, self.offset.bytes()) - } + print_ptr_addr(self, f) } } diff --git a/src/test/mir-opt/byte_slice/rustc.main.SimplifyCfg-elaborate-drops.after.mir b/src/test/mir-opt/byte_slice/rustc.main.SimplifyCfg-elaborate-drops.after.mir index b8ecaf787fe7..88cb09ac15a9 100644 --- a/src/test/mir-opt/byte_slice/rustc.main.SimplifyCfg-elaborate-drops.after.mir +++ b/src/test/mir-opt/byte_slice/rustc.main.SimplifyCfg-elaborate-drops.after.mir @@ -16,10 +16,10 @@ fn main() -> () { _1 = const b"foo"; // scope 0 at $DIR/byte_slice.rs:5:13: 5:19 // ty::Const // + ty: &[u8; 3] - // + val: Value(Scalar(alloc0+0x0)) + // + val: Value(Scalar(alloc0)) // mir::Constant // + span: $DIR/byte_slice.rs:5:13: 5:19 - // + literal: Const { ty: &[u8; 3], val: Value(Scalar(alloc0+0x0)) } + // + literal: Const { ty: &[u8; 3], val: Value(Scalar(alloc0)) } StorageLive(_2); // scope 1 at $DIR/byte_slice.rs:6:9: 6:10 _2 = [const 5u8, const 120u8]; // scope 1 at $DIR/byte_slice.rs:6:13: 6:24 // ty::Const diff --git a/src/test/mir-opt/const-promotion-extern-static/rustc.BAR-promoted[0].ConstProp.after.mir b/src/test/mir-opt/const-promotion-extern-static/rustc.BAR-promoted[0].ConstProp.after.mir index d202531c7ab6..509947071b0c 100644 --- a/src/test/mir-opt/const-promotion-extern-static/rustc.BAR-promoted[0].ConstProp.after.mir +++ b/src/test/mir-opt/const-promotion-extern-static/rustc.BAR-promoted[0].ConstProp.after.mir @@ -7,13 +7,13 @@ promoted[0] in BAR: &[&i32; 1] = { let mut _3: &i32; // in scope 0 at $DIR/const-promotion-extern-static.rs:9:33: 9:34 bb0: { - _3 = const {alloc0+0x0: &i32}; // scope 0 at $DIR/const-promotion-extern-static.rs:9:33: 9:34 + _3 = const {alloc0: &i32}; // scope 0 at $DIR/const-promotion-extern-static.rs:9:33: 9:34 // ty::Const // + ty: &i32 - // + val: Value(Scalar(alloc0+0x0)) + // + val: Value(Scalar(alloc0)) // mir::Constant // + span: $DIR/const-promotion-extern-static.rs:9:33: 9:34 - // + literal: Const { ty: &i32, val: Value(Scalar(alloc0+0x0)) } + // + literal: Const { ty: &i32, val: Value(Scalar(alloc0)) } _2 = _3; // scope 0 at $DIR/const-promotion-extern-static.rs:9:32: 9:34 _1 = [move _2]; // scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:35 _0 = &_1; // scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:35 diff --git a/src/test/mir-opt/const-promotion-extern-static/rustc.BAR.PromoteTemps.diff b/src/test/mir-opt/const-promotion-extern-static/rustc.BAR.PromoteTemps.diff index d517207390d8..8eb8d4c667b1 100644 --- a/src/test/mir-opt/const-promotion-extern-static/rustc.BAR.PromoteTemps.diff +++ b/src/test/mir-opt/const-promotion-extern-static/rustc.BAR.PromoteTemps.diff @@ -16,16 +16,16 @@ - StorageLive(_3); // scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:35 - StorageLive(_4); // scope 0 at $DIR/const-promotion-extern-static.rs:9:32: 9:34 - StorageLive(_5); // scope 0 at $DIR/const-promotion-extern-static.rs:9:33: 9:34 -- _5 = const {alloc0+0x0: &i32}; // scope 0 at $DIR/const-promotion-extern-static.rs:9:33: 9:34 +- _5 = const {alloc0: &i32}; // scope 0 at $DIR/const-promotion-extern-static.rs:9:33: 9:34 + _6 = const BAR::promoted[0]; // scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:35 // ty::Const - // + ty: &i32 -- // + val: Value(Scalar(alloc0+0x0)) +- // + val: Value(Scalar(alloc0)) + // + ty: &[&i32; 1] + // + val: Unevaluated(DefId(0:6 ~ const_promotion_extern_static[317d]::BAR[0]), [], Some(promoted[0])) // mir::Constant - // + span: $DIR/const-promotion-extern-static.rs:9:33: 9:34 -- // + literal: Const { ty: &i32, val: Value(Scalar(alloc0+0x0)) } +- // + literal: Const { ty: &i32, val: Value(Scalar(alloc0)) } - _4 = &(*_5); // scope 0 at $DIR/const-promotion-extern-static.rs:9:32: 9:34 - _3 = [move _4]; // scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:35 - _2 = &_3; // scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:35 diff --git a/src/test/mir-opt/const-promotion-extern-static/rustc.FOO-promoted[0].ConstProp.after.mir b/src/test/mir-opt/const-promotion-extern-static/rustc.FOO-promoted[0].ConstProp.after.mir index b49c1aaa8666..d9c6b4f0029a 100644 --- a/src/test/mir-opt/const-promotion-extern-static/rustc.FOO-promoted[0].ConstProp.after.mir +++ b/src/test/mir-opt/const-promotion-extern-static/rustc.FOO-promoted[0].ConstProp.after.mir @@ -9,13 +9,13 @@ promoted[0] in FOO: &[&i32; 1] = { } bb0: { - _3 = const {alloc2+0x0: &i32}; // scope 0 at $DIR/const-promotion-extern-static.rs:13:42: 13:43 + _3 = const {alloc2: &i32}; // scope 0 at $DIR/const-promotion-extern-static.rs:13:42: 13:43 // ty::Const // + ty: &i32 - // + val: Value(Scalar(alloc2+0x0)) + // + val: Value(Scalar(alloc2)) // mir::Constant // + span: $DIR/const-promotion-extern-static.rs:13:42: 13:43 - // + literal: Const { ty: &i32, val: Value(Scalar(alloc2+0x0)) } + // + literal: Const { ty: &i32, val: Value(Scalar(alloc2)) } _2 = _3; // scope 0 at $DIR/const-promotion-extern-static.rs:13:41: 13:43 _1 = [move _2]; // scope 0 at $DIR/const-promotion-extern-static.rs:13:31: 13:46 _0 = &_1; // scope 0 at $DIR/const-promotion-extern-static.rs:13:31: 13:46 diff --git a/src/test/mir-opt/const-promotion-extern-static/rustc.FOO.PromoteTemps.diff b/src/test/mir-opt/const-promotion-extern-static/rustc.FOO.PromoteTemps.diff index 09c08cf449ff..781aa3c5500c 100644 --- a/src/test/mir-opt/const-promotion-extern-static/rustc.FOO.PromoteTemps.diff +++ b/src/test/mir-opt/const-promotion-extern-static/rustc.FOO.PromoteTemps.diff @@ -18,16 +18,16 @@ - StorageLive(_3); // scope 0 at $DIR/const-promotion-extern-static.rs:13:31: 13:46 - StorageLive(_4); // scope 0 at $DIR/const-promotion-extern-static.rs:13:32: 13:45 - StorageLive(_5); // scope 1 at $DIR/const-promotion-extern-static.rs:13:42: 13:43 -- _5 = const {alloc2+0x0: &i32}; // scope 1 at $DIR/const-promotion-extern-static.rs:13:42: 13:43 +- _5 = const {alloc2: &i32}; // scope 1 at $DIR/const-promotion-extern-static.rs:13:42: 13:43 + _6 = const FOO::promoted[0]; // scope 0 at $DIR/const-promotion-extern-static.rs:13:31: 13:46 // ty::Const - // + ty: &i32 -- // + val: Value(Scalar(alloc2+0x0)) +- // + val: Value(Scalar(alloc2)) + // + ty: &[&i32; 1] + // + val: Unevaluated(DefId(0:7 ~ const_promotion_extern_static[317d]::FOO[0]), [], Some(promoted[0])) // mir::Constant - // + span: $DIR/const-promotion-extern-static.rs:13:42: 13:43 -- // + literal: Const { ty: &i32, val: Value(Scalar(alloc2+0x0)) } +- // + literal: Const { ty: &i32, val: Value(Scalar(alloc2)) } - _4 = &(*_5); // scope 1 at $DIR/const-promotion-extern-static.rs:13:41: 13:43 - _3 = [move _4]; // scope 0 at $DIR/const-promotion-extern-static.rs:13:31: 13:46 - _2 = &_3; // scope 0 at $DIR/const-promotion-extern-static.rs:13:31: 13:46 diff --git a/src/test/mir-opt/const_allocation/32bit/rustc.main.ConstProp.after.mir b/src/test/mir-opt/const_allocation/32bit/rustc.main.ConstProp.after.mir index a20dd7bf0fc9..30a383fd162b 100644 --- a/src/test/mir-opt/const_allocation/32bit/rustc.main.ConstProp.after.mir +++ b/src/test/mir-opt/const_allocation/32bit/rustc.main.ConstProp.after.mir @@ -8,13 +8,13 @@ fn main() -> () { bb0: { StorageLive(_1); // scope 0 at $DIR/const_allocation.rs:8:5: 8:8 StorageLive(_2); // scope 0 at $DIR/const_allocation.rs:8:5: 8:8 - _2 = const {alloc0+0x0: &&[(std::option::Option, &[&str])]}; // scope 0 at $DIR/const_allocation.rs:8:5: 8:8 + _2 = const {alloc0: &&[(std::option::Option, &[&str])]}; // scope 0 at $DIR/const_allocation.rs:8:5: 8:8 // ty::Const // + ty: &&[(std::option::Option, &[&str])] - // + val: Value(Scalar(alloc0+0x0)) + // + val: Value(Scalar(alloc0)) // mir::Constant // + span: $DIR/const_allocation.rs:8:5: 8:8 - // + literal: Const { ty: &&[(std::option::Option, &[&str])], val: Value(Scalar(alloc0+0x0)) } + // + literal: Const { ty: &&[(std::option::Option, &[&str])], val: Value(Scalar(alloc0)) } _1 = (*_2); // scope 0 at $DIR/const_allocation.rs:8:5: 8:8 StorageDead(_2); // scope 0 at $DIR/const_allocation.rs:8:8: 8:9 StorageDead(_1); // scope 0 at $DIR/const_allocation.rs:8:8: 8:9 @@ -30,19 +30,19 @@ fn main() -> () { } alloc0 (static: FOO, size: 8, align: 4) { - ╾─a17+0x0─╼ 03 00 00 00 │ ╾──╼.... + ╾─alloc17─╼ 03 00 00 00 │ ╾──╼.... } alloc17 (size: 48, align: 4) { - 0x00 │ 00 00 00 00 __ __ __ __ ╾─a4+0x0──╼ 00 00 00 00 │ ....░░░░╾──╼.... - 0x10 │ 00 00 00 00 __ __ __ __ ╾─a8+0x0──╼ 02 00 00 00 │ ....░░░░╾──╼.... - 0x20 │ 01 00 00 00 2a 00 00 00 ╾─a13+0x0─╼ 03 00 00 00 │ ....*...╾──╼.... + 0x00 │ 00 00 00 00 __ __ __ __ ╾─alloc4──╼ 00 00 00 00 │ ....░░░░╾──╼.... + 0x10 │ 00 00 00 00 __ __ __ __ ╾─alloc8──╼ 02 00 00 00 │ ....░░░░╾──╼.... + 0x20 │ 01 00 00 00 2a 00 00 00 ╾─alloc13─╼ 03 00 00 00 │ ....*...╾──╼.... } alloc4 (size: 0, align: 4) {} alloc8 (size: 16, align: 4) { - ╾─a7+0x0──╼ 03 00 00 00 ╾─a9+0x0──╼ 03 00 00 00 │ ╾──╼....╾──╼.... + ╾─alloc7──╼ 03 00 00 00 ╾─alloc9──╼ 03 00 00 00 │ ╾──╼....╾──╼.... } alloc7 (size: 3, align: 1) { @@ -54,8 +54,8 @@ alloc9 (size: 3, align: 1) { } alloc13 (size: 24, align: 4) { - 0x00 │ ╾─a12+0x0─╼ 03 00 00 00 ╾─a14+0x0─╼ 03 00 00 00 │ ╾──╼....╾──╼.... - 0x10 │ ╾─a15+0x0─╼ 04 00 00 00 │ ╾──╼.... + 0x00 │ ╾─alloc12─╼ 03 00 00 00 ╾─alloc14─╼ 03 00 00 00 │ ╾──╼....╾──╼.... + 0x10 │ ╾─alloc15─╼ 04 00 00 00 │ ╾──╼.... } alloc12 (size: 3, align: 1) { diff --git a/src/test/mir-opt/const_allocation/64bit/rustc.main.ConstProp.after.mir b/src/test/mir-opt/const_allocation/64bit/rustc.main.ConstProp.after.mir index ff89ac9ad936..5fa54ae5a58e 100644 --- a/src/test/mir-opt/const_allocation/64bit/rustc.main.ConstProp.after.mir +++ b/src/test/mir-opt/const_allocation/64bit/rustc.main.ConstProp.after.mir @@ -8,13 +8,13 @@ fn main() -> () { bb0: { StorageLive(_1); // scope 0 at $DIR/const_allocation.rs:8:5: 8:8 StorageLive(_2); // scope 0 at $DIR/const_allocation.rs:8:5: 8:8 - _2 = const {alloc0+0x0: &&[(std::option::Option, &[&str])]}; // scope 0 at $DIR/const_allocation.rs:8:5: 8:8 + _2 = const {alloc0: &&[(std::option::Option, &[&str])]}; // scope 0 at $DIR/const_allocation.rs:8:5: 8:8 // ty::Const // + ty: &&[(std::option::Option, &[&str])] - // + val: Value(Scalar(alloc0+0x0)) + // + val: Value(Scalar(alloc0)) // mir::Constant // + span: $DIR/const_allocation.rs:8:5: 8:8 - // + literal: Const { ty: &&[(std::option::Option, &[&str])], val: Value(Scalar(alloc0+0x0)) } + // + literal: Const { ty: &&[(std::option::Option, &[&str])], val: Value(Scalar(alloc0)) } _1 = (*_2); // scope 0 at $DIR/const_allocation.rs:8:5: 8:8 StorageDead(_2); // scope 0 at $DIR/const_allocation.rs:8:8: 8:9 StorageDead(_1); // scope 0 at $DIR/const_allocation.rs:8:8: 8:9 @@ -30,22 +30,22 @@ fn main() -> () { } alloc0 (static: FOO, size: 16, align: 8) { - ╾─────alloc17+0x0─────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........ + ╾───────alloc17───────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........ } alloc17 (size: 72, align: 8) { - 0x00 │ 00 00 00 00 __ __ __ __ ╾─────alloc4+0x0──────╼ │ ....░░░░╾──────╼ + 0x00 │ 00 00 00 00 __ __ __ __ ╾───────alloc4────────╼ │ ....░░░░╾──────╼ 0x10 │ 00 00 00 00 00 00 00 00 00 00 00 00 __ __ __ __ │ ............░░░░ - 0x20 │ ╾─────alloc8+0x0──────╼ 02 00 00 00 00 00 00 00 │ ╾──────╼........ - 0x30 │ 01 00 00 00 2a 00 00 00 ╾─────alloc13+0x0─────╼ │ ....*...╾──────╼ + 0x20 │ ╾───────alloc8────────╼ 02 00 00 00 00 00 00 00 │ ╾──────╼........ + 0x30 │ 01 00 00 00 2a 00 00 00 ╾───────alloc13───────╼ │ ....*...╾──────╼ 0x40 │ 03 00 00 00 00 00 00 00 │ ........ } alloc4 (size: 0, align: 8) {} alloc8 (size: 32, align: 8) { - 0x00 │ ╾─────alloc7+0x0──────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........ - 0x10 │ ╾─────alloc9+0x0──────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........ + 0x00 │ ╾───────alloc7────────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........ + 0x10 │ ╾───────alloc9────────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........ } alloc7 (size: 3, align: 1) { @@ -57,9 +57,9 @@ alloc9 (size: 3, align: 1) { } alloc13 (size: 48, align: 8) { - 0x00 │ ╾─────alloc12+0x0─────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........ - 0x10 │ ╾─────alloc14+0x0─────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........ - 0x20 │ ╾─────alloc15+0x0─────╼ 04 00 00 00 00 00 00 00 │ ╾──────╼........ + 0x00 │ ╾───────alloc12───────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........ + 0x10 │ ╾───────alloc14───────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........ + 0x20 │ ╾───────alloc15───────╼ 04 00 00 00 00 00 00 00 │ ╾──────╼........ } alloc12 (size: 3, align: 1) { diff --git a/src/test/mir-opt/const_allocation2/32bit/rustc.main.ConstProp.after.mir b/src/test/mir-opt/const_allocation2/32bit/rustc.main.ConstProp.after.mir index e392eaa6aeda..d386d2478292 100644 --- a/src/test/mir-opt/const_allocation2/32bit/rustc.main.ConstProp.after.mir +++ b/src/test/mir-opt/const_allocation2/32bit/rustc.main.ConstProp.after.mir @@ -8,13 +8,13 @@ fn main() -> () { bb0: { StorageLive(_1); // scope 0 at $DIR/const_allocation2.rs:5:5: 5:8 StorageLive(_2); // scope 0 at $DIR/const_allocation2.rs:5:5: 5:8 - _2 = const {alloc0+0x0: &&[(std::option::Option, &[&u8])]}; // scope 0 at $DIR/const_allocation2.rs:5:5: 5:8 + _2 = const {alloc0: &&[(std::option::Option, &[&u8])]}; // scope 0 at $DIR/const_allocation2.rs:5:5: 5:8 // ty::Const // + ty: &&[(std::option::Option, &[&u8])] - // + val: Value(Scalar(alloc0+0x0)) + // + val: Value(Scalar(alloc0)) // mir::Constant // + span: $DIR/const_allocation2.rs:5:5: 5:8 - // + literal: Const { ty: &&[(std::option::Option, &[&u8])], val: Value(Scalar(alloc0+0x0)) } + // + literal: Const { ty: &&[(std::option::Option, &[&u8])], val: Value(Scalar(alloc0)) } _1 = (*_2); // scope 0 at $DIR/const_allocation2.rs:5:5: 5:8 StorageDead(_2); // scope 0 at $DIR/const_allocation2.rs:5:8: 5:9 StorageDead(_1); // scope 0 at $DIR/const_allocation2.rs:5:8: 5:9 @@ -30,19 +30,19 @@ fn main() -> () { } alloc0 (static: FOO, size: 8, align: 4) { - ╾─a21+0x0─╼ 03 00 00 00 │ ╾──╼.... + ╾─alloc21─╼ 03 00 00 00 │ ╾──╼.... } alloc21 (size: 48, align: 4) { - 0x00 │ 00 00 00 00 __ __ __ __ ╾─a4+0x0──╼ 00 00 00 00 │ ....░░░░╾──╼.... - 0x10 │ 00 00 00 00 __ __ __ __ ╾─a9+0x0──╼ 02 00 00 00 │ ....░░░░╾──╼.... - 0x20 │ 01 00 00 00 2a 00 00 00 ╾─a19+0x0─╼ 03 00 00 00 │ ....*...╾──╼.... + 0x00 │ 00 00 00 00 __ __ __ __ ╾─alloc4──╼ 00 00 00 00 │ ....░░░░╾──╼.... + 0x10 │ 00 00 00 00 __ __ __ __ ╾─alloc9──╼ 02 00 00 00 │ ....░░░░╾──╼.... + 0x20 │ 01 00 00 00 2a 00 00 00 ╾─alloc19─╼ 03 00 00 00 │ ....*...╾──╼.... } alloc4 (size: 0, align: 4) {} alloc9 (size: 8, align: 4) { - ╾─a7+0x0──╼ ╾─a8+0x0──╼ │ ╾──╼╾──╼ + ╾─alloc7──╼ ╾─alloc8──╼ │ ╾──╼╾──╼ } alloc7 (size: 1, align: 1) { @@ -54,7 +54,7 @@ alloc8 (size: 1, align: 1) { } alloc19 (size: 12, align: 4) { - ╾─a15+0x3─╼ ╾─a16+0x0─╼ ╾─a18+0x2─╼ │ ╾──╼╾──╼╾──╼ + ╾─a15+0x3─╼ ╾─alloc16─╼ ╾─a18+0x2─╼ │ ╾──╼╾──╼╾──╼ } alloc15 (size: 4, align: 1) { diff --git a/src/test/mir-opt/const_allocation2/64bit/rustc.main.ConstProp.after.mir b/src/test/mir-opt/const_allocation2/64bit/rustc.main.ConstProp.after.mir index 81dc0372b5d1..d7acd0f0f433 100644 --- a/src/test/mir-opt/const_allocation2/64bit/rustc.main.ConstProp.after.mir +++ b/src/test/mir-opt/const_allocation2/64bit/rustc.main.ConstProp.after.mir @@ -8,13 +8,13 @@ fn main() -> () { bb0: { StorageLive(_1); // scope 0 at $DIR/const_allocation2.rs:5:5: 5:8 StorageLive(_2); // scope 0 at $DIR/const_allocation2.rs:5:5: 5:8 - _2 = const {alloc0+0x0: &&[(std::option::Option, &[&u8])]}; // scope 0 at $DIR/const_allocation2.rs:5:5: 5:8 + _2 = const {alloc0: &&[(std::option::Option, &[&u8])]}; // scope 0 at $DIR/const_allocation2.rs:5:5: 5:8 // ty::Const // + ty: &&[(std::option::Option, &[&u8])] - // + val: Value(Scalar(alloc0+0x0)) + // + val: Value(Scalar(alloc0)) // mir::Constant // + span: $DIR/const_allocation2.rs:5:5: 5:8 - // + literal: Const { ty: &&[(std::option::Option, &[&u8])], val: Value(Scalar(alloc0+0x0)) } + // + literal: Const { ty: &&[(std::option::Option, &[&u8])], val: Value(Scalar(alloc0)) } _1 = (*_2); // scope 0 at $DIR/const_allocation2.rs:5:5: 5:8 StorageDead(_2); // scope 0 at $DIR/const_allocation2.rs:5:8: 5:9 StorageDead(_1); // scope 0 at $DIR/const_allocation2.rs:5:8: 5:9 @@ -30,21 +30,21 @@ fn main() -> () { } alloc0 (static: FOO, size: 16, align: 8) { - ╾─────alloc21+0x0─────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........ + ╾───────alloc21───────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........ } alloc21 (size: 72, align: 8) { - 0x00 │ 00 00 00 00 __ __ __ __ ╾─────alloc4+0x0──────╼ │ ....░░░░╾──────╼ + 0x00 │ 00 00 00 00 __ __ __ __ ╾───────alloc4────────╼ │ ....░░░░╾──────╼ 0x10 │ 00 00 00 00 00 00 00 00 00 00 00 00 __ __ __ __ │ ............░░░░ - 0x20 │ ╾─────alloc9+0x0──────╼ 02 00 00 00 00 00 00 00 │ ╾──────╼........ - 0x30 │ 01 00 00 00 2a 00 00 00 ╾─────alloc19+0x0─────╼ │ ....*...╾──────╼ + 0x20 │ ╾───────alloc9────────╼ 02 00 00 00 00 00 00 00 │ ╾──────╼........ + 0x30 │ 01 00 00 00 2a 00 00 00 ╾───────alloc19───────╼ │ ....*...╾──────╼ 0x40 │ 03 00 00 00 00 00 00 00 │ ........ } alloc4 (size: 0, align: 8) {} alloc9 (size: 16, align: 8) { - ╾─────alloc7+0x0──────╼ ╾─────alloc8+0x0──────╼ │ ╾──────╼╾──────╼ + ╾───────alloc7────────╼ ╾───────alloc8────────╼ │ ╾──────╼╾──────╼ } alloc7 (size: 1, align: 1) { @@ -56,7 +56,7 @@ alloc8 (size: 1, align: 1) { } alloc19 (size: 24, align: 8) { - 0x00 │ ╾─────alloc15+0x3─────╼ ╾─────alloc16+0x0─────╼ │ ╾──────╼╾──────╼ + 0x00 │ ╾─────alloc15+0x3─────╼ ╾───────alloc16───────╼ │ ╾──────╼╾──────╼ 0x10 │ ╾─────alloc18+0x2─────╼ │ ╾──────╼ } diff --git a/src/test/mir-opt/const_allocation3/32bit/rustc.main.ConstProp.after.mir b/src/test/mir-opt/const_allocation3/32bit/rustc.main.ConstProp.after.mir index a29327eb9731..39c60ad987a6 100644 --- a/src/test/mir-opt/const_allocation3/32bit/rustc.main.ConstProp.after.mir +++ b/src/test/mir-opt/const_allocation3/32bit/rustc.main.ConstProp.after.mir @@ -8,13 +8,13 @@ fn main() -> () { bb0: { StorageLive(_1); // scope 0 at $DIR/const_allocation3.rs:5:5: 5:8 StorageLive(_2); // scope 0 at $DIR/const_allocation3.rs:5:5: 5:8 - _2 = const {alloc0+0x0: &&Packed}; // scope 0 at $DIR/const_allocation3.rs:5:5: 5:8 + _2 = const {alloc0: &&Packed}; // scope 0 at $DIR/const_allocation3.rs:5:5: 5:8 // ty::Const // + ty: &&Packed - // + val: Value(Scalar(alloc0+0x0)) + // + val: Value(Scalar(alloc0)) // mir::Constant // + span: $DIR/const_allocation3.rs:5:5: 5:8 - // + literal: Const { ty: &&Packed, val: Value(Scalar(alloc0+0x0)) } + // + literal: Const { ty: &&Packed, val: Value(Scalar(alloc0)) } _1 = (*_2); // scope 0 at $DIR/const_allocation3.rs:5:5: 5:8 StorageDead(_2); // scope 0 at $DIR/const_allocation3.rs:5:8: 5:9 StorageDead(_1); // scope 0 at $DIR/const_allocation3.rs:5:8: 5:9 @@ -30,19 +30,19 @@ fn main() -> () { } alloc0 (static: FOO, size: 4, align: 4) { - ╾─a9+0x0──╼ │ ╾──╼ + ╾─alloc9──╼ │ ╾──╼ } alloc9 (size: 168, align: 1) { 0x00 │ ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab │ ................ - 0x10 │ ab ab ab ab ab ab ab ab ab ab ab ab ╾─a4+0x0──╼ │ ............╾──╼ + 0x10 │ ab ab ab ab ab ab ab ab ab ab ab ab ╾─alloc4──╼ │ ............╾──╼ 0x20 │ 01 ef cd ab 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ 0x30 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ 0x40 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ 0x50 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ 0x60 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ 0x70 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ - 0x80 │ 00 00 00 00 00 00 00 00 00 00 ╾─a6+0x0──╼ 00 00 │ ..........╾──╼.. + 0x80 │ 00 00 00 00 00 00 00 00 00 00 ╾─alloc6──╼ 00 00 │ ..........╾──╼.. 0x90 │ ╾─a7+0x63─╼ 00 00 00 00 00 00 00 00 00 00 00 00 │ ╾──╼............ 0xa0 │ 00 00 00 00 00 00 00 00 │ ........ } diff --git a/src/test/mir-opt/const_allocation3/64bit/rustc.main.ConstProp.after.mir b/src/test/mir-opt/const_allocation3/64bit/rustc.main.ConstProp.after.mir index 865c7c934321..96024f1c82ca 100644 --- a/src/test/mir-opt/const_allocation3/64bit/rustc.main.ConstProp.after.mir +++ b/src/test/mir-opt/const_allocation3/64bit/rustc.main.ConstProp.after.mir @@ -8,13 +8,13 @@ fn main() -> () { bb0: { StorageLive(_1); // scope 0 at $DIR/const_allocation3.rs:5:5: 5:8 StorageLive(_2); // scope 0 at $DIR/const_allocation3.rs:5:5: 5:8 - _2 = const {alloc0+0x0: &&Packed}; // scope 0 at $DIR/const_allocation3.rs:5:5: 5:8 + _2 = const {alloc0: &&Packed}; // scope 0 at $DIR/const_allocation3.rs:5:5: 5:8 // ty::Const // + ty: &&Packed - // + val: Value(Scalar(alloc0+0x0)) + // + val: Value(Scalar(alloc0)) // mir::Constant // + span: $DIR/const_allocation3.rs:5:5: 5:8 - // + literal: Const { ty: &&Packed, val: Value(Scalar(alloc0+0x0)) } + // + literal: Const { ty: &&Packed, val: Value(Scalar(alloc0)) } _1 = (*_2); // scope 0 at $DIR/const_allocation3.rs:5:5: 5:8 StorageDead(_2); // scope 0 at $DIR/const_allocation3.rs:5:8: 5:9 StorageDead(_1); // scope 0 at $DIR/const_allocation3.rs:5:8: 5:9 @@ -30,12 +30,12 @@ fn main() -> () { } alloc0 (static: FOO, size: 8, align: 8) { - ╾─────alloc9+0x0──────╼ │ ╾──────╼ + ╾───────alloc9────────╼ │ ╾──────╼ } alloc9 (size: 180, align: 1) { 0x00 │ ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab │ ................ - 0x10 │ ab ab ab ab ab ab ab ab ab ab ab ab ╾alloc4+0x0 │ ............╾─── + 0x10 │ ab ab ab ab ab ab ab ab ab ab ab ab ╾──alloc4── │ ............╾─── 0x20 │ ──────────╼ 01 ef cd ab 00 00 00 00 00 00 00 00 │ ───╼............ 0x30 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ 0x40 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ @@ -43,7 +43,7 @@ alloc9 (size: 180, align: 1) { 0x60 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ 0x70 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ 0x80 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ╾──── │ ..............╾─ - 0x90 │ ───alloc6+0x0───╼ 00 00 ╾─────alloc7+0x63─────╼ │ ─────╼..╾──────╼ + 0x90 │ ─────alloc6─────╼ 00 00 ╾─────alloc7+0x63─────╼ │ ─────╼..╾──────╼ 0xa0 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ 0xb0 │ 00 00 00 00 │ .... } diff --git a/src/test/mir-opt/const_prop/mutable_variable_no_prop/rustc.main.ConstProp.diff b/src/test/mir-opt/const_prop/mutable_variable_no_prop/rustc.main.ConstProp.diff index 1e9cbe6024c9..b7f1242d8d12 100644 --- a/src/test/mir-opt/const_prop/mutable_variable_no_prop/rustc.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/mutable_variable_no_prop/rustc.main.ConstProp.diff @@ -29,13 +29,13 @@ StorageLive(_2); // scope 1 at $DIR/mutable_variable_no_prop.rs:8:5: 10:6 StorageLive(_3); // scope 2 at $DIR/mutable_variable_no_prop.rs:9:13: 9:19 StorageLive(_4); // scope 2 at $DIR/mutable_variable_no_prop.rs:9:13: 9:19 - _4 = const {alloc0+0x0: *mut u32}; // scope 2 at $DIR/mutable_variable_no_prop.rs:9:13: 9:19 + _4 = const {alloc0: *mut u32}; // scope 2 at $DIR/mutable_variable_no_prop.rs:9:13: 9:19 // ty::Const // + ty: *mut u32 - // + val: Value(Scalar(alloc0+0x0)) + // + val: Value(Scalar(alloc0)) // mir::Constant // + span: $DIR/mutable_variable_no_prop.rs:9:13: 9:19 - // + literal: Const { ty: *mut u32, val: Value(Scalar(alloc0+0x0)) } + // + literal: Const { ty: *mut u32, val: Value(Scalar(alloc0)) } _3 = (*_4); // scope 2 at $DIR/mutable_variable_no_prop.rs:9:13: 9:19 _1 = move _3; // scope 2 at $DIR/mutable_variable_no_prop.rs:9:9: 9:19 StorageDead(_3); // scope 2 at $DIR/mutable_variable_no_prop.rs:9:18: 9:19 diff --git a/src/test/mir-opt/const_prop/read_immutable_static/rustc.main.ConstProp.diff b/src/test/mir-opt/const_prop/read_immutable_static/rustc.main.ConstProp.diff index bbe0d1060114..103444f796ec 100644 --- a/src/test/mir-opt/const_prop/read_immutable_static/rustc.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/read_immutable_static/rustc.main.ConstProp.diff @@ -16,13 +16,13 @@ StorageLive(_1); // scope 0 at $DIR/read_immutable_static.rs:7:9: 7:10 StorageLive(_2); // scope 0 at $DIR/read_immutable_static.rs:7:13: 7:16 StorageLive(_3); // scope 0 at $DIR/read_immutable_static.rs:7:13: 7:16 - _3 = const {alloc0+0x0: &u8}; // scope 0 at $DIR/read_immutable_static.rs:7:13: 7:16 + _3 = const {alloc0: &u8}; // scope 0 at $DIR/read_immutable_static.rs:7:13: 7:16 // ty::Const // + ty: &u8 - // + val: Value(Scalar(alloc0+0x0)) + // + val: Value(Scalar(alloc0)) // mir::Constant // + span: $DIR/read_immutable_static.rs:7:13: 7:16 - // + literal: Const { ty: &u8, val: Value(Scalar(alloc0+0x0)) } + // + literal: Const { ty: &u8, val: Value(Scalar(alloc0)) } - _2 = (*_3); // scope 0 at $DIR/read_immutable_static.rs:7:13: 7:16 + _2 = const 2u8; // scope 0 at $DIR/read_immutable_static.rs:7:13: 7:16 + // ty::Const @@ -33,13 +33,13 @@ + // + literal: Const { ty: u8, val: Value(Scalar(0x02)) } StorageLive(_4); // scope 0 at $DIR/read_immutable_static.rs:7:19: 7:22 StorageLive(_5); // scope 0 at $DIR/read_immutable_static.rs:7:19: 7:22 - _5 = const {alloc0+0x0: &u8}; // scope 0 at $DIR/read_immutable_static.rs:7:19: 7:22 + _5 = const {alloc0: &u8}; // scope 0 at $DIR/read_immutable_static.rs:7:19: 7:22 // ty::Const // + ty: &u8 - // + val: Value(Scalar(alloc0+0x0)) + // + val: Value(Scalar(alloc0)) // mir::Constant // + span: $DIR/read_immutable_static.rs:7:19: 7:22 - // + literal: Const { ty: &u8, val: Value(Scalar(alloc0+0x0)) } + // + literal: Const { ty: &u8, val: Value(Scalar(alloc0)) } - _4 = (*_5); // scope 0 at $DIR/read_immutable_static.rs:7:19: 7:22 - _1 = Add(move _2, move _4); // scope 0 at $DIR/read_immutable_static.rs:7:13: 7:22 + _4 = const 2u8; // scope 0 at $DIR/read_immutable_static.rs:7:19: 7:22 diff --git a/src/test/ui/consts/const-eval/const-pointer-values-in-various-types.stderr b/src/test/ui/consts/const-eval/const-pointer-values-in-various-types.stderr index 649105812b07..d24491e1bc5c 100644 --- a/src/test/ui/consts/const-eval/const-pointer-values-in-various-types.stderr +++ b/src/test/ui/consts/const-eval/const-pointer-values-in-various-types.stderr @@ -2,7 +2,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/const-pointer-values-in-various-types.rs:25:5 | LL | const I32_REF_USIZE_UNION: usize = unsafe { Nonsense { int_32_ref: &3 }.u }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered pointer to alloc2+0x0, but expected initialized plain (non-pointer) bytes + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered pointer to alloc2, but expected initialized plain (non-pointer) bytes | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. @@ -36,7 +36,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/const-pointer-values-in-various-types.rs:37:5 | LL | const I32_REF_U64_UNION: u64 = unsafe { Nonsense { int_32_ref: &3 }.uint_64 }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered pointer to alloc22+0x0, but expected initialized plain (non-pointer) bytes + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered pointer to alloc22, but expected initialized plain (non-pointer) bytes | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. @@ -76,7 +76,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/const-pointer-values-in-various-types.rs:52:5 | LL | const I32_REF_I64_UNION: i64 = unsafe { Nonsense { int_32_ref: &3 }.int_64 }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered pointer to alloc47+0x0, but expected initialized plain (non-pointer) bytes + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered pointer to alloc47, but expected initialized plain (non-pointer) bytes | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. @@ -100,7 +100,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/const-pointer-values-in-various-types.rs:61:5 | LL | const I32_REF_F64_UNION: f64 = unsafe { Nonsense { int_32_ref: &3 }.float_64 }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered pointer to alloc62+0x0, but expected initialized plain (non-pointer) bytes + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered pointer to alloc62, but expected initialized plain (non-pointer) bytes | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. @@ -148,7 +148,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/const-pointer-values-in-various-types.rs:79:5 | LL | const STR_U64_UNION: u64 = unsafe { Nonsense { stringy: "3" }.uint_64 }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered pointer to alloc86+0x0, but expected initialized plain (non-pointer) bytes + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered pointer to alloc86, but expected initialized plain (non-pointer) bytes | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. @@ -188,7 +188,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/const-pointer-values-in-various-types.rs:94:5 | LL | const STR_I64_UNION: i64 = unsafe { Nonsense { stringy: "3" }.int_64 }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered pointer to alloc101+0x0, but expected initialized plain (non-pointer) bytes + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered pointer to alloc101, but expected initialized plain (non-pointer) bytes | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. @@ -212,7 +212,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/const-pointer-values-in-various-types.rs:103:5 | LL | const STR_F64_UNION: f64 = unsafe { Nonsense { stringy: "3" }.float_64 }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered pointer to alloc110+0x0, but expected initialized plain (non-pointer) bytes + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered pointer to alloc110, but expected initialized plain (non-pointer) bytes | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. diff --git a/src/test/ui/consts/const-eval/ref_to_int_match.stderr b/src/test/ui/consts/const-eval/ref_to_int_match.stderr index df6fc66620b3..cb0ba5d9929b 100644 --- a/src/test/ui/consts/const-eval/ref_to_int_match.stderr +++ b/src/test/ui/consts/const-eval/ref_to_int_match.stderr @@ -2,7 +2,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ref_to_int_match.rs:25:1 | LL | const BAR: Int = unsafe { Foo { r: &42 }.f }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered pointer to alloc2+0x0, but expected initialized plain (non-pointer) bytes + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered pointer to alloc2, but expected initialized plain (non-pointer) bytes | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. diff --git a/src/test/ui/consts/const-eval/ub-enum.stderr b/src/test/ui/consts/const-eval/ub-enum.stderr index 8f0ce58eaf5d..d8dafac3e70a 100644 --- a/src/test/ui/consts/const-eval/ub-enum.stderr +++ b/src/test/ui/consts/const-eval/ub-enum.stderr @@ -10,7 +10,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-enum.rs:27:1 | LL | const BAD_ENUM_PTR: Enum = unsafe { mem::transmute(&1) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered pointer to alloc8+0x0 at ., but expected initialized plain (non-pointer) bytes + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered pointer to alloc8 at ., but expected initialized plain (non-pointer) bytes | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. @@ -18,7 +18,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-enum.rs:30:1 | LL | const BAD_ENUM_WRAPPED: Wrap = unsafe { mem::transmute(&1) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered pointer to alloc13+0x0 at .0., but expected initialized plain (non-pointer) bytes + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered pointer to alloc13 at .0., but expected initialized plain (non-pointer) bytes | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. @@ -34,7 +34,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-enum.rs:44:1 | LL | const BAD_ENUM2_PTR: Enum2 = unsafe { mem::transmute(&0) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered pointer to alloc20+0x0 at ., but expected initialized plain (non-pointer) bytes + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered pointer to alloc20 at ., but expected initialized plain (non-pointer) bytes | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. @@ -42,7 +42,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-enum.rs:47:1 | LL | const BAD_ENUM2_WRAPPED: Wrap = unsafe { mem::transmute(&0) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered pointer to alloc25+0x0 at .0., but expected initialized plain (non-pointer) bytes + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered pointer to alloc25 at .0., but expected initialized plain (non-pointer) bytes | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. @@ -58,7 +58,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-enum.rs:60:1 | LL | const BAD_ENUM2_OPTION_PTR: Option = unsafe { mem::transmute(&0) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered pointer to alloc32+0x0 at ., but expected initialized plain (non-pointer) bytes + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered pointer to alloc32 at ., but expected initialized plain (non-pointer) bytes | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. diff --git a/src/test/ui/consts/const-eval/ub-ref.stderr b/src/test/ui/consts/const-eval/ub-ref.stderr index 95a83d11acd0..a219679f1826 100644 --- a/src/test/ui/consts/const-eval/ub-ref.stderr +++ b/src/test/ui/consts/const-eval/ub-ref.stderr @@ -34,7 +34,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-ref.rs:24:1 | LL | const REF_AS_USIZE: usize = unsafe { mem::transmute(&0) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered pointer to alloc16+0x0, but expected initialized plain (non-pointer) bytes + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered pointer to alloc16, but expected initialized plain (non-pointer) bytes | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. From 61fbe57f4afd8f5b1a348b644d00c912d4b2e9fb Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 12 May 2020 13:36:57 +0200 Subject: [PATCH 135/203] Clean up E0581 explanation --- src/librustc_error_codes/error_codes/E0581.md | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/librustc_error_codes/error_codes/E0581.md b/src/librustc_error_codes/error_codes/E0581.md index 947ec255a9db..89f6e3269ec3 100644 --- a/src/librustc_error_codes/error_codes/E0581.md +++ b/src/librustc_error_codes/error_codes/E0581.md @@ -1,4 +1,4 @@ -In a `fn` type, a lifetime appears only in the return type, +In a `fn` type, a lifetime appears only in the return type and not in the arguments types. Erroneous code example: @@ -10,8 +10,11 @@ fn main() { } ``` -To fix this issue, either use the lifetime in the arguments, or use -`'static`. Example: +The problem here is that the lifetime isn't contrained by any of the arguments, +making it impossible to determine how long it's supposed to live. + +To fix this issue, either use the lifetime in the arguments, or use the +`'static` lifetime. Example: ``` fn main() { From 5063297c798c98f785047d4e18a3b9fd1a5331d8 Mon Sep 17 00:00:00 2001 From: Wesley Wiser Date: Tue, 12 May 2020 08:11:58 -0400 Subject: [PATCH 136/203] Add doc comment for `rustc_middle::mir::mono::Linkage` --- src/librustc_middle/mir/mono.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/librustc_middle/mir/mono.rs b/src/librustc_middle/mir/mono.rs index 632607e33562..c889dbc0a449 100644 --- a/src/librustc_middle/mir/mono.rs +++ b/src/librustc_middle/mir/mono.rs @@ -239,6 +239,9 @@ pub struct CodegenUnit<'tcx> { size_estimate: Option, } +/// Specifies the linkage type for a `MonoItem`. +/// +/// See https://llvm.org/docs/LangRef.html#linkage-types for more details about these variants. #[derive(Copy, Clone, PartialEq, Debug, RustcEncodable, RustcDecodable, HashStable)] pub enum Linkage { External, From 34b2072599c2d14a36ed8cb7adeb0db44b8f76b3 Mon Sep 17 00:00:00 2001 From: Joshua Cotton Date: Wed, 6 May 2020 20:24:40 -0400 Subject: [PATCH 137/203] Fix bootstrap failing on win32 --- src/bootstrap/bootstrap.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index 9a91f37c5deb..b7d0fac5be31 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -180,13 +180,16 @@ def format_build_time(duration): def default_build_triple(): """Build triple as in LLVM""" default_encoding = sys.getdefaultencoding() - required = not sys.platform == 'win32' - ostype = require(["uname", "-s"], exit=required).decode(default_encoding) - cputype = require(['uname', '-m'], exit=required).decode(default_encoding) + required = sys.platform != 'win32' + ostype = require(["uname", "-s"], exit=required) + cputype = require(['uname', '-m'], exit=required) if ostype is None or cputype is None: return 'x86_64-pc-windows-msvc' + ostype = ostype.decode(default_encoding) + cputype = cputype.decode(default_encoding) + # The goal here is to come up with the same triple as LLVM would, # at least for the subset of platforms we're willing to target. ostype_mapper = { From 2d39f5abcd3953eb1578f718c75c39c457bcb009 Mon Sep 17 00:00:00 2001 From: Kornel Date: Tue, 12 May 2020 16:38:02 +0100 Subject: [PATCH 138/203] Warn against thread::sleep in async fn --- src/libstd/thread/mod.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/libstd/thread/mod.rs b/src/libstd/thread/mod.rs index 738f07250b5b..3134a5967566 100644 --- a/src/libstd/thread/mod.rs +++ b/src/libstd/thread/mod.rs @@ -737,6 +737,8 @@ pub fn panicking() -> bool { /// The thread may sleep longer than the duration specified due to scheduling /// specifics or platform-dependent functionality. It will never sleep less. /// +/// This function is blocking, and should not be used in `async` functions. +/// /// # Platform-specific behavior /// /// On Unix platforms, the underlying syscall may be interrupted by a @@ -763,6 +765,8 @@ pub fn sleep_ms(ms: u32) { /// The thread may sleep longer than the duration specified due to scheduling /// specifics or platform-dependent functionality. It will never sleep less. /// +/// This function is blocking, and should not be used in `async` functions. +/// /// # Platform-specific behavior /// /// On Unix platforms, the underlying syscall may be interrupted by a From 003ed802c4a289d959d4212ad80f33df7f3e2bc3 Mon Sep 17 00:00:00 2001 From: Laurence Tratt Date: Tue, 12 May 2020 16:54:29 +0100 Subject: [PATCH 139/203] Map to -> return. --- src/libcore/any.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcore/any.rs b/src/libcore/any.rs index 996a9cdfc4d9..79b6304958d5 100644 --- a/src/libcore/any.rs +++ b/src/libcore/any.rs @@ -448,7 +448,7 @@ impl TypeId { /// This is intended for diagnostic use. The exact contents and format of the /// string returned are not specified, other than being a best-effort /// description of the type. For example, amongst the strings -/// that `type_name::>()` might map to are `"Option"` and +/// that `type_name::>()` might return are `"Option"` and /// `"std::option::Option"`. /// /// The returned string must not be considered to be a unique identifier of a From 6c415450fd2e33ec7056805b97475d7ea73eb04c Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Tue, 12 May 2020 13:00:10 -0400 Subject: [PATCH 140/203] Provide separate option for std debug asserts --- config.toml.example | 4 ++++ src/bootstrap/builder.rs | 9 ++++++++- src/bootstrap/config.rs | 6 ++++++ 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/config.toml.example b/config.toml.example index e32beb1c6119..f76ccac8953f 100644 --- a/config.toml.example +++ b/config.toml.example @@ -314,6 +314,10 @@ # library. #debug-assertions = false +# Whether or not debug assertions are enabled for the standard library. +# Overrides the `debug-assertions` option, if defined. +#debug-assertions-std = false + # Debuginfo level for most of Rust code, corresponds to the `-C debuginfo=N` option of `rustc`. # `0` - no debug info # `1` - line tables only diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index b0e06731330a..731382e4f75b 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -916,7 +916,14 @@ impl<'a> Builder<'a> { .env("RUSTC", self.out.join("bootstrap/debug/rustc")) .env("RUSTC_REAL", self.rustc(compiler)) .env("RUSTC_STAGE", stage.to_string()) - .env("RUSTC_DEBUG_ASSERTIONS", self.config.rust_debug_assertions.to_string()) + .env( + "RUSTC_DEBUG_ASSERTIONS", + if mode == Mode::Std { + self.config.rust_debug_assertions_std.to_string() + } else { + self.config.rust_debug_assertions.to_string() + }, + ) .env("RUSTC_SYSROOT", &sysroot) .env("RUSTC_LIBDIR", &libdir) .env("RUSTDOC", self.out.join("bootstrap/debug/rustdoc")) diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index 390630ee51b8..ef822dd3e5f6 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -98,6 +98,7 @@ pub struct Config { pub rust_codegen_units: Option, pub rust_codegen_units_std: Option, pub rust_debug_assertions: bool, + pub rust_debug_assertions_std: bool, pub rust_debuginfo_level_rustc: u32, pub rust_debuginfo_level_std: u32, pub rust_debuginfo_level_tools: u32, @@ -315,6 +316,7 @@ struct Rust { codegen_units: Option, codegen_units_std: Option, debug_assertions: Option, + debug_assertions_std: Option, debuginfo_level: Option, debuginfo_level_rustc: Option, debuginfo_level_std: Option, @@ -520,6 +522,7 @@ impl Config { let mut llvm_assertions = None; let mut debug = None; let mut debug_assertions = None; + let mut debug_assertions_std = None; let mut debuginfo_level = None; let mut debuginfo_level_rustc = None; let mut debuginfo_level_std = None; @@ -562,6 +565,7 @@ impl Config { if let Some(ref rust) = toml.rust { debug = rust.debug; debug_assertions = rust.debug_assertions; + debug_assertions_std = rust.debug_assertions_std; debuginfo_level = rust.debuginfo_level; debuginfo_level_rustc = rust.debuginfo_level_rustc; debuginfo_level_std = rust.debuginfo_level_std; @@ -661,6 +665,8 @@ impl Config { let default = debug == Some(true); config.rust_debug_assertions = debug_assertions.unwrap_or(default); + config.rust_debug_assertions_std = + debug_assertions_std.unwrap_or(config.rust_debug_assertions); let with_defaults = |debuginfo_level_specific: Option| { debuginfo_level_specific.or(debuginfo_level).unwrap_or(if debug == Some(true) { From 545320a22ff61c30e932200c07466ba3f2be76aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Wed, 22 Apr 2020 16:03:39 -0700 Subject: [PATCH 141/203] Suggest adding super trait constraints --- .../traits/error_reporting/suggestions.rs | 45 +++++++++++++++++-- .../defaults-unsound-62211-1.stderr | 16 +++++-- .../defaults-unsound-62211-2.stderr | 16 +++++-- .../ui/associated-types/issue-63593.stderr | 4 +- ...ait-with-supertraits-needing-sized-self.rs | 11 +++++ ...with-supertraits-needing-sized-self.stderr | 17 +++++++ 6 files changed, 96 insertions(+), 13 deletions(-) create mode 100644 src/test/ui/associated-types/trait-with-supertraits-needing-sized-self.rs create mode 100644 src/test/ui/associated-types/trait-with-supertraits-needing-sized-self.stderr diff --git a/src/librustc_trait_selection/traits/error_reporting/suggestions.rs b/src/librustc_trait_selection/traits/error_reporting/suggestions.rs index e0b99333fd10..5abae7ed68b9 100644 --- a/src/librustc_trait_selection/traits/error_reporting/suggestions.rs +++ b/src/librustc_trait_selection/traits/error_reporting/suggestions.rs @@ -15,7 +15,7 @@ use rustc_middle::ty::{ self, suggest_constraining_type_param, AdtKind, DefIdTree, Infer, InferTy, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness, }; -use rustc_span::symbol::{kw, sym, Symbol}; +use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::{MultiSpan, Span, DUMMY_SP}; use std::fmt; @@ -173,6 +173,7 @@ fn suggest_restriction( fn_sig: Option<&hir::FnSig<'_>>, projection: Option<&ty::ProjectionTy<'_>>, trait_ref: ty::PolyTraitRef<'_>, + super_traits: Option<(&Ident, &hir::GenericBounds<'_>)>, ) { let span = generics.where_clause.span_for_predicates_or_empty_place(); if span.from_expansion() || span.desugaring_kind().is_some() { @@ -262,8 +263,22 @@ fn suggest_restriction( ); } else { // Trivial case: `T` needs an extra bound: `T: Bound`. - let (sp, sugg) = - predicate_constraint(generics, trait_ref.without_const().to_predicate().to_string()); + let (sp, sugg) = match super_traits { + None => { + predicate_constraint(generics, trait_ref.without_const().to_predicate().to_string()) + } + Some((ident, bounds)) => match bounds { + [.., bound] => ( + bound.span().shrink_to_hi(), + format!(" + {}", trait_ref.print_only_trait_path().to_string()), + ), + [] => ( + ident.span.shrink_to_hi(), + format!(": {}", trait_ref.print_only_trait_path().to_string()), + ), + }, + }; + let appl = Applicability::MachineApplicable; err.span_suggestion(sp, &format!("consider further restricting {}", msg), sugg, appl); } @@ -288,13 +303,33 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { let mut hir_id = body_id; while let Some(node) = self.tcx.hir().find(hir_id) { match node { + hir::Node::Item(hir::Item { + ident, + kind: hir::ItemKind::Trait(_, _, generics, bounds, _), + .. + }) if param_ty && self_ty == self.tcx.types.self_param => { + // Restricting `Self` for a single method. + suggest_restriction( + &generics, + "`Self`", + err, + None, + projection, + trait_ref, + Some((ident, bounds)), + ); + return; + } + hir::Node::TraitItem(hir::TraitItem { generics, kind: hir::TraitItemKind::Fn(..), .. }) if param_ty && self_ty == self.tcx.types.self_param => { // Restricting `Self` for a single method. - suggest_restriction(&generics, "`Self`", err, None, projection, trait_ref); + suggest_restriction( + &generics, "`Self`", err, None, projection, trait_ref, None, + ); return; } @@ -319,6 +354,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { Some(fn_sig), projection, trait_ref, + None, ); return; } @@ -336,6 +372,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { None, projection, trait_ref, + None, ); return; } diff --git a/src/test/ui/associated-types/defaults-unsound-62211-1.stderr b/src/test/ui/associated-types/defaults-unsound-62211-1.stderr index 856d513d60bd..c804bc3d833f 100644 --- a/src/test/ui/associated-types/defaults-unsound-62211-1.stderr +++ b/src/test/ui/associated-types/defaults-unsound-62211-1.stderr @@ -2,7 +2,9 @@ error[E0277]: the trait bound `Self: std::marker::Copy` is not satisfied --> $DIR/defaults-unsound-62211-1.rs:21:18 | LL | trait UncheckedCopy: Sized { - | -------------------------- required by `UncheckedCopy` + | --------------------------- help: consider further restricting `Self`: `+ std::marker::Copy` + | | + | required by `UncheckedCopy` ... LL | type Output: Copy | ^^^^ the trait `std::marker::Copy` is not implemented for `Self` @@ -11,7 +13,9 @@ error[E0277]: cannot add-assign `&'static str` to `Self` --> $DIR/defaults-unsound-62211-1.rs:25:7 | LL | trait UncheckedCopy: Sized { - | -------------------------- required by `UncheckedCopy` + | --------------------------- help: consider further restricting `Self`: `+ std::ops::AddAssign<&'static str>` + | | + | required by `UncheckedCopy` ... LL | + AddAssign<&'static str> | ^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `Self += &'static str` @@ -22,7 +26,9 @@ error[E0277]: the trait bound `Self: std::ops::Deref` is not satisfied --> $DIR/defaults-unsound-62211-1.rs:23:7 | LL | trait UncheckedCopy: Sized { - | -------------------------- required by `UncheckedCopy` + | --------------------------- help: consider further restricting `Self`: `+ std::ops::Deref` + | | + | required by `UncheckedCopy` ... LL | + Deref | ^^^^^^^^^^^^^^^^^^^ the trait `std::ops::Deref` is not implemented for `Self` @@ -31,7 +37,9 @@ error[E0277]: `Self` doesn't implement `std::fmt::Display` --> $DIR/defaults-unsound-62211-1.rs:28:7 | LL | trait UncheckedCopy: Sized { - | -------------------------- required by `UncheckedCopy` + | --------------------------- help: consider further restricting `Self`: `+ std::fmt::Display` + | | + | required by `UncheckedCopy` ... LL | + Display = Self; | ^^^^^^^ `Self` cannot be formatted with the default formatter diff --git a/src/test/ui/associated-types/defaults-unsound-62211-2.stderr b/src/test/ui/associated-types/defaults-unsound-62211-2.stderr index 1060c82fec22..aee5e4b28ca6 100644 --- a/src/test/ui/associated-types/defaults-unsound-62211-2.stderr +++ b/src/test/ui/associated-types/defaults-unsound-62211-2.stderr @@ -2,7 +2,9 @@ error[E0277]: the trait bound `Self: std::marker::Copy` is not satisfied --> $DIR/defaults-unsound-62211-2.rs:21:18 | LL | trait UncheckedCopy: Sized { - | -------------------------- required by `UncheckedCopy` + | --------------------------- help: consider further restricting `Self`: `+ std::marker::Copy` + | | + | required by `UncheckedCopy` ... LL | type Output: Copy | ^^^^ the trait `std::marker::Copy` is not implemented for `Self` @@ -11,7 +13,9 @@ error[E0277]: cannot add-assign `&'static str` to `Self` --> $DIR/defaults-unsound-62211-2.rs:25:7 | LL | trait UncheckedCopy: Sized { - | -------------------------- required by `UncheckedCopy` + | --------------------------- help: consider further restricting `Self`: `+ std::ops::AddAssign<&'static str>` + | | + | required by `UncheckedCopy` ... LL | + AddAssign<&'static str> | ^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `Self += &'static str` @@ -22,7 +26,9 @@ error[E0277]: the trait bound `Self: std::ops::Deref` is not satisfied --> $DIR/defaults-unsound-62211-2.rs:23:7 | LL | trait UncheckedCopy: Sized { - | -------------------------- required by `UncheckedCopy` + | --------------------------- help: consider further restricting `Self`: `+ std::ops::Deref` + | | + | required by `UncheckedCopy` ... LL | + Deref | ^^^^^^^^^^^^^^^^^^^ the trait `std::ops::Deref` is not implemented for `Self` @@ -31,7 +37,9 @@ error[E0277]: `Self` doesn't implement `std::fmt::Display` --> $DIR/defaults-unsound-62211-2.rs:28:7 | LL | trait UncheckedCopy: Sized { - | -------------------------- required by `UncheckedCopy` + | --------------------------- help: consider further restricting `Self`: `+ std::fmt::Display` + | | + | required by `UncheckedCopy` ... LL | + Display = Self; | ^^^^^^^ `Self` cannot be formatted with the default formatter diff --git a/src/test/ui/associated-types/issue-63593.stderr b/src/test/ui/associated-types/issue-63593.stderr index c27800f5a3fb..42529fd2b220 100644 --- a/src/test/ui/associated-types/issue-63593.stderr +++ b/src/test/ui/associated-types/issue-63593.stderr @@ -2,7 +2,9 @@ error[E0277]: the size for values of type `Self` cannot be known at compilation --> $DIR/issue-63593.rs:9:5 | LL | trait MyTrait { - | ------------- required by `MyTrait` + | -------------- help: consider further restricting `Self`: `: std::marker::Sized` + | | + | required by `MyTrait` LL | type This = Self; | ^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | diff --git a/src/test/ui/associated-types/trait-with-supertraits-needing-sized-self.rs b/src/test/ui/associated-types/trait-with-supertraits-needing-sized-self.rs new file mode 100644 index 000000000000..0474bf0a3394 --- /dev/null +++ b/src/test/ui/associated-types/trait-with-supertraits-needing-sized-self.rs @@ -0,0 +1,11 @@ +use std::ops::{Add, Sub, Mul, Div}; + +trait ArithmeticOps: Add + Sub + Mul + Div {} +//~^ ERROR the size for values of type `Self` cannot be known at compilation time + +impl ArithmeticOps for T where T: Add + Sub + Mul + Div { + // Nothing to implement, since T already supports the other traits. + // It has the functions it needs already +} + +fn main() {} diff --git a/src/test/ui/associated-types/trait-with-supertraits-needing-sized-self.stderr b/src/test/ui/associated-types/trait-with-supertraits-needing-sized-self.stderr new file mode 100644 index 000000000000..707bcf5e2feb --- /dev/null +++ b/src/test/ui/associated-types/trait-with-supertraits-needing-sized-self.stderr @@ -0,0 +1,17 @@ +error[E0277]: the size for values of type `Self` cannot be known at compilation time + --> $DIR/trait-with-supertraits-needing-sized-self.rs:3:22 + | +LL | trait ArithmeticOps: Add + Sub + Mul + Div {} + | ^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time - help: consider further restricting `Self`: `+ std::marker::Sized` + | + ::: $SRC_DIR/libcore/ops/arith.rs:LL:COL + | +LL | pub trait Add { + | --- required by this bound in `std::ops::Add` + | + = help: the trait `std::marker::Sized` is not implemented for `Self` + = note: to learn more, visit + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. From 45738e8cd1b026836f6cf161843971459bc1334e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Wed, 22 Apr 2020 16:31:58 -0700 Subject: [PATCH 142/203] Increase verbosity of bound restriction suggestions - Make the bound restriction suggestion `span_suggestion_verbose`. - Fix whitespace typo. --- .../traits/error_reporting/suggestions.rs | 12 ++++--- .../bad-bounds-on-assoc-in-trait.stderr | 24 ++++++++----- .../associated-types-bound-failure.fixed | 2 +- .../associated-types-bound-failure.stderr | 8 +++-- .../associated-types-for-unimpl-trait.fixed | 2 +- .../associated-types-for-unimpl-trait.stderr | 10 +++--- ...ated-types-no-suitable-supertrait-2.stderr | 10 +++--- ...ciated-types-no-suitable-supertrait.stderr | 10 +++--- ...ated-trait-in-method-without-default.fixed | 2 +- ...ted-trait-in-method-without-default.stderr | 10 +++--- .../associated-types-unsized.fixed | 2 +- .../associated-types-unsized.stderr | 6 ++-- .../defaults-suitability.stderr | 16 +++++---- .../defaults-unsound-62211-1.stderr | 34 ++++++++++++------- .../defaults-unsound-62211-2.stderr | 34 ++++++++++++------- .../ui/associated-types/issue-63593.stderr | 8 +++-- ...with-supertraits-needing-sized-self.stderr | 6 +++- src/test/ui/issues/issue-22872.stderr | 6 ++-- src/test/ui/issues/issue-27078.stderr | 8 +++-- src/test/ui/issues/issue-42312.stderr | 8 +++-- .../impl-trait-with-missing-bounds.stderr | 10 +++--- ...issing-assoc-type-bound-restriction.stderr | 24 ++++++++----- .../type-params-in-different-spaces-2.stderr | 14 +++++--- ...typeck-default-trait-impl-assoc-type.fixed | 2 +- ...ypeck-default-trait-impl-assoc-type.stderr | 6 ++-- .../wf/wf-trait-associated-type-trait.stderr | 10 +++--- src/test/ui/wf/wf-trait-default-fn-arg.stderr | 9 +++-- src/test/ui/wf/wf-trait-default-fn-ret.stderr | 9 +++-- .../wf-trait-default-fn-where-clause.stderr | 9 +++-- src/test/ui/wf/wf-trait-fn-arg.stderr | 9 +++-- src/test/ui/wf/wf-trait-fn-ret.stderr | 9 +++-- .../ui/wf/wf-trait-fn-where-clause.stderr | 9 +++-- 32 files changed, 215 insertions(+), 123 deletions(-) diff --git a/src/librustc_trait_selection/traits/error_reporting/suggestions.rs b/src/librustc_trait_selection/traits/error_reporting/suggestions.rs index 5abae7ed68b9..c9eb2ee6c5a3 100644 --- a/src/librustc_trait_selection/traits/error_reporting/suggestions.rs +++ b/src/librustc_trait_selection/traits/error_reporting/suggestions.rs @@ -156,7 +156,7 @@ fn predicate_constraint(generics: &hir::Generics<'_>, pred: String) -> (Span, St ( generics.where_clause.span_for_predicates_or_empty_place().shrink_to_hi(), format!( - "{} {} ", + "{} {}", if !generics.where_clause.predicates.is_empty() { "," } else { " where" }, pred, ), @@ -263,7 +263,7 @@ fn suggest_restriction( ); } else { // Trivial case: `T` needs an extra bound: `T: Bound`. - let (sp, sugg) = match super_traits { + let (sp, suggestion) = match super_traits { None => { predicate_constraint(generics, trait_ref.without_const().to_predicate().to_string()) } @@ -279,8 +279,12 @@ fn suggest_restriction( }, }; - let appl = Applicability::MachineApplicable; - err.span_suggestion(sp, &format!("consider further restricting {}", msg), sugg, appl); + err.span_suggestion_verbose( + sp, + &format!("consider further restricting {}", msg), + suggestion, + Applicability::MachineApplicable, + ); } } diff --git a/src/test/ui/associated-type-bounds/bad-bounds-on-assoc-in-trait.stderr b/src/test/ui/associated-type-bounds/bad-bounds-on-assoc-in-trait.stderr index f65ae32c01c9..cbacc3610dcf 100644 --- a/src/test/ui/associated-type-bounds/bad-bounds-on-assoc-in-trait.stderr +++ b/src/test/ui/associated-type-bounds/bad-bounds-on-assoc-in-trait.stderr @@ -16,11 +16,13 @@ error[E0277]: `<::C as std::iter::Iterator>::Item` is not an iterato --> $DIR/bad-bounds-on-assoc-in-trait.rs:36:20 | LL | fn assume_case1() { - | ^^^^^ - help: consider further restricting the associated type: `where <::C as std::iter::Iterator>::Item: std::iter::Iterator` - | | - | `<::C as std::iter::Iterator>::Item` is not an iterator + | ^^^^^ `<::C as std::iter::Iterator>::Item` is not an iterator | = help: the trait `std::iter::Iterator` is not implemented for `<::C as std::iter::Iterator>::Item` +help: consider further restricting the associated type + | +LL | fn assume_case1() where <::C as std::iter::Iterator>::Item: std::iter::Iterator { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: `<::C as std::iter::Iterator>::Item` cannot be sent between threads safely --> $DIR/bad-bounds-on-assoc-in-trait.rs:36:20 @@ -32,11 +34,13 @@ LL | Send + Iterator() { - | ^^^^^ - help: consider further restricting the associated type: `where <::C as std::iter::Iterator>::Item: std::marker::Send` - | | - | `<::C as std::iter::Iterator>::Item` cannot be sent between threads safely + | ^^^^^ `<::C as std::iter::Iterator>::Item` cannot be sent between threads safely | = help: the trait `std::marker::Send` is not implemented for `<::C as std::iter::Iterator>::Item` +help: consider further restricting the associated type + | +LL | fn assume_case1() where <::C as std::iter::Iterator>::Item: std::marker::Send { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: `<::C as std::iter::Iterator>::Item` cannot be shared between threads safely --> $DIR/bad-bounds-on-assoc-in-trait.rs:36:20 @@ -48,11 +52,13 @@ LL | > + Sync>; | ---- required by this bound in `Case1` ... LL | fn assume_case1() { - | ^^^^^ - help: consider further restricting the associated type: `where <::C as std::iter::Iterator>::Item: std::marker::Sync` - | | - | `<::C as std::iter::Iterator>::Item` cannot be shared between threads safely + | ^^^^^ `<::C as std::iter::Iterator>::Item` cannot be shared between threads safely | = help: the trait `std::marker::Sync` is not implemented for `<::C as std::iter::Iterator>::Item` +help: consider further restricting the associated type + | +LL | fn assume_case1() where <::C as std::iter::Iterator>::Item: std::marker::Sync { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: `<_ as Lam<&'a u8>>::App` doesn't implement `std::fmt::Debug` --> $DIR/bad-bounds-on-assoc-in-trait.rs:36:20 diff --git a/src/test/ui/associated-types/associated-types-bound-failure.fixed b/src/test/ui/associated-types/associated-types-bound-failure.fixed index cc47f31d0045..68ee38d16b3f 100644 --- a/src/test/ui/associated-types/associated-types-bound-failure.fixed +++ b/src/test/ui/associated-types/associated-types-bound-failure.fixed @@ -14,7 +14,7 @@ pub trait GetToInt } fn foo(g: G) -> isize - where G : GetToInt, ::R: ToInt + where G : GetToInt, ::R: ToInt { ToInt::to_int(&g.get()) //~ ERROR E0277 } diff --git a/src/test/ui/associated-types/associated-types-bound-failure.stderr b/src/test/ui/associated-types/associated-types-bound-failure.stderr index c420c86a2758..ab8909d1092b 100644 --- a/src/test/ui/associated-types/associated-types-bound-failure.stderr +++ b/src/test/ui/associated-types/associated-types-bound-failure.stderr @@ -4,11 +4,13 @@ error[E0277]: the trait bound `::R: ToInt` is not satisfied LL | fn to_int(&self) -> isize; | -------------------------- required by `ToInt::to_int` ... -LL | where G : GetToInt - | - help: consider further restricting the associated type: `, ::R: ToInt` -LL | { LL | ToInt::to_int(&g.get()) | ^^^^^^^^ the trait `ToInt` is not implemented for `::R` + | +help: consider further restricting the associated type + | +LL | where G : GetToInt, ::R: ToInt + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/associated-types/associated-types-for-unimpl-trait.fixed b/src/test/ui/associated-types/associated-types-for-unimpl-trait.fixed index aa23326506f6..80bbef17469d 100644 --- a/src/test/ui/associated-types/associated-types-for-unimpl-trait.fixed +++ b/src/test/ui/associated-types/associated-types-for-unimpl-trait.fixed @@ -7,7 +7,7 @@ trait Get { } trait Other { - fn uhoh(&self, foo: U, bar: ::Value) where Self: Get {} + fn uhoh(&self, foo: U, bar: ::Value) where Self: Get {} //~^ ERROR the trait bound `Self: Get` is not satisfied } diff --git a/src/test/ui/associated-types/associated-types-for-unimpl-trait.stderr b/src/test/ui/associated-types/associated-types-for-unimpl-trait.stderr index 83d5390417e7..6d7289bd0712 100644 --- a/src/test/ui/associated-types/associated-types-for-unimpl-trait.stderr +++ b/src/test/ui/associated-types/associated-types-for-unimpl-trait.stderr @@ -2,10 +2,12 @@ error[E0277]: the trait bound `Self: Get` is not satisfied --> $DIR/associated-types-for-unimpl-trait.rs:10:5 | LL | fn uhoh(&self, foo: U, bar: ::Value) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-^^ - | | | - | | help: consider further restricting `Self`: `where Self: Get` - | the trait `Get` is not implemented for `Self` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `Self` + | +help: consider further restricting `Self` + | +LL | fn uhoh(&self, foo: U, bar: ::Value) where Self: Get {} + | ^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/associated-types/associated-types-no-suitable-supertrait-2.stderr b/src/test/ui/associated-types/associated-types-no-suitable-supertrait-2.stderr index 6aa0403088d3..dfe62aa5d6b0 100644 --- a/src/test/ui/associated-types/associated-types-no-suitable-supertrait-2.stderr +++ b/src/test/ui/associated-types/associated-types-no-suitable-supertrait-2.stderr @@ -2,10 +2,12 @@ error[E0277]: the trait bound `Self: Get` is not satisfied --> $DIR/associated-types-no-suitable-supertrait-2.rs:17:5 | LL | fn uhoh(&self, foo: U, bar: ::Value) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-^^ - | | | - | | help: consider further restricting `Self`: `where Self: Get` - | the trait `Get` is not implemented for `Self` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `Self` + | +help: consider further restricting `Self` + | +LL | fn uhoh(&self, foo: U, bar: ::Value) where Self: Get {} + | ^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/associated-types/associated-types-no-suitable-supertrait.stderr b/src/test/ui/associated-types/associated-types-no-suitable-supertrait.stderr index 8c242be97961..f0f2451a1ece 100644 --- a/src/test/ui/associated-types/associated-types-no-suitable-supertrait.stderr +++ b/src/test/ui/associated-types/associated-types-no-suitable-supertrait.stderr @@ -2,10 +2,12 @@ error[E0277]: the trait bound `Self: Get` is not satisfied --> $DIR/associated-types-no-suitable-supertrait.rs:17:5 | LL | fn uhoh(&self, foo: U, bar: ::Value) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-^^ - | | | - | | help: consider further restricting `Self`: `where Self: Get` - | the trait `Get` is not implemented for `Self` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `Self` + | +help: consider further restricting `Self` + | +LL | fn uhoh(&self, foo: U, bar: ::Value) where Self: Get {} + | ^^^^^^^^^^^^^^^ error[E0277]: the trait bound `(T, U): Get` is not satisfied --> $DIR/associated-types-no-suitable-supertrait.rs:22:5 diff --git a/src/test/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.fixed b/src/test/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.fixed index f357045a456e..9bc308465ebd 100644 --- a/src/test/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.fixed +++ b/src/test/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.fixed @@ -7,7 +7,7 @@ trait Get { } trait Other { - fn okay(&self, foo: U, bar: ::Value) where Self: Get ; + fn okay(&self, foo: U, bar: ::Value) where Self: Get; //~^ ERROR E0277 } diff --git a/src/test/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.stderr b/src/test/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.stderr index cb01488fa34d..4528f03c54a6 100644 --- a/src/test/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.stderr +++ b/src/test/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.stderr @@ -2,10 +2,12 @@ error[E0277]: the trait bound `Self: Get` is not satisfied --> $DIR/associated-types-projection-to-unrelated-trait-in-method-without-default.rs:10:5 | LL | fn okay(&self, foo: U, bar: ::Value); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- - | | | - | | help: consider further restricting `Self`: `where Self: Get` - | the trait `Get` is not implemented for `Self` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `Self` + | +help: consider further restricting `Self` + | +LL | fn okay(&self, foo: U, bar: ::Value) where Self: Get; + | ^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/associated-types/associated-types-unsized.fixed b/src/test/ui/associated-types/associated-types-unsized.fixed index f780d171fee8..9837796e308d 100644 --- a/src/test/ui/associated-types/associated-types-unsized.fixed +++ b/src/test/ui/associated-types/associated-types-unsized.fixed @@ -6,7 +6,7 @@ trait Get { fn get(&self) -> ::Value; } -fn foo(t: T) where ::Value: std::marker::Sized { +fn foo(t: T) where ::Value: std::marker::Sized { let x = t.get(); //~ ERROR the size for values of type } diff --git a/src/test/ui/associated-types/associated-types-unsized.stderr b/src/test/ui/associated-types/associated-types-unsized.stderr index 2352ac4ad382..6daba54ac696 100644 --- a/src/test/ui/associated-types/associated-types-unsized.stderr +++ b/src/test/ui/associated-types/associated-types-unsized.stderr @@ -1,8 +1,6 @@ error[E0277]: the size for values of type `::Value` cannot be known at compilation time --> $DIR/associated-types-unsized.rs:10:9 | -LL | fn foo(t: T) { - | - help: consider further restricting the associated type: `where ::Value: std::marker::Sized` LL | let x = t.get(); | ^ doesn't have a size known at compile-time | @@ -10,6 +8,10 @@ LL | let x = t.get(); = note: to learn more, visit = note: all local variables must have a statically known size = help: unsized locals are gated as an unstable feature +help: consider further restricting the associated type + | +LL | fn foo(t: T) where ::Value: std::marker::Sized { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/associated-types/defaults-suitability.stderr b/src/test/ui/associated-types/defaults-suitability.stderr index 3f6702da2a4a..8676c1fa2231 100644 --- a/src/test/ui/associated-types/defaults-suitability.stderr +++ b/src/test/ui/associated-types/defaults-suitability.stderr @@ -85,25 +85,29 @@ error[E0277]: the trait bound `>::Baz: std::clone::Clone` is not --> $DIR/defaults-suitability.rs:72:15 | LL | trait Foo2 { - | -------------- help: consider further restricting the associated type: `where >::Baz: std::clone::Clone` - | | - | required by `Foo2` + | ------------- required by `Foo2` LL | type Bar: Clone = Vec; | ^^^^^ the trait `std::clone::Clone` is not implemented for `>::Baz` | = note: required because of the requirements on the impl of `std::clone::Clone` for `std::vec::Vec<>::Baz>` +help: consider further restricting the associated type + | +LL | trait Foo2 where >::Baz: std::clone::Clone { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `>::Baz: std::clone::Clone` is not satisfied --> $DIR/defaults-suitability.rs:81:15 | LL | trait Foo25 { - | ---------------------- help: consider further restricting the associated type: `where >::Baz: std::clone::Clone` - | | - | required by `Foo25` + | --------------------- required by `Foo25` LL | type Bar: Clone = Vec; | ^^^^^ the trait `std::clone::Clone` is not implemented for `>::Baz` | = note: required because of the requirements on the impl of `std::clone::Clone` for `std::vec::Vec<>::Baz>` +help: consider further restricting the associated type + | +LL | trait Foo25 where >::Baz: std::clone::Clone { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `T: std::clone::Clone` is not satisfied --> $DIR/defaults-suitability.rs:90:16 diff --git a/src/test/ui/associated-types/defaults-unsound-62211-1.stderr b/src/test/ui/associated-types/defaults-unsound-62211-1.stderr index c804bc3d833f..69c310766c1c 100644 --- a/src/test/ui/associated-types/defaults-unsound-62211-1.stderr +++ b/src/test/ui/associated-types/defaults-unsound-62211-1.stderr @@ -2,50 +2,60 @@ error[E0277]: the trait bound `Self: std::marker::Copy` is not satisfied --> $DIR/defaults-unsound-62211-1.rs:21:18 | LL | trait UncheckedCopy: Sized { - | --------------------------- help: consider further restricting `Self`: `+ std::marker::Copy` - | | - | required by `UncheckedCopy` + | -------------------------- required by `UncheckedCopy` ... LL | type Output: Copy | ^^^^ the trait `std::marker::Copy` is not implemented for `Self` + | +help: consider further restricting `Self` + | +LL | trait UncheckedCopy: Sized + std::marker::Copy { + | ^^^^^^^^^^^^^^^^^^^ error[E0277]: cannot add-assign `&'static str` to `Self` --> $DIR/defaults-unsound-62211-1.rs:25:7 | LL | trait UncheckedCopy: Sized { - | --------------------------- help: consider further restricting `Self`: `+ std::ops::AddAssign<&'static str>` - | | - | required by `UncheckedCopy` + | -------------------------- required by `UncheckedCopy` ... LL | + AddAssign<&'static str> | ^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `Self += &'static str` | = help: the trait `std::ops::AddAssign<&'static str>` is not implemented for `Self` +help: consider further restricting `Self` + | +LL | trait UncheckedCopy: Sized + std::ops::AddAssign<&'static str> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `Self: std::ops::Deref` is not satisfied --> $DIR/defaults-unsound-62211-1.rs:23:7 | LL | trait UncheckedCopy: Sized { - | --------------------------- help: consider further restricting `Self`: `+ std::ops::Deref` - | | - | required by `UncheckedCopy` + | -------------------------- required by `UncheckedCopy` ... LL | + Deref | ^^^^^^^^^^^^^^^^^^^ the trait `std::ops::Deref` is not implemented for `Self` + | +help: consider further restricting `Self` + | +LL | trait UncheckedCopy: Sized + std::ops::Deref { + | ^^^^^^^^^^^^^^^^^ error[E0277]: `Self` doesn't implement `std::fmt::Display` --> $DIR/defaults-unsound-62211-1.rs:28:7 | LL | trait UncheckedCopy: Sized { - | --------------------------- help: consider further restricting `Self`: `+ std::fmt::Display` - | | - | required by `UncheckedCopy` + | -------------------------- required by `UncheckedCopy` ... LL | + Display = Self; | ^^^^^^^ `Self` cannot be formatted with the default formatter | = help: the trait `std::fmt::Display` is not implemented for `Self` = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead +help: consider further restricting `Self` + | +LL | trait UncheckedCopy: Sized + std::fmt::Display { + | ^^^^^^^^^^^^^^^^^^^ error[E0277]: `T` doesn't implement `std::fmt::Display` --> $DIR/defaults-unsound-62211-1.rs:41:9 diff --git a/src/test/ui/associated-types/defaults-unsound-62211-2.stderr b/src/test/ui/associated-types/defaults-unsound-62211-2.stderr index aee5e4b28ca6..84f0ba7529ea 100644 --- a/src/test/ui/associated-types/defaults-unsound-62211-2.stderr +++ b/src/test/ui/associated-types/defaults-unsound-62211-2.stderr @@ -2,50 +2,60 @@ error[E0277]: the trait bound `Self: std::marker::Copy` is not satisfied --> $DIR/defaults-unsound-62211-2.rs:21:18 | LL | trait UncheckedCopy: Sized { - | --------------------------- help: consider further restricting `Self`: `+ std::marker::Copy` - | | - | required by `UncheckedCopy` + | -------------------------- required by `UncheckedCopy` ... LL | type Output: Copy | ^^^^ the trait `std::marker::Copy` is not implemented for `Self` + | +help: consider further restricting `Self` + | +LL | trait UncheckedCopy: Sized + std::marker::Copy { + | ^^^^^^^^^^^^^^^^^^^ error[E0277]: cannot add-assign `&'static str` to `Self` --> $DIR/defaults-unsound-62211-2.rs:25:7 | LL | trait UncheckedCopy: Sized { - | --------------------------- help: consider further restricting `Self`: `+ std::ops::AddAssign<&'static str>` - | | - | required by `UncheckedCopy` + | -------------------------- required by `UncheckedCopy` ... LL | + AddAssign<&'static str> | ^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `Self += &'static str` | = help: the trait `std::ops::AddAssign<&'static str>` is not implemented for `Self` +help: consider further restricting `Self` + | +LL | trait UncheckedCopy: Sized + std::ops::AddAssign<&'static str> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `Self: std::ops::Deref` is not satisfied --> $DIR/defaults-unsound-62211-2.rs:23:7 | LL | trait UncheckedCopy: Sized { - | --------------------------- help: consider further restricting `Self`: `+ std::ops::Deref` - | | - | required by `UncheckedCopy` + | -------------------------- required by `UncheckedCopy` ... LL | + Deref | ^^^^^^^^^^^^^^^^^^^ the trait `std::ops::Deref` is not implemented for `Self` + | +help: consider further restricting `Self` + | +LL | trait UncheckedCopy: Sized + std::ops::Deref { + | ^^^^^^^^^^^^^^^^^ error[E0277]: `Self` doesn't implement `std::fmt::Display` --> $DIR/defaults-unsound-62211-2.rs:28:7 | LL | trait UncheckedCopy: Sized { - | --------------------------- help: consider further restricting `Self`: `+ std::fmt::Display` - | | - | required by `UncheckedCopy` + | -------------------------- required by `UncheckedCopy` ... LL | + Display = Self; | ^^^^^^^ `Self` cannot be formatted with the default formatter | = help: the trait `std::fmt::Display` is not implemented for `Self` = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead +help: consider further restricting `Self` + | +LL | trait UncheckedCopy: Sized + std::fmt::Display { + | ^^^^^^^^^^^^^^^^^^^ error[E0277]: `T` doesn't implement `std::fmt::Display` --> $DIR/defaults-unsound-62211-2.rs:41:9 diff --git a/src/test/ui/associated-types/issue-63593.stderr b/src/test/ui/associated-types/issue-63593.stderr index 42529fd2b220..82e76ff0b7cb 100644 --- a/src/test/ui/associated-types/issue-63593.stderr +++ b/src/test/ui/associated-types/issue-63593.stderr @@ -2,14 +2,16 @@ error[E0277]: the size for values of type `Self` cannot be known at compilation --> $DIR/issue-63593.rs:9:5 | LL | trait MyTrait { - | -------------- help: consider further restricting `Self`: `: std::marker::Sized` - | | - | required by `MyTrait` + | ------------- required by `MyTrait` LL | type This = Self; | ^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | = help: the trait `std::marker::Sized` is not implemented for `Self` = note: to learn more, visit +help: consider further restricting `Self` + | +LL | trait MyTrait: std::marker::Sized { + | ^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/associated-types/trait-with-supertraits-needing-sized-self.stderr b/src/test/ui/associated-types/trait-with-supertraits-needing-sized-self.stderr index 707bcf5e2feb..a37573dffff4 100644 --- a/src/test/ui/associated-types/trait-with-supertraits-needing-sized-self.stderr +++ b/src/test/ui/associated-types/trait-with-supertraits-needing-sized-self.stderr @@ -2,7 +2,7 @@ error[E0277]: the size for values of type `Self` cannot be known at compilation --> $DIR/trait-with-supertraits-needing-sized-self.rs:3:22 | LL | trait ArithmeticOps: Add + Sub + Mul + Div {} - | ^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time - help: consider further restricting `Self`: `+ std::marker::Sized` + | ^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | ::: $SRC_DIR/libcore/ops/arith.rs:LL:COL | @@ -11,6 +11,10 @@ LL | pub trait Add { | = help: the trait `std::marker::Sized` is not implemented for `Self` = note: to learn more, visit +help: consider further restricting `Self` + | +LL | trait ArithmeticOps: Add + Sub + Mul + Div + std::marker::Sized {} + | ^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-22872.stderr b/src/test/ui/issues/issue-22872.stderr index 283a5e04a8b6..038490bbd7c7 100644 --- a/src/test/ui/issues/issue-22872.stderr +++ b/src/test/ui/issues/issue-22872.stderr @@ -1,14 +1,16 @@ error[E0277]: `

>::Item` is not an iterator --> $DIR/issue-22872.rs:20:40 | -LL | fn push_process

(process: P) where P: Process<'static> { - | - help: consider further restricting the associated type: `,

>::Item: std::iter::Iterator` LL | let _: Box Wrap<'b>> = Box::new(Wrapper(process)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ `

>::Item` is not an iterator | = help: the trait `std::iter::Iterator` is not implemented for `

>::Item` = note: required because of the requirements on the impl of `for<'b> Wrap<'b>` for `Wrapper

` = note: required for the cast to the object type `dyn for<'b> Wrap<'b>` +help: consider further restricting the associated type + | +LL | fn push_process

(process: P) where P: Process<'static>,

>::Item: std::iter::Iterator { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-27078.stderr b/src/test/ui/issues/issue-27078.stderr index fbc72d063f37..3eb9d3c62039 100644 --- a/src/test/ui/issues/issue-27078.stderr +++ b/src/test/ui/issues/issue-27078.stderr @@ -2,14 +2,16 @@ error[E0277]: the size for values of type `Self` cannot be known at compilation --> $DIR/issue-27078.rs:5:12 | LL | fn foo(self) -> &'static i32 { - | ^^^^ - help: consider further restricting `Self`: `where Self: std::marker::Sized` - | | - | doesn't have a size known at compile-time + | ^^^^ doesn't have a size known at compile-time | = help: the trait `std::marker::Sized` is not implemented for `Self` = note: to learn more, visit = note: all local variables must have a statically known size = help: unsized locals are gated as an unstable feature +help: consider further restricting `Self` + | +LL | fn foo(self) -> &'static i32 where Self: std::marker::Sized { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-42312.stderr b/src/test/ui/issues/issue-42312.stderr index 915bfffd6d59..0d4797a7a067 100644 --- a/src/test/ui/issues/issue-42312.stderr +++ b/src/test/ui/issues/issue-42312.stderr @@ -2,14 +2,16 @@ error[E0277]: the size for values of type `::Target` ca --> $DIR/issue-42312.rs:4:12 | LL | fn baz(_: Self::Target) where Self: Deref {} - | ^ - help: consider further restricting the associated type: `, ::Target: std::marker::Sized` - | | - | doesn't have a size known at compile-time + | ^ doesn't have a size known at compile-time | = help: the trait `std::marker::Sized` is not implemented for `::Target` = note: to learn more, visit = note: all function arguments must have a statically known size = help: unsized locals are gated as an unstable feature +help: consider further restricting the associated type + | +LL | fn baz(_: Self::Target) where Self: Deref, ::Target: std::marker::Sized {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the size for values of type `(dyn std::string::ToString + 'static)` cannot be known at compilation time --> $DIR/issue-42312.rs:8:10 diff --git a/src/test/ui/suggestions/impl-trait-with-missing-bounds.stderr b/src/test/ui/suggestions/impl-trait-with-missing-bounds.stderr index 6fc629b33a21..fb0914a8743e 100644 --- a/src/test/ui/suggestions/impl-trait-with-missing-bounds.stderr +++ b/src/test/ui/suggestions/impl-trait-with-missing-bounds.stderr @@ -10,7 +10,7 @@ LL | fn qux(_: impl std::fmt::Debug) {} = help: the trait `std::fmt::Debug` is not implemented for `::Item` help: introduce a type parameter with a trait bound instead of using `impl Trait` | -LL | fn foo(constraints: I) where ::Item: std::fmt::Debug { +LL | fn foo(constraints: I) where ::Item: std::fmt::Debug { | ^^^^^^^^^^^^^ ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: `::Item` doesn't implement `std::fmt::Debug` @@ -25,7 +25,7 @@ LL | fn qux(_: impl std::fmt::Debug) {} = help: the trait `std::fmt::Debug` is not implemented for `::Item` help: introduce a type parameter with a trait bound instead of using `impl Trait` | -LL | fn bar(t: T, constraints: I) where T: std::fmt::Debug, ::Item: std::fmt::Debug { +LL | fn bar(t: T, constraints: I) where T: std::fmt::Debug, ::Item: std::fmt::Debug { | ^^^^^^^^^^^^^ ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: `::Item` doesn't implement `std::fmt::Debug` @@ -40,7 +40,7 @@ LL | fn qux(_: impl std::fmt::Debug) {} = help: the trait `std::fmt::Debug` is not implemented for `::Item` help: introduce a type parameter with a trait bound instead of using `impl Trait` | -LL | fn baz(t: impl std::fmt::Debug, constraints: I) where ::Item: std::fmt::Debug { +LL | fn baz(t: impl std::fmt::Debug, constraints: I) where ::Item: std::fmt::Debug { | ^^^^^^^^^^^^^ ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: `::Item` doesn't implement `std::fmt::Debug` @@ -55,7 +55,7 @@ LL | fn qux(_: impl std::fmt::Debug) {} = help: the trait `std::fmt::Debug` is not implemented for `::Item` help: introduce a type parameter with a trait bound instead of using `impl Trait` | -LL | fn bat(t: T, constraints: U, _: I) where ::Item: std::fmt::Debug { +LL | fn bat(t: T, constraints: U, _: I) where ::Item: std::fmt::Debug { | ^^^^^^^^^^^^^ ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: `::Item` doesn't implement `std::fmt::Debug` @@ -70,7 +70,7 @@ LL | fn qux(_: impl std::fmt::Debug) {} = help: the trait `std::fmt::Debug` is not implemented for `::Item` help: introduce a type parameter with a trait bound instead of using `impl Trait` | -LL | fn bak(constraints: I) where ::Item: std::fmt::Debug { +LL | fn bak(constraints: I) where ::Item: std::fmt::Debug { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 5 previous errors diff --git a/src/test/ui/suggestions/missing-assoc-type-bound-restriction.stderr b/src/test/ui/suggestions/missing-assoc-type-bound-restriction.stderr index ef484e94729e..a8ea21479618 100644 --- a/src/test/ui/suggestions/missing-assoc-type-bound-restriction.stderr +++ b/src/test/ui/suggestions/missing-assoc-type-bound-restriction.stderr @@ -8,9 +8,12 @@ LL | type Assoc: Child; | --------------- required by this bound in `Parent` ... LL | impl> Parent for ParentWrapper { - | ^^^^^^ - help: consider further restricting the associated type: `where ::Assoc: Child` - | | - | the trait `Child` is not implemented for `::Assoc` + | ^^^^^^ the trait `Child` is not implemented for `::Assoc` + | +help: consider further restricting the associated type + | +LL | impl> Parent for ParentWrapper where ::Assoc: Child { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `::Assoc: Child` is not satisfied --> $DIR/missing-assoc-type-bound-restriction.rs:20:18 @@ -21,13 +24,14 @@ LL | type Ty; LL | type Assoc: Child; | --------------- required by this bound in `Parent` ... -LL | impl> Parent for ParentWrapper { - | - help: consider further restricting the associated type: `where ::Assoc: Child` -... LL | type Assoc = ChildWrapper; | ^^^^^^^^^^^^^^^^^^^^^^ the trait `Child` is not implemented for `::Assoc` | = note: required because of the requirements on the impl of `Child` for `ChildWrapper<::Assoc>` +help: consider further restricting the associated type + | +LL | impl> Parent for ParentWrapper where ::Assoc: Child { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `::Assoc: Child` is not satisfied --> $DIR/missing-assoc-type-bound-restriction.rs:20:5 @@ -38,11 +42,13 @@ LL | type Ty; LL | type Assoc: Child; | --------------- required by this bound in `Parent` ... -LL | impl> Parent for ParentWrapper { - | - help: consider further restricting the associated type: `where ::Assoc: Child` -... LL | type Assoc = ChildWrapper; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Child` is not implemented for `::Assoc` + | +help: consider further restricting the associated type + | +LL | impl> Parent for ParentWrapper where ::Assoc: Child { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 3 previous errors diff --git a/src/test/ui/type/type-params-in-different-spaces-2.stderr b/src/test/ui/type/type-params-in-different-spaces-2.stderr index 7ce249a60b85..e0039f2a3160 100644 --- a/src/test/ui/type/type-params-in-different-spaces-2.stderr +++ b/src/test/ui/type/type-params-in-different-spaces-2.stderr @@ -4,10 +4,13 @@ error[E0277]: the trait bound `Self: Tr` is not satisfied LL | fn op(_: T) -> Self; | -------------------- required by `Tr::op` ... -LL | fn test(u: U) -> Self { - | - help: consider further restricting `Self`: `where Self: Tr` LL | Tr::op(u) | ^^^^^^ the trait `Tr` is not implemented for `Self` + | +help: consider further restricting `Self` + | +LL | fn test(u: U) -> Self where Self: Tr { + | ^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `Self: Tr` is not satisfied --> $DIR/type-params-in-different-spaces-2.rs:16:9 @@ -15,10 +18,13 @@ error[E0277]: the trait bound `Self: Tr` is not satisfied LL | fn op(_: T) -> Self; | -------------------- required by `Tr::op` ... -LL | fn test(u: U) -> Self { - | - help: consider further restricting `Self`: `where Self: Tr` LL | Tr::op(u) | ^^^^^^ the trait `Tr` is not implemented for `Self` + | +help: consider further restricting `Self` + | +LL | fn test(u: U) -> Self where Self: Tr { + | ^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/typeck/typeck-default-trait-impl-assoc-type.fixed b/src/test/ui/typeck/typeck-default-trait-impl-assoc-type.fixed index 7a108d880bed..dd1195b99f69 100644 --- a/src/test/ui/typeck/typeck-default-trait-impl-assoc-type.fixed +++ b/src/test/ui/typeck/typeck-default-trait-impl-assoc-type.fixed @@ -7,7 +7,7 @@ trait Trait { type AssocType; fn dummy(&self) { } } -fn bar() where ::AssocType: std::marker::Send { +fn bar() where ::AssocType: std::marker::Send { is_send::(); //~ ERROR E0277 } diff --git a/src/test/ui/typeck/typeck-default-trait-impl-assoc-type.stderr b/src/test/ui/typeck/typeck-default-trait-impl-assoc-type.stderr index e64acfc54ff2..f97d41637ba0 100644 --- a/src/test/ui/typeck/typeck-default-trait-impl-assoc-type.stderr +++ b/src/test/ui/typeck/typeck-default-trait-impl-assoc-type.stderr @@ -1,8 +1,6 @@ error[E0277]: `::AssocType` cannot be sent between threads safely --> $DIR/typeck-default-trait-impl-assoc-type.rs:11:5 | -LL | fn bar() { - | - help: consider further restricting the associated type: `where ::AssocType: std::marker::Send` LL | is_send::(); | ^^^^^^^^^^^^^^^^^^^^^^^ `::AssocType` cannot be sent between threads safely ... @@ -10,6 +8,10 @@ LL | fn is_send() { | ---- required by this bound in `is_send` | = help: the trait `std::marker::Send` is not implemented for `::AssocType` +help: consider further restricting the associated type + | +LL | fn bar() where ::AssocType: std::marker::Send { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/wf/wf-trait-associated-type-trait.stderr b/src/test/ui/wf/wf-trait-associated-type-trait.stderr index 70cf88f262fd..e2892e3d2488 100644 --- a/src/test/ui/wf/wf-trait-associated-type-trait.stderr +++ b/src/test/ui/wf/wf-trait-associated-type-trait.stderr @@ -3,12 +3,14 @@ error[E0277]: the trait bound `::Type1: std::marker::Copy` is | LL | struct IsCopy { x: T } | ---- required by this bound in `IsCopy` -LL | -LL | trait SomeTrait { - | - help: consider further restricting the associated type: `where ::Type1: std::marker::Copy` -LL | type Type1; +... LL | type Type2 = IsCopy; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `::Type1` + | +help: consider further restricting the associated type + | +LL | trait SomeTrait where ::Type1: std::marker::Copy { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/wf/wf-trait-default-fn-arg.stderr b/src/test/ui/wf/wf-trait-default-fn-arg.stderr index ed563af59281..23d886e25ff1 100644 --- a/src/test/ui/wf/wf-trait-default-fn-arg.stderr +++ b/src/test/ui/wf/wf-trait-default-fn-arg.stderr @@ -5,9 +5,12 @@ LL | struct Bar { value: Box } | -- required by this bound in `Bar` ... LL | fn bar(&self, x: &Bar) { - | ^^^^^^^^^^ - help: consider further restricting `Self`: `where Self: std::cmp::Eq` - | | - | the trait `std::cmp::Eq` is not implemented for `Self` + | ^^^^^^^^^^ the trait `std::cmp::Eq` is not implemented for `Self` + | +help: consider further restricting `Self` + | +LL | fn bar(&self, x: &Bar) where Self: std::cmp::Eq { + | ^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/wf/wf-trait-default-fn-ret.stderr b/src/test/ui/wf/wf-trait-default-fn-ret.stderr index 57cf1e9e6dae..021406401720 100644 --- a/src/test/ui/wf/wf-trait-default-fn-ret.stderr +++ b/src/test/ui/wf/wf-trait-default-fn-ret.stderr @@ -5,9 +5,12 @@ LL | struct Bar { value: Box } | -- required by this bound in `Bar` ... LL | fn bar(&self) -> Bar { - | ^^^^^^^^^- help: consider further restricting `Self`: `where Self: std::cmp::Eq` - | | - | the trait `std::cmp::Eq` is not implemented for `Self` + | ^^^^^^^^^ the trait `std::cmp::Eq` is not implemented for `Self` + | +help: consider further restricting `Self` + | +LL | fn bar(&self) -> Bar where Self: std::cmp::Eq { + | ^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/wf/wf-trait-default-fn-where-clause.stderr b/src/test/ui/wf/wf-trait-default-fn-where-clause.stderr index 534bf4d34483..3664c8b25aae 100644 --- a/src/test/ui/wf/wf-trait-default-fn-where-clause.stderr +++ b/src/test/ui/wf/wf-trait-default-fn-where-clause.stderr @@ -5,9 +5,12 @@ LL | trait Bar { } | -- required by this bound in `Bar` ... LL | fn bar(&self) where A: Bar { - | ^^^^^^^^^- help: consider further restricting `Self`: `, Self: std::cmp::Eq` - | | - | the trait `std::cmp::Eq` is not implemented for `Self` + | ^^^^^^^^^ the trait `std::cmp::Eq` is not implemented for `Self` + | +help: consider further restricting `Self` + | +LL | fn bar(&self) where A: Bar, Self: std::cmp::Eq { + | ^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/wf/wf-trait-fn-arg.stderr b/src/test/ui/wf/wf-trait-fn-arg.stderr index 494619a2f291..b5f5f70ce817 100644 --- a/src/test/ui/wf/wf-trait-fn-arg.stderr +++ b/src/test/ui/wf/wf-trait-fn-arg.stderr @@ -5,9 +5,12 @@ LL | struct Bar { value: Box } | -- required by this bound in `Bar` ... LL | fn bar(&self, x: &Bar); - | ^^^^^^^^^^ - help: consider further restricting `Self`: `where Self: std::cmp::Eq` - | | - | the trait `std::cmp::Eq` is not implemented for `Self` + | ^^^^^^^^^^ the trait `std::cmp::Eq` is not implemented for `Self` + | +help: consider further restricting `Self` + | +LL | fn bar(&self, x: &Bar) where Self: std::cmp::Eq; + | ^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/wf/wf-trait-fn-ret.stderr b/src/test/ui/wf/wf-trait-fn-ret.stderr index 6a3381d9a22f..5e7d8cbfea61 100644 --- a/src/test/ui/wf/wf-trait-fn-ret.stderr +++ b/src/test/ui/wf/wf-trait-fn-ret.stderr @@ -5,9 +5,12 @@ LL | struct Bar { value: Box } | -- required by this bound in `Bar` ... LL | fn bar(&self) -> &Bar; - | ^^^^^^^^^^- help: consider further restricting `Self`: `where Self: std::cmp::Eq` - | | - | the trait `std::cmp::Eq` is not implemented for `Self` + | ^^^^^^^^^^ the trait `std::cmp::Eq` is not implemented for `Self` + | +help: consider further restricting `Self` + | +LL | fn bar(&self) -> &Bar where Self: std::cmp::Eq; + | ^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/wf/wf-trait-fn-where-clause.stderr b/src/test/ui/wf/wf-trait-fn-where-clause.stderr index 2d6cf838f083..2d9ba56c5854 100644 --- a/src/test/ui/wf/wf-trait-fn-where-clause.stderr +++ b/src/test/ui/wf/wf-trait-fn-where-clause.stderr @@ -5,9 +5,12 @@ LL | struct Bar { value: Box } | -- required by this bound in `Bar` ... LL | fn bar(&self) where Self: Sized, Bar: Copy; - | ^^^^- help: consider further restricting `Self`: `, Self: std::cmp::Eq` - | | - | the trait `std::cmp::Eq` is not implemented for `Self` + | ^^^^ the trait `std::cmp::Eq` is not implemented for `Self` + | +help: consider further restricting `Self` + | +LL | fn bar(&self) where Self: Sized, Bar: Copy, Self: std::cmp::Eq; + | ^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error From 4556130e7d9fdf03bedfa177a658808dbec16b8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 7 May 2020 12:54:05 -0700 Subject: [PATCH 143/203] fix test output after rebase --- src/test/ui/issues/issue-20005.stderr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/ui/issues/issue-20005.stderr b/src/test/ui/issues/issue-20005.stderr index f53489a99f3b..775f9702401a 100644 --- a/src/test/ui/issues/issue-20005.stderr +++ b/src/test/ui/issues/issue-20005.stderr @@ -11,7 +11,7 @@ LL | ) -> >::Result where Dst: From { = note: to learn more, visit help: consider further restricting `Self` | -LL | ) -> >::Result where Dst: From, Self: std::marker::Sized { +LL | ) -> >::Result where Dst: From, Self: std::marker::Sized { | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider relaxing the implicit `Sized` restriction | From 722b3df454f427db019de2e3c54739b61e6f713b Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Tue, 12 May 2020 11:27:03 -0700 Subject: [PATCH 144/203] Update books --- src/doc/book | 2 +- src/doc/edition-guide | 2 +- src/doc/embedded-book | 2 +- src/doc/nomicon | 2 +- src/doc/reference | 2 +- src/doc/rust-by-example | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/doc/book b/src/doc/book index e37c0e84e2ef..6247be15a7f7 160000 --- a/src/doc/book +++ b/src/doc/book @@ -1 +1 @@ -Subproject commit e37c0e84e2ef73d3a4ebffda8011db6814a3b02d +Subproject commit 6247be15a7f7509559f7981ee2209b9e0cc121df diff --git a/src/doc/edition-guide b/src/doc/edition-guide index 8204c1d12347..49270740c7a4 160000 --- a/src/doc/edition-guide +++ b/src/doc/edition-guide @@ -1 +1 @@ -Subproject commit 8204c1d123472cd17f0c1c5c77300ae802eb0271 +Subproject commit 49270740c7a4bff2763e6bc730b191d45b7d5167 diff --git a/src/doc/embedded-book b/src/doc/embedded-book index 40beccdf1bb8..366c50a03bed 160000 --- a/src/doc/embedded-book +++ b/src/doc/embedded-book @@ -1 +1 @@ -Subproject commit 40beccdf1bb8eb9184a2e3b42db8b8c6e394247f +Subproject commit 366c50a03bed928589771eba8a6f18e0c0c01d23 diff --git a/src/doc/nomicon b/src/doc/nomicon index 4d2d27599774..d1517d4e3f29 160000 --- a/src/doc/nomicon +++ b/src/doc/nomicon @@ -1 +1 @@ -Subproject commit 4d2d275997746d35eabfc4d992dfbdcce2f626ed +Subproject commit d1517d4e3f29264c5c67bce2658516bb5202c800 diff --git a/src/doc/reference b/src/doc/reference index ed22e6fbfcb6..892b928b565e 160000 --- a/src/doc/reference +++ b/src/doc/reference @@ -1 +1 @@ -Subproject commit ed22e6fbfcb6ce436e9ea3b4bb4a55b2fb50a57e +Subproject commit 892b928b565e35d25b6f9c47faee03b94bc41489 diff --git a/src/doc/rust-by-example b/src/doc/rust-by-example index ffc99581689f..ab072b14393c 160000 --- a/src/doc/rust-by-example +++ b/src/doc/rust-by-example @@ -1 +1 @@ -Subproject commit ffc99581689fe2455908aaef5f5cf50dd03bb8f5 +Subproject commit ab072b14393cbd9e8a1d1d75879bf51e27217bbb From 58797b01f1b0925095986e4f42b839cdb2a99ac8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 12 May 2020 11:56:11 -0700 Subject: [PATCH 145/203] review comments --- .../traits/error_reporting/suggestions.rs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/librustc_trait_selection/traits/error_reporting/suggestions.rs b/src/librustc_trait_selection/traits/error_reporting/suggestions.rs index c9eb2ee6c5a3..5c4ba40bf38e 100644 --- a/src/librustc_trait_selection/traits/error_reporting/suggestions.rs +++ b/src/librustc_trait_selection/traits/error_reporting/suggestions.rs @@ -175,6 +175,11 @@ fn suggest_restriction( trait_ref: ty::PolyTraitRef<'_>, super_traits: Option<(&Ident, &hir::GenericBounds<'_>)>, ) { + // When we are dealing with a trait, `super_traits` will be `Some`: + // Given `trait T: A + B + C {}` + // - ^^^^^^^^^ GenericBounds + // | + // &Ident let span = generics.where_clause.span_for_predicates_or_empty_place(); if span.from_expansion() || span.desugaring_kind().is_some() { return; @@ -311,7 +316,8 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { ident, kind: hir::ItemKind::Trait(_, _, generics, bounds, _), .. - }) if param_ty && self_ty == self.tcx.types.self_param => { + }) if self_ty == self.tcx.types.self_param => { + assert!(param_ty); // Restricting `Self` for a single method. suggest_restriction( &generics, @@ -329,7 +335,8 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { generics, kind: hir::TraitItemKind::Fn(..), .. - }) if param_ty && self_ty == self.tcx.types.self_param => { + }) if self_ty == self.tcx.types.self_param => { + assert!(param_ty); // Restricting `Self` for a single method. suggest_restriction( &generics, "`Self`", err, None, projection, trait_ref, None, From 5320bd986b054d72522b29539278bfc5d576eabb Mon Sep 17 00:00:00 2001 From: Jade McGough Date: Mon, 11 May 2020 17:28:24 -0700 Subject: [PATCH 146/203] add long error explanation for E0228 --- src/librustc_error_codes/error_codes.rs | 2 +- src/librustc_error_codes/error_codes/E0228.md | 40 +++++++++++++++++++ .../object-lifetime-default-ambiguous.stderr | 1 + ...time-default-dyn-binding-nonstatic1.stderr | 1 + ...time-default-dyn-binding-nonstatic2.stderr | 1 + ...time-default-dyn-binding-nonstatic3.stderr | 1 + .../missing-lifetime-specifier.stderr | 2 +- .../dyn-trait-underscore-in-struct.stderr | 3 +- 8 files changed, 48 insertions(+), 3 deletions(-) create mode 100644 src/librustc_error_codes/error_codes/E0228.md diff --git a/src/librustc_error_codes/error_codes.rs b/src/librustc_error_codes/error_codes.rs index e01412bc21cf..2399e99a3099 100644 --- a/src/librustc_error_codes/error_codes.rs +++ b/src/librustc_error_codes/error_codes.rs @@ -120,6 +120,7 @@ E0223: include_str!("./error_codes/E0223.md"), E0224: include_str!("./error_codes/E0224.md"), E0225: include_str!("./error_codes/E0225.md"), E0226: include_str!("./error_codes/E0226.md"), +E0228: include_str!("./error_codes/E0228.md"), E0229: include_str!("./error_codes/E0229.md"), E0230: include_str!("./error_codes/E0230.md"), E0231: include_str!("./error_codes/E0231.md"), @@ -482,7 +483,6 @@ E0753: include_str!("./error_codes/E0753.md"), // E0218, // no associated type defined // E0219, // associated type defined in higher-ranked supertrait E0227, // ambiguous lifetime bound, explicit lifetime bound required - E0228, // explicit lifetime bound required // E0233, // E0234, // E0235, // structure constructor specifies a structure of type but diff --git a/src/librustc_error_codes/error_codes/E0228.md b/src/librustc_error_codes/error_codes/E0228.md new file mode 100644 index 000000000000..3443a5ae8638 --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0228.md @@ -0,0 +1,40 @@ +The lifetime bound for this object type cannot be deduced from context and must +be specified. + +Erroneous code example: + +```compile_fail,E0228 +trait Trait { } + +struct TwoBounds<'a, 'b, T: Sized + 'a + 'b> { + x: &'a i32, + y: &'b i32, + z: T, +} + +type Foo<'a, 'b> = TwoBounds<'a, 'b, dyn Trait>; +``` + +When a trait object is used as a type argument of a generic type, Rust will try +to infer its lifetime if unspecified. However, this isn't possible when the +containing type has more than one lifetime bound. + +The above example can be resolved by either reducing the number of lifetime +bounds to one or by making the trait object lifetime explicit, like so: + +``` +trait Trait { } + +struct TwoBounds<'a, 'b, T: Sized + 'a + 'b> { + x: &'a i32, + y: &'b i32, + z: T, +} + +type Foo<'a, 'b> = TwoBounds<'a, 'b, dyn Trait + 'b>; +``` + +For more information, see [RFC 599] and its amendment [RFC 1156]. + +[RFC 599]: https://github.com/rust-lang/rfcs/blob/master/text/0599-default-object-bound.md +[RFC 1156]: https://github.com/rust-lang/rfcs/blob/master/text/1156-adjust-default-object-bounds.md diff --git a/src/test/ui/object-lifetime/object-lifetime-default-ambiguous.stderr b/src/test/ui/object-lifetime/object-lifetime-default-ambiguous.stderr index 0c3dbffeea63..bd50a27fd5e5 100644 --- a/src/test/ui/object-lifetime/object-lifetime-default-ambiguous.stderr +++ b/src/test/ui/object-lifetime/object-lifetime-default-ambiguous.stderr @@ -18,3 +18,4 @@ LL | fn f(t: &Ref2) { error: aborting due to 3 previous errors +For more information about this error, try `rustc --explain E0228`. diff --git a/src/test/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic1.stderr b/src/test/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic1.stderr index 9dbf7a78ed7a..f06a9da1deea 100644 --- a/src/test/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic1.stderr +++ b/src/test/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic1.stderr @@ -6,3 +6,4 @@ LL | fn bar<'a>(x: &'a str) -> &'a dyn Foo<'a, Item = dyn Bar> { &() } error: aborting due to previous error +For more information about this error, try `rustc --explain E0228`. diff --git a/src/test/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic2.stderr b/src/test/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic2.stderr index d069f52ce47d..51d8450af768 100644 --- a/src/test/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic2.stderr +++ b/src/test/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic2.stderr @@ -6,3 +6,4 @@ LL | fn bar<'a>(x: &'a str) -> &'a dyn Foo<'a, Item = dyn Bar> { &() } error: aborting due to previous error +For more information about this error, try `rustc --explain E0228`. diff --git a/src/test/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic3.stderr b/src/test/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic3.stderr index 9c7b6b98f2e3..f721bf39419b 100644 --- a/src/test/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic3.stderr +++ b/src/test/ui/object-lifetime/object-lifetime-default-dyn-binding-nonstatic3.stderr @@ -6,3 +6,4 @@ LL | fn bar(x: &str) -> &dyn Foo { &() } error: aborting due to previous error +For more information about this error, try `rustc --explain E0228`. diff --git a/src/test/ui/suggestions/missing-lifetime-specifier.stderr b/src/test/ui/suggestions/missing-lifetime-specifier.stderr index f5ff54cc916c..2630cf1affae 100644 --- a/src/test/ui/suggestions/missing-lifetime-specifier.stderr +++ b/src/test/ui/suggestions/missing-lifetime-specifier.stderr @@ -252,5 +252,5 @@ LL | static f: RefCell>>>> = RefCell error: aborting due to 28 previous errors -Some errors have detailed explanations: E0106, E0107. +Some errors have detailed explanations: E0106, E0107, E0228. For more information about an error, try `rustc --explain E0106`. diff --git a/src/test/ui/underscore-lifetime/dyn-trait-underscore-in-struct.stderr b/src/test/ui/underscore-lifetime/dyn-trait-underscore-in-struct.stderr index fe242e6a909e..2c595833cd1b 100644 --- a/src/test/ui/underscore-lifetime/dyn-trait-underscore-in-struct.stderr +++ b/src/test/ui/underscore-lifetime/dyn-trait-underscore-in-struct.stderr @@ -18,4 +18,5 @@ LL | x: Box, error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0106`. +Some errors have detailed explanations: E0106, E0228. +For more information about an error, try `rustc --explain E0106`. From 9111d8b66e013a881bae4e09646514be86ca4c87 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 4 May 2020 17:17:07 +1000 Subject: [PATCH 147/203] Fix the new capacity measurement in arenas. For the given code paths, the amount of space used in the previous chunk is irrelevant. (This will almost never make a difference to behaviour, but it makes the code clearer.) --- src/libarena/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libarena/lib.rs b/src/libarena/lib.rs index 0f0bd617f439..b42a2e711acd 100644 --- a/src/libarena/lib.rs +++ b/src/libarena/lib.rs @@ -224,7 +224,7 @@ impl TypedArena { new_capacity = last_chunk.storage.capacity(); loop { new_capacity = new_capacity.checked_mul(2).unwrap(); - if new_capacity >= currently_used_cap + n { + if new_capacity >= n { break; } } @@ -350,7 +350,7 @@ impl DroplessArena { new_capacity = last_chunk.storage.capacity(); loop { new_capacity = new_capacity.checked_mul(2).unwrap(); - if new_capacity >= used_bytes + needed_bytes { + if new_capacity >= needed_bytes { break; } } From 40d4868b3949c60de42e400baabe281a00a8c615 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 4 May 2020 19:25:09 +1000 Subject: [PATCH 148/203] Be less aggressive with `DroplessArena`/`TypedArena` growth. `DroplessArena` and `TypedArena` use an aggressive growth strategy: the first chunk is 4 KiB, the second is 8 KiB, and it keeps on doubling indefinitely. DHAT profiles show that sometimes this results in large chunks (e.g. 16-128 MiB) that are barely filled. Although these don't contribute to RSS, they clog up the DHAT profiles. This commit changes things so that the doubling stops at 2 MiB. This is large enough that chunk allocations are still rare (you might get 100s instead of 10s of them) but avoids lots of unused space in the worst case. It gives a slight speed-up to cycle counts in some cases. --- src/libarena/lib.rs | 39 ++++++++++++++++++++++++++------------- 1 file changed, 26 insertions(+), 13 deletions(-) diff --git a/src/libarena/lib.rs b/src/libarena/lib.rs index b42a2e711acd..bbe80c26dcbf 100644 --- a/src/libarena/lib.rs +++ b/src/libarena/lib.rs @@ -5,8 +5,7 @@ //! of individual objects while the arena itself is still alive. The benefit //! of an arena is very fast allocation; just a pointer bump. //! -//! This crate implements `TypedArena`, a simple arena that can only hold -//! objects of a single type. +//! This crate implements several kinds of arena. #![doc( html_root_url = "https://doc.rust-lang.org/nightly/", @@ -98,7 +97,13 @@ impl TypedArenaChunk { } } +// The arenas start with PAGE-sized chunks, and then each new chunk is twice as +// big as its predecessor, up until we reach HUGE_PAGE-sized chunks, whereupon +// we stop growing. This scales well, from arenas that are barely used up to +// arenas that are used for 100s of MiBs. Note also that the chosen sizes match +// the usual sizes of pages and huge pages on Linux. const PAGE: usize = 4096; +const HUGE_PAGE: usize = 2 * 1024 * 1024; impl Default for TypedArena { /// Creates a new `TypedArena`. @@ -211,6 +216,9 @@ impl TypedArena { #[cold] fn grow(&self, n: usize) { unsafe { + // We need the element size in to convert chunk sizes (ranging from + // PAGE to HUGE_PAGE bytes) to element counts. + let elem_size = cmp::max(1, mem::size_of::()); let mut chunks = self.chunks.borrow_mut(); let (chunk, mut new_capacity); if let Some(last_chunk) = chunks.last_mut() { @@ -221,18 +229,20 @@ impl TypedArena { self.end.set(last_chunk.end()); return; } else { + // If the previous chunk's capacity is less than HUGE_PAGE + // bytes, then this chunk will be least double the previous + // chunk's size. new_capacity = last_chunk.storage.capacity(); - loop { + if new_capacity < HUGE_PAGE / elem_size { new_capacity = new_capacity.checked_mul(2).unwrap(); - if new_capacity >= n { - break; - } } } } else { - let elem_size = cmp::max(1, mem::size_of::()); - new_capacity = cmp::max(n, PAGE / elem_size); + new_capacity = PAGE / elem_size; } + // Also ensure that this chunk can fit `n`. + new_capacity = cmp::max(n, new_capacity); + chunk = TypedArenaChunk::::new(new_capacity); self.ptr.set(chunk.start()); self.end.set(chunk.end()); @@ -347,17 +357,20 @@ impl DroplessArena { self.end.set(last_chunk.end()); return; } else { + // If the previous chunk's capacity is less than HUGE_PAGE + // bytes, then this chunk will be least double the previous + // chunk's size. new_capacity = last_chunk.storage.capacity(); - loop { + if new_capacity < HUGE_PAGE { new_capacity = new_capacity.checked_mul(2).unwrap(); - if new_capacity >= needed_bytes { - break; - } } } } else { - new_capacity = cmp::max(needed_bytes, PAGE); + new_capacity = PAGE; } + // Also ensure that this chunk can fit `needed_bytes`. + new_capacity = cmp::max(needed_bytes, new_capacity); + chunk = TypedArenaChunk::::new(new_capacity); self.ptr.set(chunk.start()); self.end.set(chunk.end()); From 5a0ac0552e05c079f252482cfcdaab3c4b39d614 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 13 May 2020 15:47:19 +1000 Subject: [PATCH 149/203] Use simpler impls for some `Iterator` methods for slices. The default implementations of several `Iterator` methods use `fold` or `try_fold`, which works, but is overkill for slices and bloats the amount of LLVM IR generated and consequently hurts compile times. This commit adds the simple, obvious implementations for `for_each`, `all`, `any`, `find`, `find_map`, and simplifies the existing implementations for `position` and `rposition`. These changes reduce compile times significantly on some benchmarks. --- src/libcore/slice/mod.rs | 122 +++++++++++++++++++++++++++++++++------ 1 file changed, 105 insertions(+), 17 deletions(-) diff --git a/src/libcore/slice/mod.rs b/src/libcore/slice/mod.rs index f74c6862006c..3386f83ec810 100644 --- a/src/libcore/slice/mod.rs +++ b/src/libcore/slice/mod.rs @@ -3179,6 +3179,7 @@ macro_rules! is_empty { $self.ptr.as_ptr() as *const T == $self.end }; } + // To get rid of some bounds checks (see `position`), we compute the length in a somewhat // unexpected way. (Tested by `codegen/slice-position-bounds-check`.) macro_rules! len { @@ -3347,40 +3348,127 @@ macro_rules! iterator { self.next_back() } + // We override the default implementation, which uses `try_fold`, + // because this simple implementation generates less LLVM IR and is + // faster to compile. + #[inline] + fn for_each(mut self, mut f: F) + where + Self: Sized, + F: FnMut(Self::Item), + { + while let Some(x) = self.next() { + f(x); + } + } + + // We override the default implementation, which uses `try_fold`, + // because this simple implementation generates less LLVM IR and is + // faster to compile. + #[inline] + fn all(&mut self, mut f: F) -> bool + where + Self: Sized, + F: FnMut(Self::Item) -> bool, + { + while let Some(x) = self.next() { + if !f(x) { + return false; + } + } + true + } + + // We override the default implementation, which uses `try_fold`, + // because this simple implementation generates less LLVM IR and is + // faster to compile. + #[inline] + fn any(&mut self, mut f: F) -> bool + where + Self: Sized, + F: FnMut(Self::Item) -> bool, + { + while let Some(x) = self.next() { + if f(x) { + return true; + } + } + false + } + + // We override the default implementation, which uses `try_fold`, + // because this simple implementation generates less LLVM IR and is + // faster to compile. + #[inline] + fn find

(&mut self, mut predicate: P) -> Option + where + Self: Sized, + P: FnMut(&Self::Item) -> bool, + { + while let Some(x) = self.next() { + if predicate(&x) { + return Some(x); + } + } + None + } + + // We override the default implementation, which uses `try_fold`, + // because this simple implementation generates less LLVM IR and is + // faster to compile. + #[inline] + fn find_map(&mut self, mut f: F) -> Option + where + Self: Sized, + F: FnMut(Self::Item) -> Option, + { + while let Some(x) = self.next() { + if let Some(y) = f(x) { + return Some(y); + } + } + None + } + + // We override the default implementation, which uses `try_fold`, + // because this simple implementation generates less LLVM IR and is + // faster to compile. Also, the `assume` avoids a bounds check. #[inline] #[rustc_inherit_overflow_checks] fn position

(&mut self, mut predicate: P) -> Option where Self: Sized, P: FnMut(Self::Item) -> bool, { - // The addition might panic on overflow. let n = len!(self); - self.try_fold(0, move |i, x| { - if predicate(x) { Err(i) } - else { Ok(i + 1) } - }).err() - .map(|i| { + let mut i = 0; + while let Some(x) = self.next() { + if predicate(x) { unsafe { assume(i < n) }; - i - }) + return Some(i); + } + i += 1; + } + None } + // We override the default implementation, which uses `try_fold`, + // because this simple implementation generates less LLVM IR and is + // faster to compile. Also, the `assume` avoids a bounds check. #[inline] fn rposition

(&mut self, mut predicate: P) -> Option where P: FnMut(Self::Item) -> bool, Self: Sized + ExactSizeIterator + DoubleEndedIterator { - // No need for an overflow check here, because `ExactSizeIterator` let n = len!(self); - self.try_rfold(n, move |i, x| { - let i = i - 1; - if predicate(x) { Err(i) } - else { Ok(i) } - }).err() - .map(|i| { + let mut i = n; + while let Some(x) = self.next_back() { + i -= 1; + if predicate(x) { unsafe { assume(i < n) }; - i - }) + return Some(i); + } + } + None } $($extra)* From 3b108588d159b4f4600ec226679f5ce64341b82e Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 13 May 2020 15:48:08 +1000 Subject: [PATCH 150/203] Change `Iterator::nth` to use `self.next()` in a `while` loop. Currently it uses `for x in self`, which seems dubious within an iterator method. Furthermore, `self.next()` is used in all the other iterator methods. --- src/libcore/iter/traits/iterator.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcore/iter/traits/iterator.rs b/src/libcore/iter/traits/iterator.rs index 34ca79154b68..447db405c028 100644 --- a/src/libcore/iter/traits/iterator.rs +++ b/src/libcore/iter/traits/iterator.rs @@ -333,7 +333,7 @@ pub trait Iterator { #[inline] #[stable(feature = "rust1", since = "1.0.0")] fn nth(&mut self, mut n: usize) -> Option { - for x in self { + while let Some(x) = self.next() { if n == 0 { return Some(x); } From 1be5d1eabb957c8b0bd0f4564a5f7c8bef1826bb Mon Sep 17 00:00:00 2001 From: Julian Wollersberger <24991778+Julian-Wollersberger@users.noreply.github.com> Date: Wed, 13 May 2020 09:42:30 +0200 Subject: [PATCH 151/203] Unified `unescape_{char,byte,str,byte_str,raw_str,raw_byte_str}` methods into one method `unescape_literal` with a mode argument. --- src/librustc_lexer/src/unescape.rs | 46 +++++++++++++++++++++++++++--- 1 file changed, 42 insertions(+), 4 deletions(-) diff --git a/src/librustc_lexer/src/unescape.rs b/src/librustc_lexer/src/unescape.rs index c51bf735fa72..dcb4cc917960 100644 --- a/src/librustc_lexer/src/unescape.rs +++ b/src/librustc_lexer/src/unescape.rs @@ -58,6 +58,42 @@ pub enum EscapeError { NonAsciiCharInByteString, } +/// Takes a contents of a literal (without quotes) and produces a +/// sequence of escaped characters or errors. +/// Values are returned through invoking of the provided callback. +pub fn unescape_literal(literal_text: &str, mode: Mode, callback: &mut F) +where + F: FnMut(Range, Result), +{ + match mode { + Mode::Char | Mode::Byte => { + let mut chars = literal_text.chars(); + let result = unescape_char_or_byte(&mut chars, mode); + // The Chars iterator moved forward. + callback(0..(literal_text.len() - chars.as_str().len()), result); + } + Mode::Str | Mode::ByteStr => unescape_str_or_byte_str(literal_text, mode, callback), + // NOTE: Raw strings do not perform any explicit character escaping, here we + // only translate CRLF to LF and produce errors on bare CR. + Mode::RawStr | Mode::RawByteStr => { + unescape_raw_str_or_byte_str(literal_text, mode, callback) + } + } +} + +/// Takes a contents of a byte, byte string or raw byte string (without quotes) +/// and produces a sequence of bytes or errors. +/// Values are returned through invoking of the provided callback. +pub fn unescape_byte_literal(literal_text: &str, mode: Mode, callback: &mut F) +where + F: FnMut(Range, Result), +{ + assert!(mode.is_bytes()); + unescape_literal(literal_text, mode, &mut |range, result| { + callback(range, result.map(byte_from_char)); + }) +} + /// Takes a contents of a char literal (without quotes), and returns an /// unescaped char or an error pub fn unescape_char(literal_text: &str) -> Result { @@ -130,13 +166,15 @@ pub enum Mode { Str, Byte, ByteStr, + RawStr, + RawByteStr, } impl Mode { pub fn in_single_quotes(self) -> bool { match self { Mode::Char | Mode::Byte => true, - Mode::Str | Mode::ByteStr => false, + Mode::Str | Mode::ByteStr | Mode::RawStr | Mode::RawByteStr => false, } } @@ -146,8 +184,8 @@ impl Mode { pub fn is_bytes(self) -> bool { match self { - Mode::Byte | Mode::ByteStr => true, - Mode::Char | Mode::Str => false, + Mode::Byte | Mode::ByteStr | Mode::RawByteStr => true, + Mode::Char | Mode::Str | Mode::RawStr => false, } } } @@ -345,7 +383,7 @@ where fn byte_from_char(c: char) -> u8 { let res = c as u32; - assert!(res <= u8::max_value() as u32, "guaranteed because of Mode::Byte(Str)"); + assert!(res <= u8::max_value() as u32, "guaranteed because of Mode::ByteStr"); res as u8 } From 18cc63d693a3a1d130ba533994c895b56fed3769 Mon Sep 17 00:00:00 2001 From: Julian Wollersberger <24991778+Julian-Wollersberger@users.noreply.github.com> Date: Wed, 13 May 2020 09:52:01 +0200 Subject: [PATCH 152/203] Unified `validate_{byte,str,raw_str,raw_byte_str}_escape` methods into one method `validate_literal_escape` with a mode argument. This enables simplifying the `match` in `cook_lexer_literal()` and it eliminates 90 lines of repetition :) --- src/librustc_parse/lexer/mod.rs | 152 +++++++------------------------- 1 file changed, 30 insertions(+), 122 deletions(-) diff --git a/src/librustc_parse/lexer/mod.rs b/src/librustc_parse/lexer/mod.rs index f676a34a1d12..1d67d6de4daa 100644 --- a/src/librustc_parse/lexer/mod.rs +++ b/src/librustc_parse/lexer/mod.rs @@ -15,6 +15,7 @@ mod tokentrees; mod unescape_error_reporting; mod unicode_chars; +use rustc_lexer::unescape::Mode; use unescape_error_reporting::{emit_unescape_error, push_escaped_char}; #[derive(Clone, Debug)] @@ -326,38 +327,27 @@ impl<'a> StringReader<'a> { suffix_start: BytePos, kind: rustc_lexer::LiteralKind, ) -> (token::LitKind, Symbol) { - match kind { + // prefix means `"` or `br"` or `r###"`, ... + let (lit_kind, mode, prefix_len, postfix_len) = match kind { rustc_lexer::LiteralKind::Char { terminated } => { if !terminated { self.fatal_span_(start, suffix_start, "unterminated character literal").raise() } - let content_start = start + BytePos(1); - let content_end = suffix_start - BytePos(1); - self.validate_char_escape(content_start, content_end); - let id = self.symbol_from_to(content_start, content_end); - (token::Char, id) + (token::Char, Mode::Char, 1, 1) // ' ' } rustc_lexer::LiteralKind::Byte { terminated } => { if !terminated { self.fatal_span_(start + BytePos(1), suffix_start, "unterminated byte constant") .raise() } - let content_start = start + BytePos(2); - let content_end = suffix_start - BytePos(1); - self.validate_byte_escape(content_start, content_end); - let id = self.symbol_from_to(content_start, content_end); - (token::Byte, id) + (token::Byte, Mode::Byte, 2, 1) // b' ' } rustc_lexer::LiteralKind::Str { terminated } => { if !terminated { self.fatal_span_(start, suffix_start, "unterminated double quote string") .raise() } - let content_start = start + BytePos(1); - let content_end = suffix_start - BytePos(1); - self.validate_str_escape(content_start, content_end); - let id = self.symbol_from_to(content_start, content_end); - (token::Str, id) + (token::Str, Mode::Str, 1, 1) // " " } rustc_lexer::LiteralKind::ByteStr { terminated } => { if !terminated { @@ -368,42 +358,28 @@ impl<'a> StringReader<'a> { ) .raise() } - let content_start = start + BytePos(2); - let content_end = suffix_start - BytePos(1); - self.validate_byte_str_escape(content_start, content_end); - let id = self.symbol_from_to(content_start, content_end); - (token::ByteStr, id) + (token::ByteStr, Mode::ByteStr, 2, 1) // b" " } rustc_lexer::LiteralKind::RawStr(unvalidated_raw_str) => { let valid_raw_str = self.validate_and_report_errors(start, unvalidated_raw_str); let n_hashes = valid_raw_str.num_hashes(); let n = u32::from(n_hashes); - - let content_start = start + BytePos(2 + n); - let content_end = suffix_start - BytePos(1 + n); - self.validate_raw_str_escape(content_start, content_end); - let id = self.symbol_from_to(content_start, content_end); - (token::StrRaw(n_hashes), id) + (token::StrRaw(n_hashes), Mode::RawStr, 2 + n, 1 + n) // r##" "## } rustc_lexer::LiteralKind::RawByteStr(unvalidated_raw_str) => { let validated_raw_str = self.validate_and_report_errors(start, unvalidated_raw_str); let n_hashes = validated_raw_str.num_hashes(); let n = u32::from(n_hashes); - - let content_start = start + BytePos(3 + n); - let content_end = suffix_start - BytePos(1 + n); - self.validate_raw_byte_str_escape(content_start, content_end); - let id = self.symbol_from_to(content_start, content_end); - (token::ByteStrRaw(n_hashes), id) + (token::ByteStrRaw(n_hashes), Mode::RawByteStr, 3 + n, 1 + n) // br##" "## } rustc_lexer::LiteralKind::Int { base, empty_int } => { - if empty_int { + return if empty_int { self.err_span_(start, suffix_start, "no valid digits found for number"); (token::Integer, sym::integer(0)) } else { self.validate_int_literal(base, start, suffix_start); (token::Integer, self.symbol_from_to(start, suffix_start)) - } + }; } rustc_lexer::LiteralKind::Float { base, empty_exponent } => { if empty_exponent { @@ -431,9 +407,14 @@ impl<'a> StringReader<'a> { } let id = self.symbol_from_to(start, suffix_start); - (token::Float, id) + return (token::Float, id); } - } + }; + let content_start = start + BytePos(prefix_len); + let content_end = suffix_start - BytePos(postfix_len); + let id = self.symbol_from_to(content_start, content_end); + self.validate_literal_escape(mode, content_start, content_end); + return (lit_kind, id); } #[inline] @@ -555,96 +536,23 @@ impl<'a> StringReader<'a> { .raise(); } - fn validate_char_escape(&self, content_start: BytePos, content_end: BytePos) { - let lit = self.str_from_to(content_start, content_end); - if let Err((off, err)) = unescape::unescape_char(lit) { - emit_unescape_error( - &self.sess.span_diagnostic, - lit, - self.mk_sp(content_start - BytePos(1), content_end + BytePos(1)), - unescape::Mode::Char, - 0..off, - err, - ) - } - } - - fn validate_byte_escape(&self, content_start: BytePos, content_end: BytePos) { - let lit = self.str_from_to(content_start, content_end); - if let Err((off, err)) = unescape::unescape_byte(lit) { - emit_unescape_error( - &self.sess.span_diagnostic, - lit, - self.mk_sp(content_start - BytePos(1), content_end + BytePos(1)), - unescape::Mode::Byte, - 0..off, - err, - ) - } - } - - fn validate_str_escape(&self, content_start: BytePos, content_end: BytePos) { - let lit = self.str_from_to(content_start, content_end); - unescape::unescape_str(lit, &mut |range, c| { - if let Err(err) = c { + fn validate_literal_escape(&self, mode: Mode, content_start: BytePos, content_end: BytePos) { + let lit_content = self.str_from_to(content_start, content_end); + unescape::unescape_literal(lit_content, mode, &mut |range, result| { + // Here we only check for errors. The actual unescaping is done later. + if let Err(err) = result { + let span_with_quotes = + self.mk_sp(content_start - BytePos(1), content_end + BytePos(1)); emit_unescape_error( &self.sess.span_diagnostic, - lit, - self.mk_sp(content_start - BytePos(1), content_end + BytePos(1)), - unescape::Mode::Str, + lit_content, + span_with_quotes, + mode, range, err, - ) + ); } - }) - } - - fn validate_raw_str_escape(&self, content_start: BytePos, content_end: BytePos) { - let lit = self.str_from_to(content_start, content_end); - unescape::unescape_raw_str(lit, &mut |range, c| { - if let Err(err) = c { - emit_unescape_error( - &self.sess.span_diagnostic, - lit, - self.mk_sp(content_start - BytePos(1), content_end + BytePos(1)), - unescape::Mode::Str, - range, - err, - ) - } - }) - } - - fn validate_raw_byte_str_escape(&self, content_start: BytePos, content_end: BytePos) { - let lit = self.str_from_to(content_start, content_end); - unescape::unescape_raw_byte_str(lit, &mut |range, c| { - if let Err(err) = c { - emit_unescape_error( - &self.sess.span_diagnostic, - lit, - self.mk_sp(content_start - BytePos(1), content_end + BytePos(1)), - unescape::Mode::ByteStr, - range, - err, - ) - } - }) - } - - fn validate_byte_str_escape(&self, content_start: BytePos, content_end: BytePos) { - let lit = self.str_from_to(content_start, content_end); - unescape::unescape_byte_str(lit, &mut |range, c| { - if let Err(err) = c { - emit_unescape_error( - &self.sess.span_diagnostic, - lit, - self.mk_sp(content_start - BytePos(1), content_end + BytePos(1)), - unescape::Mode::ByteStr, - range, - err, - ) - } - }) + }); } fn validate_int_literal(&self, base: Base, content_start: BytePos, content_end: BytePos) { From 43ae7854543ea98516c3946e5f14ff3bb0f18bfd Mon Sep 17 00:00:00 2001 From: Julian Wollersberger <24991778+Julian-Wollersberger@users.noreply.github.com> Date: Wed, 13 May 2020 10:03:49 +0200 Subject: [PATCH 153/203] Replace some usages of the old `unescape_` functions in AST, clippy and tests. --- src/librustc_ast/util/literal.rs | 75 ++++++++++++---------- src/librustc_lexer/src/unescape.rs | 48 -------------- src/librustc_lexer/src/unescape/tests.rs | 10 +-- src/tools/clippy/clippy_lints/src/write.rs | 4 +- 4 files changed, 50 insertions(+), 87 deletions(-) diff --git a/src/librustc_ast/util/literal.rs b/src/librustc_ast/util/literal.rs index 1b17f343a6d6..4428d09902b9 100644 --- a/src/librustc_ast/util/literal.rs +++ b/src/librustc_ast/util/literal.rs @@ -6,8 +6,7 @@ use crate::tokenstream::TokenTree; use rustc_data_structures::sync::Lrc; use rustc_lexer::unescape::{unescape_byte, unescape_char}; -use rustc_lexer::unescape::{unescape_byte_str, unescape_str}; -use rustc_lexer::unescape::{unescape_raw_byte_str, unescape_raw_str}; +use rustc_lexer::unescape::{unescape_byte_literal, unescape_literal, Mode}; use rustc_span::symbol::{kw, sym, Symbol}; use rustc_span::Span; @@ -59,45 +58,53 @@ impl LitKind { // new symbol because the string in the LitKind is different to the // string in the token. let s = symbol.as_str(); - let symbol = if s.contains(&['\\', '\r'][..]) { - let mut buf = String::with_capacity(s.len()); - let mut error = Ok(()); - unescape_str(&s, &mut |_, unescaped_char| match unescaped_char { - Ok(c) => buf.push(c), - Err(_) => error = Err(LitError::LexerError), - }); - error?; - Symbol::intern(&buf) - } else { - symbol - }; + let symbol = + if s.contains(&['\\', '\r'][..]) { + let mut buf = String::with_capacity(s.len()); + let mut error = Ok(()); + unescape_literal(&s, Mode::Str, &mut |_, unescaped_char| { + match unescaped_char { + Ok(c) => buf.push(c), + Err(_) => error = Err(LitError::LexerError), + } + }); + error?; + Symbol::intern(&buf) + } else { + symbol + }; LitKind::Str(symbol, ast::StrStyle::Cooked) } token::StrRaw(n) => { // Ditto. let s = symbol.as_str(); - let symbol = if s.contains('\r') { - let mut buf = String::with_capacity(s.len()); - let mut error = Ok(()); - unescape_raw_str(&s, &mut |_, unescaped_char| match unescaped_char { - Ok(c) => buf.push(c), - Err(_) => error = Err(LitError::LexerError), - }); - error?; - buf.shrink_to_fit(); - Symbol::intern(&buf) - } else { - symbol - }; + let symbol = + if s.contains('\r') { + let mut buf = String::with_capacity(s.len()); + let mut error = Ok(()); + unescape_literal(&s, Mode::RawStr, &mut |_, unescaped_char| { + match unescaped_char { + Ok(c) => buf.push(c), + Err(_) => error = Err(LitError::LexerError), + } + }); + error?; + buf.shrink_to_fit(); + Symbol::intern(&buf) + } else { + symbol + }; LitKind::Str(symbol, ast::StrStyle::Raw(n)) } token::ByteStr => { let s = symbol.as_str(); let mut buf = Vec::with_capacity(s.len()); let mut error = Ok(()); - unescape_byte_str(&s, &mut |_, unescaped_byte| match unescaped_byte { - Ok(c) => buf.push(c), - Err(_) => error = Err(LitError::LexerError), + unescape_byte_literal(&s, Mode::ByteStr, &mut |_, unescaped_byte| { + match unescaped_byte { + Ok(c) => buf.push(c), + Err(_) => error = Err(LitError::LexerError), + } }); error?; buf.shrink_to_fit(); @@ -108,9 +115,11 @@ impl LitKind { let bytes = if s.contains('\r') { let mut buf = Vec::with_capacity(s.len()); let mut error = Ok(()); - unescape_raw_byte_str(&s, &mut |_, unescaped_byte| match unescaped_byte { - Ok(c) => buf.push(c), - Err(_) => error = Err(LitError::LexerError), + unescape_byte_literal(&s, Mode::RawByteStr, &mut |_, unescaped_byte| { + match unescaped_byte { + Ok(c) => buf.push(c), + Err(_) => error = Err(LitError::LexerError), + } }); error?; buf.shrink_to_fit(); diff --git a/src/librustc_lexer/src/unescape.rs b/src/librustc_lexer/src/unescape.rs index dcb4cc917960..2a9e1b7cbc34 100644 --- a/src/librustc_lexer/src/unescape.rs +++ b/src/librustc_lexer/src/unescape.rs @@ -111,54 +111,6 @@ pub fn unescape_byte(literal_text: &str) -> Result { .map_err(|err| (literal_text.len() - chars.as_str().len(), err)) } -/// Takes a contents of a string literal (without quotes) and produces a -/// sequence of escaped characters or errors. -/// Values are returned through invoking of the provided callback. -pub fn unescape_str(literal_text: &str, callback: &mut F) -where - F: FnMut(Range, Result), -{ - unescape_str_or_byte_str(literal_text, Mode::Str, callback) -} - -/// Takes a contents of a byte string literal (without quotes) and produces a -/// sequence of bytes or errors. -/// Values are returned through invoking of the provided callback. -pub fn unescape_byte_str(literal_text: &str, callback: &mut F) -where - F: FnMut(Range, Result), -{ - unescape_str_or_byte_str(literal_text, Mode::ByteStr, &mut |range, char| { - callback(range, char.map(byte_from_char)) - }) -} - -/// Takes a contents of a raw string literal (without quotes) and produces a -/// sequence of characters or errors. -/// Values are returned through invoking of the provided callback. -/// NOTE: Raw strings do not perform any explicit character escaping, here we -/// only translate CRLF to LF and produce errors on bare CR. -pub fn unescape_raw_str(literal_text: &str, callback: &mut F) -where - F: FnMut(Range, Result), -{ - unescape_raw_str_or_byte_str(literal_text, Mode::Str, callback) -} - -/// Takes a contents of a raw byte string literal (without quotes) and produces a -/// sequence of bytes or errors. -/// Values are returned through invoking of the provided callback. -/// NOTE: Raw strings do not perform any explicit character escaping, here we -/// only translate CRLF to LF and produce errors on bare CR. -pub fn unescape_raw_byte_str(literal_text: &str, callback: &mut F) -where - F: FnMut(Range, Result), -{ - unescape_raw_str_or_byte_str(literal_text, Mode::ByteStr, &mut |range, char| { - callback(range, char.map(byte_from_char)) - }) -} - /// What kind of literal do we parse. #[derive(Debug, Clone, Copy)] pub enum Mode { diff --git a/src/librustc_lexer/src/unescape/tests.rs b/src/librustc_lexer/src/unescape/tests.rs index e7b1ff6479d8..f2b751a78f27 100644 --- a/src/librustc_lexer/src/unescape/tests.rs +++ b/src/librustc_lexer/src/unescape/tests.rs @@ -102,7 +102,7 @@ fn test_unescape_char_good() { fn test_unescape_str_good() { fn check(literal_text: &str, expected: &str) { let mut buf = Ok(String::with_capacity(literal_text.len())); - unescape_str(literal_text, &mut |range, c| { + unescape_literal(literal_text, Mode::Str, &mut |range, c| { if let Ok(b) = &mut buf { match c { Ok(c) => b.push(c), @@ -222,7 +222,7 @@ fn test_unescape_byte_good() { fn test_unescape_byte_str_good() { fn check(literal_text: &str, expected: &[u8]) { let mut buf = Ok(Vec::with_capacity(literal_text.len())); - unescape_byte_str(literal_text, &mut |range, c| { + unescape_byte_literal(literal_text, Mode::ByteStr, &mut |range, c| { if let Ok(b) = &mut buf { match c { Ok(c) => b.push(c), @@ -246,7 +246,7 @@ fn test_unescape_byte_str_good() { fn test_unescape_raw_str() { fn check(literal: &str, expected: &[(Range, Result)]) { let mut unescaped = Vec::with_capacity(literal.len()); - unescape_raw_str(literal, &mut |range, res| unescaped.push((range, res))); + unescape_literal(literal, Mode::RawStr, &mut |range, res| unescaped.push((range, res))); assert_eq!(unescaped, expected); } @@ -258,7 +258,9 @@ fn test_unescape_raw_str() { fn test_unescape_raw_byte_str() { fn check(literal: &str, expected: &[(Range, Result)]) { let mut unescaped = Vec::with_capacity(literal.len()); - unescape_raw_byte_str(literal, &mut |range, res| unescaped.push((range, res))); + unescape_byte_literal(literal, Mode::RawByteStr, &mut |range, res| { + unescaped.push((range, res)) + }); assert_eq!(unescaped, expected); } diff --git a/src/tools/clippy/clippy_lints/src/write.rs b/src/tools/clippy/clippy_lints/src/write.rs index 5ad43ad55a36..26bf463bd292 100644 --- a/src/tools/clippy/clippy_lints/src/write.rs +++ b/src/tools/clippy/clippy_lints/src/write.rs @@ -483,8 +483,8 @@ fn check_newlines(fmtstr: &StrLit) -> bool { }; match fmtstr.style { - StrStyle::Cooked => unescape::unescape_str(contents, &mut cb), - StrStyle::Raw(_) => unescape::unescape_raw_str(contents, &mut cb), + StrStyle::Cooked => unescape::unescape_literal(contents, unescape::Mode::Str, &mut cb), + StrStyle::Raw(_) => unescape::unescape_literal(contents, unescape::Mode::RawStr, &mut cb), } should_lint From bb2ff593a63dc5500b0dd8d83cfa9bdca5768b79 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 13 May 2020 13:40:55 +0200 Subject: [PATCH 154/203] Clean up E0582 explanation --- src/librustc_error_codes/error_codes/E0582.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/librustc_error_codes/error_codes/E0582.md b/src/librustc_error_codes/error_codes/E0582.md index c0cf44852c4e..e50cc60ea330 100644 --- a/src/librustc_error_codes/error_codes/E0582.md +++ b/src/librustc_error_codes/error_codes/E0582.md @@ -1,5 +1,5 @@ -A lifetime appears only in an associated-type binding, -and not in the input types to the trait. +A lifetime is only present in an associated-type binding, and not in the input +types to the trait. Erroneous code example: From 5f93bc774b1c0b9c415c4989cb81e6b650711e7d Mon Sep 17 00:00:00 2001 From: Bastian Kauschke Date: Wed, 13 May 2020 14:46:15 +0200 Subject: [PATCH 155/203] use `require_lang_item` over `unwrap`. --- src/librustc_middle/ty/adjustment.rs | 7 ++++--- src/librustc_middle/ty/instance.rs | 4 ++-- src/librustc_middle/ty/layout.rs | 5 +++-- src/librustc_mir/borrow_check/type_check/mod.rs | 12 +++++++----- src/librustc_mir/monomorphize/collector.rs | 6 ++---- src/librustc_mir/shim.rs | 3 ++- src/librustc_mir/transform/generator.rs | 5 +++-- src/librustc_mir/util/elaborate_drops.rs | 7 +++---- src/librustc_mir_build/hair/pattern/const_to_pat.rs | 3 ++- src/librustc_trait_selection/traits/project.rs | 5 +++-- 10 files changed, 31 insertions(+), 26 deletions(-) diff --git a/src/librustc_middle/ty/adjustment.rs b/src/librustc_middle/ty/adjustment.rs index efd5adeba8c5..52ebcd63e7cd 100644 --- a/src/librustc_middle/ty/adjustment.rs +++ b/src/librustc_middle/ty/adjustment.rs @@ -2,6 +2,7 @@ use crate::ty::subst::SubstsRef; use crate::ty::{self, Ty, TyCtxt}; use rustc_hir as hir; use rustc_hir::def_id::DefId; +use rustc_hir::lang_items::{DerefMutTraitLangItem, DerefTraitLangItem}; use rustc_macros::HashStable; #[derive(Clone, Copy, Debug, PartialEq, Eq, RustcEncodable, RustcDecodable, HashStable)] @@ -117,11 +118,11 @@ pub struct OverloadedDeref<'tcx> { impl<'tcx> OverloadedDeref<'tcx> { pub fn method_call(&self, tcx: TyCtxt<'tcx>, source: Ty<'tcx>) -> (DefId, SubstsRef<'tcx>) { let trait_def_id = match self.mutbl { - hir::Mutability::Not => tcx.lang_items().deref_trait(), - hir::Mutability::Mut => tcx.lang_items().deref_mut_trait(), + hir::Mutability::Not => tcx.require_lang_item(DerefTraitLangItem, None), + hir::Mutability::Mut => tcx.require_lang_item(DerefMutTraitLangItem, None), }; let method_def_id = tcx - .associated_items(trait_def_id.unwrap()) + .associated_items(trait_def_id) .in_definition_order() .find(|m| m.kind == ty::AssocKind::Fn) .unwrap() diff --git a/src/librustc_middle/ty/instance.rs b/src/librustc_middle/ty/instance.rs index 88cc63a72857..1ce079821a22 100644 --- a/src/librustc_middle/ty/instance.rs +++ b/src/librustc_middle/ty/instance.rs @@ -4,7 +4,7 @@ use crate::ty::{self, SubstsRef, Ty, TyCtxt, TypeFoldable}; use rustc_errors::ErrorReported; use rustc_hir::def::Namespace; use rustc_hir::def_id::{CrateNum, DefId}; -use rustc_hir::lang_items::DropInPlaceFnLangItem; +use rustc_hir::lang_items::{DropInPlaceFnLangItem, FnOnceTraitLangItem}; use rustc_macros::HashStable; use std::fmt; @@ -375,7 +375,7 @@ impl<'tcx> Instance<'tcx> { substs: ty::SubstsRef<'tcx>, ) -> Instance<'tcx> { debug!("fn_once_adapter_shim({:?}, {:?})", closure_did, substs); - let fn_once = tcx.lang_items().fn_once_trait().unwrap(); + let fn_once = tcx.require_lang_item(FnOnceTraitLangItem, None); let call_once = tcx .associated_items(fn_once) .in_definition_order() diff --git a/src/librustc_middle/ty/layout.rs b/src/librustc_middle/ty/layout.rs index 7c4e4d095bc5..e1e47852dec9 100644 --- a/src/librustc_middle/ty/layout.rs +++ b/src/librustc_middle/ty/layout.rs @@ -8,6 +8,7 @@ use rustc_ast::ast::{self, IntTy, UintTy}; use rustc_attr as attr; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_hir as hir; +use rustc_hir::lang_items::{GeneratorStateLangItem, PinTypeLangItem}; use rustc_index::bit_set::BitSet; use rustc_index::vec::{Idx, IndexVec}; use rustc_session::{DataTypeKind, FieldInfo, SizeKind, VariantInfo}; @@ -2317,13 +2318,13 @@ impl<'tcx> ty::Instance<'tcx> { let env_region = ty::ReLateBound(ty::INNERMOST, ty::BrEnv); let env_ty = tcx.mk_mut_ref(tcx.mk_region(env_region), ty); - let pin_did = tcx.lang_items().pin_type().unwrap(); + let pin_did = tcx.require_lang_item(PinTypeLangItem, None); let pin_adt_ref = tcx.adt_def(pin_did); let pin_substs = tcx.intern_substs(&[env_ty.into()]); let env_ty = tcx.mk_adt(pin_adt_ref, pin_substs); sig.map_bound(|sig| { - let state_did = tcx.lang_items().gen_state().unwrap(); + let state_did = tcx.require_lang_item(GeneratorStateLangItem, None); let state_adt_ref = tcx.adt_def(state_did); let state_substs = tcx.intern_substs(&[ sig.yield_ty.into(), diff --git a/src/librustc_mir/borrow_check/type_check/mod.rs b/src/librustc_mir/borrow_check/type_check/mod.rs index 9282a0a06b48..059c241f9fe6 100644 --- a/src/librustc_mir/borrow_check/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/type_check/mod.rs @@ -10,6 +10,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_errors::struct_span_err; use rustc_hir as hir; use rustc_hir::def_id::{DefId, LocalDefId}; +use rustc_hir::lang_items::{CoerceUnsizedTraitLangItem, CopyTraitLangItem, SizedTraitLangItem}; use rustc_index::vec::{Idx, IndexVec}; use rustc_infer::infer::canonical::QueryRegionConstraints; use rustc_infer::infer::outlives::env::RegionBoundPairs; @@ -502,7 +503,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { if let PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy) = context { let tcx = self.tcx(); let trait_ref = ty::TraitRef { - def_id: tcx.lang_items().copy_trait().unwrap(), + def_id: tcx.require_lang_item(CopyTraitLangItem, None), substs: tcx.mk_substs_trait(place_ty.ty, &[]), }; @@ -1468,7 +1469,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { self.check_rvalue(body, rv, location); if !self.tcx().features().unsized_locals { let trait_ref = ty::TraitRef { - def_id: tcx.lang_items().sized_trait().unwrap(), + def_id: tcx.require_lang_item(SizedTraitLangItem, None), substs: tcx.mk_substs_trait(place_ty, &[]), }; self.prove_trait_ref( @@ -2013,7 +2014,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { ty::Predicate::Trait( ty::Binder::bind(ty::TraitPredicate { trait_ref: ty::TraitRef::new( - self.tcx().lang_items().copy_trait().unwrap(), + self.tcx() + .require_lang_item(CopyTraitLangItem, None), tcx.mk_substs_trait(ty, &[]), ), }), @@ -2037,7 +2039,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { } let trait_ref = ty::TraitRef { - def_id: tcx.lang_items().sized_trait().unwrap(), + def_id: tcx.require_lang_item(SizedTraitLangItem, None), substs: tcx.mk_substs_trait(ty, &[]), }; @@ -2135,7 +2137,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { CastKind::Pointer(PointerCast::Unsize) => { let &ty = ty; let trait_ref = ty::TraitRef { - def_id: tcx.lang_items().coerce_unsized_trait().unwrap(), + def_id: tcx.require_lang_item(CoerceUnsizedTraitLangItem, None), substs: tcx.mk_substs_trait(op.ty(body, tcx), &[ty.into()]), }; diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs index 4648100e3b70..a8094990594f 100644 --- a/src/librustc_mir/monomorphize/collector.rs +++ b/src/librustc_mir/monomorphize/collector.rs @@ -580,10 +580,8 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> { } mir::Rvalue::NullaryOp(mir::NullOp::Box, _) => { let tcx = self.tcx; - let exchange_malloc_fn_def_id = tcx - .lang_items() - .require(ExchangeMallocFnLangItem) - .unwrap_or_else(|e| tcx.sess.fatal(&e)); + let exchange_malloc_fn_def_id = + tcx.require_lang_item(ExchangeMallocFnLangItem, None); let instance = Instance::mono(tcx, exchange_malloc_fn_def_id); if should_monomorphize_locally(tcx, &instance) { self.output.push(create_fn_mono_item(instance)); diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs index 847f59b95e95..d025468d28bf 100644 --- a/src/librustc_mir/shim.rs +++ b/src/librustc_mir/shim.rs @@ -1,5 +1,6 @@ use rustc_hir as hir; use rustc_hir::def_id::DefId; +use rustc_hir::lang_items::FnMutTraitLangItem; use rustc_middle::mir::*; use rustc_middle::ty::query::Providers; use rustc_middle::ty::subst::{InternalSubsts, Subst}; @@ -70,7 +71,7 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> Body<' build_call_shim(tcx, instance, None, CallKind::Direct(def_id), None) } ty::InstanceDef::ClosureOnceShim { call_once: _ } => { - let fn_mut = tcx.lang_items().fn_mut_trait().unwrap(); + let fn_mut = tcx.require_lang_item(FnMutTraitLangItem, None); let call_mut = tcx .associated_items(fn_mut) .in_definition_order() diff --git a/src/librustc_mir/transform/generator.rs b/src/librustc_mir/transform/generator.rs index bfc872be653a..1f1f74beb4b8 100644 --- a/src/librustc_mir/transform/generator.rs +++ b/src/librustc_mir/transform/generator.rs @@ -61,6 +61,7 @@ use crate::util::storage; use rustc_data_structures::fx::FxHashMap; use rustc_hir as hir; use rustc_hir::def_id::DefId; +use rustc_hir::lang_items::{GeneratorStateLangItem, PinTypeLangItem}; use rustc_index::bit_set::{BitMatrix, BitSet}; use rustc_index::vec::{Idx, IndexVec}; use rustc_middle::mir::visit::{MutVisitor, PlaceContext}; @@ -381,7 +382,7 @@ fn make_generator_state_argument_indirect<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Bo fn make_generator_state_argument_pinned<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { let ref_gen_ty = body.local_decls.raw[1].ty; - let pin_did = tcx.lang_items().pin_type().unwrap(); + let pin_did = tcx.require_lang_item(PinTypeLangItem, None); let pin_adt_ref = tcx.adt_def(pin_did); let substs = tcx.intern_substs(&[ref_gen_ty.into()]); let pin_ref_gen_ty = tcx.mk_adt(pin_adt_ref, substs); @@ -1207,7 +1208,7 @@ impl<'tcx> MirPass<'tcx> for StateTransform { }; // Compute GeneratorState - let state_did = tcx.lang_items().gen_state().unwrap(); + let state_did = tcx.require_lang_item(GeneratorStateLangItem, None); let state_adt_ref = tcx.adt_def(state_did); let state_substs = tcx.intern_substs(&[yield_ty.into(), body.return_ty().into()]); let ret_ty = tcx.mk_adt(state_adt_ref, state_substs); diff --git a/src/librustc_mir/util/elaborate_drops.rs b/src/librustc_mir/util/elaborate_drops.rs index 2d7d3a0ccae1..af7c88b178d3 100644 --- a/src/librustc_mir/util/elaborate_drops.rs +++ b/src/librustc_mir/util/elaborate_drops.rs @@ -1,6 +1,6 @@ use crate::util::patch::MirPatch; use rustc_hir as hir; -use rustc_hir::lang_items; +use rustc_hir::lang_items::{BoxFreeFnLangItem, DropTraitLangItem}; use rustc_index::vec::Idx; use rustc_middle::mir::*; use rustc_middle::traits::Reveal; @@ -535,7 +535,7 @@ where fn destructor_call_block(&mut self, (succ, unwind): (BasicBlock, Unwind)) -> BasicBlock { debug!("destructor_call_block({:?}, {:?})", self, succ); let tcx = self.tcx(); - let drop_trait = tcx.lang_items().drop_trait().unwrap(); + let drop_trait = tcx.require_lang_item(DropTraitLangItem, None); let drop_fn = tcx.associated_items(drop_trait).in_definition_order().next().unwrap(); let ty = self.place_ty(self.place); let substs = tcx.mk_substs_trait(ty, &[]); @@ -877,8 +877,7 @@ where ) -> BasicBlock { let tcx = self.tcx(); let unit_temp = Place::from(self.new_temp(tcx.mk_unit())); - let free_func = - tcx.require_lang_item(lang_items::BoxFreeFnLangItem, Some(self.source_info.span)); + let free_func = tcx.require_lang_item(BoxFreeFnLangItem, Some(self.source_info.span)); let args = adt.variants[VariantIdx::new(0)] .fields .iter() diff --git a/src/librustc_mir_build/hair/pattern/const_to_pat.rs b/src/librustc_mir_build/hair/pattern/const_to_pat.rs index 854f8eeaf344..d3129751586a 100644 --- a/src/librustc_mir_build/hair/pattern/const_to_pat.rs +++ b/src/librustc_mir_build/hair/pattern/const_to_pat.rs @@ -1,4 +1,5 @@ use rustc_hir as hir; +use rustc_hir::lang_items::EqTraitLangItem; use rustc_index::vec::Idx; use rustc_infer::infer::{InferCtxt, TyCtxtInferExt}; use rustc_middle::mir::Field; @@ -140,7 +141,7 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> { // code at the moment, because types like `for <'a> fn(&'a ())` do // not *yet* implement `PartialEq`. So for now we leave this here. let ty_is_partial_eq: bool = { - let partial_eq_trait_id = self.tcx().lang_items().eq_trait().unwrap(); + let partial_eq_trait_id = self.tcx().require_lang_item(EqTraitLangItem, None); let obligation: PredicateObligation<'_> = predicate_for_trait_def( self.tcx(), self.param_env, diff --git a/src/librustc_trait_selection/traits/project.rs b/src/librustc_trait_selection/traits/project.rs index 47df82690e07..0779882b6dd5 100644 --- a/src/librustc_trait_selection/traits/project.rs +++ b/src/librustc_trait_selection/traits/project.rs @@ -20,6 +20,7 @@ use crate::traits::error_reporting::InferCtxtExt; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_errors::ErrorReported; use rustc_hir::def_id::DefId; +use rustc_hir::lang_items::{FnOnceTraitLangItem, GeneratorTraitLangItem}; use rustc_middle::ty::fold::{TypeFoldable, TypeFolder}; use rustc_middle::ty::subst::{InternalSubsts, Subst}; use rustc_middle::ty::{self, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, WithConstness}; @@ -1222,7 +1223,7 @@ fn confirm_generator_candidate<'cx, 'tcx>( let tcx = selcx.tcx(); - let gen_def_id = tcx.lang_items().gen_trait().unwrap(); + let gen_def_id = tcx.require_lang_item(GeneratorTraitLangItem, None); let predicate = super::util::generator_trait_ref_and_outputs( tcx, @@ -1309,7 +1310,7 @@ fn confirm_callable_candidate<'cx, 'tcx>( debug!("confirm_callable_candidate({:?},{:?})", obligation, fn_sig); // the `Output` associated type is declared on `FnOnce` - let fn_once_def_id = tcx.lang_items().fn_once_trait().unwrap(); + let fn_once_def_id = tcx.require_lang_item(FnOnceTraitLangItem, None); let predicate = super::util::closure_trait_ref_and_return_type( tcx, From 46e9cbea3a65aff70c838ebbd157d715ee84718b Mon Sep 17 00:00:00 2001 From: Faris Sufyan <47665123+Dolpheyn@users.noreply.github.com> Date: Wed, 13 May 2020 21:04:52 +0800 Subject: [PATCH 156/203] Update src/libcore/option.rs Co-authored-by: Steve Klabnik --- src/libcore/option.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcore/option.rs b/src/libcore/option.rs index 4df9eaa48156..542115763c24 100644 --- a/src/libcore/option.rs +++ b/src/libcore/option.rs @@ -1357,7 +1357,7 @@ impl<'a, T> IntoIterator for &'a mut Option { #[stable(since = "1.12.0", feature = "option_from")] impl From for Option { - /// Copies val to a new Option::Some + /// Copies `val` into a new `Some`. /// /// # Examples /// From 4588c26e53a39f0379a0f25ace4228bc207f4a73 Mon Sep 17 00:00:00 2001 From: Faris Sufyan <47665123+Dolpheyn@users.noreply.github.com> Date: Wed, 13 May 2020 21:05:53 +0800 Subject: [PATCH 157/203] Update src/libcore/option.rs Co-authored-by: Steve Klabnik --- src/libcore/option.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libcore/option.rs b/src/libcore/option.rs index 542115763c24..515040dd4cca 100644 --- a/src/libcore/option.rs +++ b/src/libcore/option.rs @@ -1363,6 +1363,7 @@ impl From for Option { /// /// ``` /// let o: Option = Option::from(67); + /// /// assert_eq!(Some(67), o); /// ``` fn from(val: T) -> Option { From a9e7d572380c271848f1137f39ef09257144bd37 Mon Sep 17 00:00:00 2001 From: Faris Sufyan <47665123+Dolpheyn@users.noreply.github.com> Date: Wed, 13 May 2020 21:12:35 +0800 Subject: [PATCH 158/203] Update src/libcore/option.rs Co-authored-by: Steve Klabnik --- src/libcore/option.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcore/option.rs b/src/libcore/option.rs index 515040dd4cca..3e64177a4676 100644 --- a/src/libcore/option.rs +++ b/src/libcore/option.rs @@ -1373,7 +1373,7 @@ impl From for Option { #[stable(feature = "option_ref_from_ref_option", since = "1.30.0")] impl<'a, T> From<&'a Option> for Option<&'a T> { - /// Converts from &Option to Option<&T> + /// Converts from `&Option` to `Option<&T>`. /// /// # Examples /// Converts an `Option<`[`String`]`>` into an `Option<`[`usize`]`>`, preserving the original. From 644bb24e335bd15c7c90a2c31afa63d9ba5f5dbc Mon Sep 17 00:00:00 2001 From: Faris Sufyan <47665123+Dolpheyn@users.noreply.github.com> Date: Wed, 13 May 2020 21:12:50 +0800 Subject: [PATCH 159/203] Update src/libcore/option.rs Co-authored-by: Steve Klabnik --- src/libcore/option.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libcore/option.rs b/src/libcore/option.rs index 3e64177a4676..848560bd795d 100644 --- a/src/libcore/option.rs +++ b/src/libcore/option.rs @@ -1405,6 +1405,7 @@ impl<'a, T> From<&'a mut Option> for Option<&'a mut T> { /// ``` /// let mut s = Some(String::from("Hello")); /// let o: Option<&mut String> = Option::from(&mut s); + /// /// match o { /// Some(t) => *t = String::from("Hello, Rustaceans!"), /// None => (), From adc2bf0cfe3f4c6611ebcd80b570ed8ebd76b548 Mon Sep 17 00:00:00 2001 From: Faris Sufyan <47665123+Dolpheyn@users.noreply.github.com> Date: Wed, 13 May 2020 21:13:08 +0800 Subject: [PATCH 160/203] Update src/libcore/option.rs Co-authored-by: Steve Klabnik --- src/libcore/option.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libcore/option.rs b/src/libcore/option.rs index 848560bd795d..340637a55f7e 100644 --- a/src/libcore/option.rs +++ b/src/libcore/option.rs @@ -1376,6 +1376,7 @@ impl<'a, T> From<&'a Option> for Option<&'a T> { /// Converts from `&Option` to `Option<&T>`. /// /// # Examples + /// /// Converts an `Option<`[`String`]`>` into an `Option<`[`usize`]`>`, preserving the original. /// The [`map`] method takes the `self` argument by value, consuming the original, /// so this technique uses `as_ref` to first take an `Option` to a reference From f445a8286e4d889ac33935768f2ac0823b2c01ba Mon Sep 17 00:00:00 2001 From: Faris Sufyan <47665123+Dolpheyn@users.noreply.github.com> Date: Wed, 13 May 2020 21:13:17 +0800 Subject: [PATCH 161/203] Update src/libcore/option.rs Co-authored-by: Steve Klabnik --- src/libcore/option.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcore/option.rs b/src/libcore/option.rs index 340637a55f7e..a6a8d4bd7e17 100644 --- a/src/libcore/option.rs +++ b/src/libcore/option.rs @@ -1399,7 +1399,7 @@ impl<'a, T> From<&'a Option> for Option<&'a T> { #[stable(feature = "option_ref_from_ref_option", since = "1.30.0")] impl<'a, T> From<&'a mut Option> for Option<&'a mut T> { - /// Converts from &mut Option to Option<&mut T> + /// Converts from `&mut Option` to `Option<&mut T>` /// /// # Examples /// From ef1688db8e33b635287462854b7203f86c7acbf5 Mon Sep 17 00:00:00 2001 From: Faris Sufyan <47665123+Dolpheyn@users.noreply.github.com> Date: Wed, 13 May 2020 21:13:27 +0800 Subject: [PATCH 162/203] Update src/libcore/option.rs Co-authored-by: Steve Klabnik --- src/libcore/option.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libcore/option.rs b/src/libcore/option.rs index a6a8d4bd7e17..ebaa48948625 100644 --- a/src/libcore/option.rs +++ b/src/libcore/option.rs @@ -1411,6 +1411,7 @@ impl<'a, T> From<&'a mut Option> for Option<&'a mut T> { /// Some(t) => *t = String::from("Hello, Rustaceans!"), /// None => (), /// } + /// /// assert_eq!(s, Some(String::from("Hello, Rustaceans!"))); /// ``` fn from(o: &'a mut Option) -> Option<&'a mut T> { From 6c3856f3ec5bbcd1c748d01a463f04a8fef0bd6c Mon Sep 17 00:00:00 2001 From: Faris Sufyan <47665123+Dolpheyn@users.noreply.github.com> Date: Wed, 13 May 2020 21:13:35 +0800 Subject: [PATCH 163/203] Update src/libcore/option.rs Co-authored-by: Steve Klabnik --- src/libcore/option.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/libcore/option.rs b/src/libcore/option.rs index ebaa48948625..e8483875c97e 100644 --- a/src/libcore/option.rs +++ b/src/libcore/option.rs @@ -1389,7 +1389,9 @@ impl<'a, T> From<&'a Option> for Option<&'a T> { /// ``` /// let s: Option = Some(String::from("Hello, Rustaceans!")); /// let o: Option = Option::from(&s).map(|ss: &String| ss.len()); + /// /// println!("Can still print s: {:?}", s); + /// /// assert_eq!(o, Some(18)); /// ``` fn from(o: &'a Option) -> Option<&'a T> { From 2b42a2b541e04164428e83a4adfc4c120a482f82 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Wed, 13 May 2020 11:32:43 -0400 Subject: [PATCH 164/203] Forbid stage arguments to check Users generally expect that check builds are fast, and that's only true in stage 0 (stages beyond that need us to build a compiler, which is slow). --- src/bootstrap/flags.rs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/bootstrap/flags.rs b/src/bootstrap/flags.rs index fb380af0a47e..646b9e05d99c 100644 --- a/src/bootstrap/flags.rs +++ b/src/bootstrap/flags.rs @@ -503,6 +503,20 @@ Arguments: } }; + if let Subcommand::Check { .. } = &cmd { + if matches.opt_str("stage").is_some() { + println!("{}", "--stage not supported for x.py check, always treated as stage 0"); + process::exit(1); + } + if matches.opt_str("keep-stage").is_some() { + println!( + "{}", + "--keep-stage not supported for x.py check, only one stage available" + ); + process::exit(1); + } + } + Flags { verbose: matches.opt_count("verbose"), stage: matches.opt_str("stage").map(|j| j.parse().expect("`stage` should be a number")), From 617c7cd9fa9751375abbf1a43cfe29ffc19ee92b Mon Sep 17 00:00:00 2001 From: Tymoteusz Jankowski Date: Wed, 13 May 2020 16:54:16 +0200 Subject: [PATCH 165/203] Make intra links work inside trait impl block --- .../passes/collect_intra_doc_links.rs | 66 +++++++++++++++---- src/test/rustdoc/intra-link-trait-impl.rs | 35 ++++++++++ 2 files changed, 90 insertions(+), 11 deletions(-) create mode 100644 src/test/rustdoc/intra-link-trait-impl.rs diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index fbdb538cd874..a3ef350a0487 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -12,7 +12,8 @@ use rustc_hir::def_id::DefId; use rustc_middle::ty; use rustc_resolve::ParentScope; use rustc_session::lint; -use rustc_span::symbol::{Ident, Symbol}; +use rustc_span::symbol::Ident; +use rustc_span::symbol::Symbol; use rustc_span::DUMMY_SP; use std::ops::Range; @@ -130,6 +131,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> { current_item: &Option, parent_id: Option, extra_fragment: &Option, + item_opt: Option<&Item>, ) -> Result<(Res, Option), ErrorKind> { let cx = self.cx; @@ -230,16 +232,44 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> { DefKind::Struct | DefKind::Union | DefKind::Enum | DefKind::TyAlias, did, ) => { - let item = cx - .tcx - .inherent_impls(did) - .iter() - .flat_map(|imp| cx.tcx.associated_items(*imp).in_definition_order()) - .find(|item| item.ident.name == item_name); + // We need item's parent to know if it's + // trait impl or struct/enum/etc impl + let item_parent = item_opt + .and_then(|item| self.cx.as_local_hir_id(item.def_id)) + .and_then(|item_hir| { + let parent_hir = self.cx.tcx.hir().get_parent_item(item_hir); + self.cx.tcx.hir().find(parent_hir) + }); + let item = match item_parent { + Some(hir::Node::Item(hir::Item { + kind: hir::ItemKind::Impl { of_trait: Some(_), self_ty, .. }, + .. + })) => { + // trait impl + cx.tcx + .associated_item_def_ids(self_ty.hir_id.owner) + .iter() + .map(|child| { + let associated_item = cx.tcx.associated_item(*child); + associated_item + }) + .find(|child| child.ident.name == item_name) + } + _ => { + // struct/enum/etc. impl + cx.tcx + .inherent_impls(did) + .iter() + .flat_map(|imp| cx.tcx.associated_items(*imp).in_definition_order()) + .find(|item| item.ident.name == item_name) + } + }; + if let Some(item) = item { let out = match item.kind { ty::AssocKind::Fn if ns == ValueNS => "method", ty::AssocKind::Const if ns == ValueNS => "associatedconstant", + ty::AssocKind::Type if ns == ValueNS => "associatedtype", _ => return self.variant_field(path_str, current_item, module_id), }; if extra_fragment.is_some() { @@ -484,8 +514,14 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> { match kind { Some(ns @ ValueNS) => { - match self.resolve(path_str, ns, ¤t_item, base_node, &extra_fragment) - { + match self.resolve( + path_str, + ns, + ¤t_item, + base_node, + &extra_fragment, + None, + ) { Ok(res) => res, Err(ErrorKind::ResolutionFailure) => { resolution_failure(cx, &item, path_str, &dox, link_range); @@ -501,8 +537,14 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> { } } Some(ns @ TypeNS) => { - match self.resolve(path_str, ns, ¤t_item, base_node, &extra_fragment) - { + match self.resolve( + path_str, + ns, + ¤t_item, + base_node, + &extra_fragment, + None, + ) { Ok(res) => res, Err(ErrorKind::ResolutionFailure) => { resolution_failure(cx, &item, path_str, &dox, link_range); @@ -526,6 +568,7 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> { ¤t_item, base_node, &extra_fragment, + None, ) { Err(ErrorKind::AnchorFailure(msg)) => { anchor_failure(cx, &item, &ori_link, &dox, link_range, msg); @@ -539,6 +582,7 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> { ¤t_item, base_node, &extra_fragment, + Some(&item), ) { Err(ErrorKind::AnchorFailure(msg)) => { anchor_failure(cx, &item, &ori_link, &dox, link_range, msg); diff --git a/src/test/rustdoc/intra-link-trait-impl.rs b/src/test/rustdoc/intra-link-trait-impl.rs new file mode 100644 index 000000000000..fab8406d525e --- /dev/null +++ b/src/test/rustdoc/intra-link-trait-impl.rs @@ -0,0 +1,35 @@ +#![crate_name = "foo"] + +// ignore-tidy-linelength + +pub struct MyStruct; + +impl MyTrait for MyStruct { + +// @has foo/struct.MyStruct.html '//a/@href' '../foo/struct.MyStruct.html#associatedtype.AssoType' + + /// [`AssoType`] + /// + /// [`AssoType`]: MyStruct::AssoType + type AssoType = u32; + +// @has foo/struct.MyStruct.html '//a/@href' '../foo/struct.MyStruct.html#associatedconstant.ASSO_CONST' + + /// [`ASSO_CONST`] + /// + /// [`ASSO_CONST`]: MyStruct::ASSO_CONST + const ASSO_CONST: i32 = 10; + +// @has foo/struct.MyStruct.html '//a/@href' '../foo/struct.MyStruct.html#method.trait_fn' + + /// [`trait_fn`] + /// + /// [`trait_fn`]: MyStruct::trait_fn + fn trait_fn() { } +} + +pub trait MyTrait { + type AssoType; + const ASSO_CONST: i32 = 1; + fn trait_fn(); +} From cef616b1dc1b3e0aa846fd8325ab8dde94de12d5 Mon Sep 17 00:00:00 2001 From: CAD97 Date: Wed, 13 May 2020 14:49:45 -0400 Subject: [PATCH 166/203] Improve comments in iter::Step --- src/libcore/iter/range.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libcore/iter/range.rs b/src/libcore/iter/range.rs index 1b0968939026..9e54e69bc552 100644 --- a/src/libcore/iter/range.rs +++ b/src/libcore/iter/range.rs @@ -15,7 +15,7 @@ use super::{FusedIterator, TrustedLen}; /// This trait is `unsafe` because its implementation must be correct for /// the safety of `unsafe trait TrustedLen` implementations, and the results /// of using this trait can otherwise be trusted by `unsafe` code to be correct -/// and fulful the listed obligations. +/// and fulfill the listed obligations. #[unstable(feature = "step_trait", reason = "recently redesigned", issue = "42168")] pub unsafe trait Step: Clone + PartialOrd + Sized { /// Returns the number of *successor* steps required to get from `start` to `end`. @@ -27,8 +27,8 @@ pub unsafe trait Step: Clone + PartialOrd + Sized { /// /// For any `a`, `b`, and `n`: /// - /// * `steps_between(&a, &b) == Some(n)` if and only if `Step::forward(&a, n) == Some(b)` - /// * `steps_between(&a, &b) == Some(n)` if and only if `Step::backward(&a, n) == Some(a)` + /// * `steps_between(&a, &b) == Some(n)` if and only if `Step::forward_checked(&a, n) == Some(b)` + /// * `steps_between(&a, &b) == Some(n)` if and only if `Step::backward_checked(&a, n) == Some(a)` /// * `steps_between(&a, &b) == Some(n)` only if `a <= b` /// * Corollary: `steps_between(&a, &b) == Some(0)` if and only if `a == b` /// * Note that `a <= b` does _not_ imply `steps_between(&a, &b) != None`; From 9001a6429969be2732f0f0b650f193faeade89e7 Mon Sep 17 00:00:00 2001 From: Bastian Kauschke Date: Wed, 13 May 2020 21:38:58 +0200 Subject: [PATCH 167/203] add spans to `require_lang_items` --- src/librustc_mir/borrow_check/type_check/mod.rs | 17 +++++++++++------ src/librustc_mir/transform/generator.rs | 2 +- src/librustc_typeck/check/demand.rs | 3 ++- 3 files changed, 14 insertions(+), 8 deletions(-) diff --git a/src/librustc_mir/borrow_check/type_check/mod.rs b/src/librustc_mir/borrow_check/type_check/mod.rs index 059c241f9fe6..bad176c603f3 100644 --- a/src/librustc_mir/borrow_check/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/type_check/mod.rs @@ -503,7 +503,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { if let PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy) = context { let tcx = self.tcx(); let trait_ref = ty::TraitRef { - def_id: tcx.require_lang_item(CopyTraitLangItem, None), + def_id: tcx.require_lang_item(CopyTraitLangItem, Some(self.last_span)), substs: tcx.mk_substs_trait(place_ty.ty, &[]), }; @@ -1469,7 +1469,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { self.check_rvalue(body, rv, location); if !self.tcx().features().unsized_locals { let trait_ref = ty::TraitRef { - def_id: tcx.require_lang_item(SizedTraitLangItem, None), + def_id: tcx.require_lang_item(SizedTraitLangItem, Some(self.last_span)), substs: tcx.mk_substs_trait(place_ty, &[]), }; self.prove_trait_ref( @@ -2014,8 +2014,10 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { ty::Predicate::Trait( ty::Binder::bind(ty::TraitPredicate { trait_ref: ty::TraitRef::new( - self.tcx() - .require_lang_item(CopyTraitLangItem, None), + self.tcx().require_lang_item( + CopyTraitLangItem, + Some(self.last_span), + ), tcx.mk_substs_trait(ty, &[]), ), }), @@ -2039,7 +2041,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { } let trait_ref = ty::TraitRef { - def_id: tcx.require_lang_item(SizedTraitLangItem, None), + def_id: tcx.require_lang_item(SizedTraitLangItem, Some(self.last_span)), substs: tcx.mk_substs_trait(ty, &[]), }; @@ -2137,7 +2139,10 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { CastKind::Pointer(PointerCast::Unsize) => { let &ty = ty; let trait_ref = ty::TraitRef { - def_id: tcx.require_lang_item(CoerceUnsizedTraitLangItem, None), + def_id: tcx.require_lang_item( + CoerceUnsizedTraitLangItem, + Some(self.last_span), + ), substs: tcx.mk_substs_trait(op.ty(body, tcx), &[ty.into()]), }; diff --git a/src/librustc_mir/transform/generator.rs b/src/librustc_mir/transform/generator.rs index 1f1f74beb4b8..14faa5be02f4 100644 --- a/src/librustc_mir/transform/generator.rs +++ b/src/librustc_mir/transform/generator.rs @@ -382,7 +382,7 @@ fn make_generator_state_argument_indirect<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Bo fn make_generator_state_argument_pinned<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { let ref_gen_ty = body.local_decls.raw[1].ty; - let pin_did = tcx.require_lang_item(PinTypeLangItem, None); + let pin_did = tcx.require_lang_item(PinTypeLangItem, Some(body.span)); let pin_adt_ref = tcx.adt_def(pin_did); let substs = tcx.intern_substs(&[ref_gen_ty.into()]); let pin_ref_gen_ty = tcx.mk_adt(pin_adt_ref, substs); diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs index 8ae5ee4c3f97..bff1e727fe36 100644 --- a/src/librustc_typeck/check/demand.rs +++ b/src/librustc_typeck/check/demand.rs @@ -7,6 +7,7 @@ use rustc_trait_selection::traits::{self, ObligationCause}; use rustc_ast::util::parser::PREC_POSTFIX; use rustc_errors::{Applicability, DiagnosticBuilder}; use rustc_hir as hir; +use rustc_hir::lang_items::DerefTraitLangItem; use rustc_hir::{is_range_literal, Node}; use rustc_middle::ty::adjustment::AllowTwoPhase; use rustc_middle::ty::{self, AssocItem, Ty, TypeAndMut}; @@ -634,7 +635,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { _ if sp == expr.span && !is_macro => { // Check for `Deref` implementations by constructing a predicate to // prove: `::Output == U` - let deref_trait = self.tcx.lang_items().deref_trait().unwrap(); + let deref_trait = self.tcx.require_lang_item(DerefTraitLangItem, Some(expr.span)); let item_def_id = self .tcx .associated_items(deref_trait) From e44f87fca30186b6dd34932a8532d4e52b9b88fe Mon Sep 17 00:00:00 2001 From: Tshepang Lekhonkhobe Date: Wed, 13 May 2020 23:02:56 +0200 Subject: [PATCH 168/203] docs: fix link source https://github.com/rust-lang/rust/pull/72163#issuecomment-628234966 --- src/librustc_mir_build/build/scope.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_mir_build/build/scope.rs b/src/librustc_mir_build/build/scope.rs index 710a41bc8fdb..19b983018c95 100644 --- a/src/librustc_mir_build/build/scope.rs +++ b/src/librustc_mir_build/build/scope.rs @@ -223,7 +223,7 @@ impl Scope { } } -/// A trait that determined how [DropTree::lower_to_mir] creates its blocks and +/// A trait that determined how [DropTree::build_mir] creates its blocks and /// links to any entry nodes. trait DropTreeBuilder<'tcx> { /// Create a new block for the tree. This should call either From 90b196129b85b5b2ae795e9bd621b95d7bec17b4 Mon Sep 17 00:00:00 2001 From: CAD97 Date: Wed, 13 May 2020 17:57:06 -0400 Subject: [PATCH 169/203] Improve Step::forward/backward for optimization The previous definition did not optimize down to a single add operation, but this version does appear to. --- src/libcore/iter/range.rs | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/src/libcore/iter/range.rs b/src/libcore/iter/range.rs index 9e54e69bc552..7a08d6d1ff37 100644 --- a/src/libcore/iter/range.rs +++ b/src/libcore/iter/range.rs @@ -202,26 +202,24 @@ macro_rules! step_identical_methods { #[inline] fn forward(start: Self, n: usize) -> Self { - match Self::forward_checked(start, n) { - Some(result) => result, - None => { - let result = Add::add(start, n as Self); - // add one modular cycle to ensure overflow occurs - Add::add(Add::add(result as $u, $u::MAX), 1) as Self - } + // In debug builds, trigger a panic on overflow. + // This should optimize completely out in release builds. + if Self::forward_checked(start, n).is_none() { + let _ = Add::add(Self::MAX, 1); } + // Do wrapping math to allow e.g. `Step::forward(-128u8, 255)`. + start.wrapping_add(n as Self) as Self } #[inline] fn backward(start: Self, n: usize) -> Self { - match Self::backward_checked(start, n) { - Some(result) => result, - None => { - let result = Sub::sub(start, n as Self); - // sub one modular cycle to ensure overflow occurs - Sub::sub(Sub::sub(result as $u, $u::MAX), 1) as Self - } + // In debug builds, trigger a panic on overflow. + // This should optimize completely out in release builds. + if Self::backward_checked(start, n).is_none() { + let _ = Sub::sub(Self::MIN, 1); } + // Do wrapping math to allow e.g. `Step::backward(127u8, 255)`. + start.wrapping_sub(n as Self) as Self } }; } From dab3a5813e2590b2161d84a410e4d5bdc072152d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= Date: Thu, 14 May 2020 00:00:00 +0000 Subject: [PATCH 170/203] Fix Arc::decr_strong_count doc test --- src/liballoc/sync.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/liballoc/sync.rs b/src/liballoc/sync.rs index 19d289c87fd9..dbee9d27d8ac 100644 --- a/src/liballoc/sync.rs +++ b/src/liballoc/sync.rs @@ -835,12 +835,14 @@ impl Arc { /// /// unsafe { /// let ptr = Arc::into_raw(five); - /// Arc::decr_strong_count(ptr); + /// Arc::incr_strong_count(ptr); /// - /// // This assertion is deterministic because we haven't shared + /// // Those assertions are deterministic because we haven't shared /// // the `Arc` between threads. /// let five = Arc::from_raw(ptr); - /// assert_eq!(0, Arc::strong_count(&five)); + /// assert_eq!(2, Arc::strong_count(&five)); + /// Arc::decr_strong_count(ptr); + /// assert_eq!(1, Arc::strong_count(&five)); /// } /// ``` #[inline] From 883c177abb216fcef5b2d2369970394b0967f302 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 4 May 2020 15:26:17 +0200 Subject: [PATCH 171/203] Move doc alias discovery into the Attributes struct and some code improvements --- src/librustdoc/clean/types.rs | 9 +++++++ src/librustdoc/html/render.rs | 2 +- src/librustdoc/html/render/cache.rs | 41 +++-------------------------- src/librustdoc/html/static/main.js | 2 +- 4 files changed, 15 insertions(+), 39 deletions(-) diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 0a682857b182..cd767802714b 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -643,6 +643,15 @@ impl Attributes { }) .collect() } + + pub fn get_doc_aliases(&self) -> FxHashSet { + self.other_attrs + .lists(sym::doc) + .filter(|a| a.check_name(sym::alias)) + .filter_map(|a| a.value_str().map(|s| s.to_string().replace("\"", ""))) + .filter(|v| !v.is_empty()) + .collect::>() + } } impl PartialEq for Attributes { diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 9454baf76409..abca8ab778cc 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -278,7 +278,7 @@ pub struct RenderInfo { /// Struct representing one entry in the JS search index. These are all emitted /// by hand to a large JS file at the end of cache-creation. #[derive(Debug)] -pub struct IndexItem { +struct IndexItem { ty: ItemType, name: String, path: String, diff --git a/src/librustdoc/html/render/cache.rs b/src/librustdoc/html/render/cache.rs index 53cf1abb16d5..b8d97c2ac503 100644 --- a/src/librustdoc/html/render/cache.rs +++ b/src/librustdoc/html/render/cache.rs @@ -328,15 +328,7 @@ impl DocFolder for Cache { search_type: get_index_search_type(&item), }); - for alias in item - .attrs - .lists(sym::doc) - .filter(|a| a.check_name(sym::alias)) - .filter_map(|a| a.value_str().map(|s| s.to_string().replace("\"", ""))) - .filter(|v| !v.is_empty()) - .collect::>() - .into_iter() - { + for alias in item.attrs.get_doc_aliases() { self.aliases .entry(alias.to_lowercase()) .or_insert(Vec::with_capacity(1)) @@ -378,9 +370,6 @@ impl DocFolder for Cache { | clean::MacroItem(..) | clean::ProcMacroItem(..) | clean::VariantItem(..) - | clean::StructFieldItem(..) - | clean::TyMethodItem(..) - | clean::MethodItem(..) if !self.stripped_mod => { // Re-exported items mean that the same id can show up twice @@ -564,15 +553,7 @@ fn build_index(krate: &clean::Crate, cache: &mut Cache) -> String { parent_idx: None, search_type: get_index_search_type(&item), }); - for alias in item - .attrs - .lists(sym::doc) - .filter(|a| a.check_name(sym::alias)) - .filter_map(|a| a.value_str().map(|s| s.to_string().replace("\"", ""))) - .filter(|v| !v.is_empty()) - .collect::>() - .into_iter() - { + for alias in item.attrs.get_doc_aliases().into_iter() { aliases .entry(alias.to_lowercase()) .or_insert(Vec::with_capacity(1)) @@ -619,22 +600,8 @@ fn build_index(krate: &clean::Crate, cache: &mut Cache) -> String { .map(|module| shorten(plain_summary_line(module.doc_value()))) .unwrap_or(String::new()); - let crate_aliases = aliases - .iter() - .map(|(k, values)| { - ( - k.clone(), - values - .iter() - .filter_map(|v| { - let x = &crate_items[*v]; - if x.parent_idx.is_some() == x.parent.is_some() { Some(*v) } else { None } - }) - .collect::>(), - ) - }) - .filter(|(_, values)| !values.is_empty()) - .collect::>(); + let crate_aliases = + aliases.iter().map(|(k, values)| (k.clone(), values.clone())).collect::>(); #[derive(Serialize)] struct CrateData<'a> { diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js index 94ae69fde57f..22e312e13c01 100644 --- a/src/librustdoc/html/static/main.js +++ b/src/librustdoc/html/static/main.js @@ -972,7 +972,7 @@ function getSearchElement() { desc: item.desc, ty: item.ty, parent: item.parent, - type: item.parent, + type: item.type, is_alias: true, }; } From c4d9318be6a493da4c6aa307dd4de7e24a15120a Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 7 May 2020 21:42:41 +0200 Subject: [PATCH 172/203] Make current crate aliases go first --- src/librustdoc/html/static/main.js | 20 ++++++--- src/test/rustdoc-js-std/alias-2.js | 6 +-- src/test/rustdoc-js/doc-alias.js | 68 +++++++++++++++++++++--------- src/test/rustdoc-js/doc-alias.rs | 1 - src/tools/rustdoc-js/tester.js | 6 ++- 5 files changed, 67 insertions(+), 34 deletions(-) diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js index 22e312e13c01..7592331dd656 100644 --- a/src/librustdoc/html/static/main.js +++ b/src/librustdoc/html/static/main.js @@ -978,7 +978,10 @@ function getSearchElement() { } function handleAliases(ret, query, filterCrates) { + // We separate aliases and crate aliases because we want to have current crate + // aliases to be before the others in the displayed results. var aliases = []; + var crateAliases = []; var i; if (filterCrates !== undefined && ALIASES[filterCrates] && @@ -990,25 +993,28 @@ function getSearchElement() { } else { Object.keys(ALIASES).forEach(function(crate) { if (ALIASES[crate][query.search]) { + var pushTo = crate === window.currentCrate ? crateAliases : aliases; for (i = 0; i < ALIASES[crate][query.search].length; ++i) { - aliases.push( + pushTo.push( createAliasFromItem( searchIndex[ALIASES[crate][query.search][i]])); } } }); } - aliases.sort(function(aaa, bbb) { + + var sortFunc = function(aaa, bbb) { if (aaa.path < bbb.path) { return 1; } else if (aaa.path === bbb.path) { return 0; } return -1; - }); - for (i = 0; i < aliases.length; ++i) { - var alias = aliases[i]; + }; + crateAliases.sort(sortFunc); + aliases.sort(sortFunc); + var pushFunc = function(alias) { alias.alias = query.raw; var res = buildHrefAndPath(alias); alias.displayPath = pathSplitter(res[0]); @@ -1019,7 +1025,9 @@ function getSearchElement() { if (ret.others.length > MAX_RESULTS) { ret.others.pop(); } - } + }; + onEach(aliases, pushFunc); + onEach(crateAliases, pushFunc); } // quoted values mean literal search diff --git a/src/test/rustdoc-js-std/alias-2.js b/src/test/rustdoc-js-std/alias-2.js index cb6ec4f8fed4..798fa29efbd2 100644 --- a/src/test/rustdoc-js-std/alias-2.js +++ b/src/test/rustdoc-js-std/alias-2.js @@ -1,12 +1,10 @@ -// ignore-order - const QUERY = '+'; const EXPECTED = { 'others': [ - { 'path': 'core::ops', 'name': 'AddAssign' }, - { 'path': 'core::ops', 'name': 'Add' }, { 'path': 'std::ops', 'name': 'AddAssign' }, { 'path': 'std::ops', 'name': 'Add' }, + { 'path': 'core::ops', 'name': 'AddAssign' }, + { 'path': 'core::ops', 'name': 'Add' }, ], }; diff --git a/src/test/rustdoc-js/doc-alias.js b/src/test/rustdoc-js/doc-alias.js index e6310b625e53..896808d41578 100644 --- a/src/test/rustdoc-js/doc-alias.js +++ b/src/test/rustdoc-js/doc-alias.js @@ -32,7 +32,8 @@ const EXPECTED = [ 'path': 'doc_alias', 'name': 'Struct', 'alias': 'StructItem', - 'href': '../doc_alias/struct.Struct.html' + 'href': '../doc_alias/struct.Struct.html', + 'is_alias': true }, ], }, @@ -42,7 +43,8 @@ const EXPECTED = [ 'path': 'doc_alias::Struct', 'name': 'field', 'alias': 'StructFieldItem', - 'href': '../doc_alias/struct.Struct.html#structfield.field' + 'href': '../doc_alias/struct.Struct.html#structfield.field', + 'is_alias': true }, ], }, @@ -52,7 +54,8 @@ const EXPECTED = [ 'path': 'doc_alias::Struct', 'name': 'method', 'alias': 'StructMethodItem', - 'href': '../doc_alias/struct.Struct.html#method.method' + 'href': '../doc_alias/struct.Struct.html#method.method', + 'is_alias': true }, ], }, @@ -65,8 +68,15 @@ const EXPECTED = [ 'others': [], }, { - // ImplTraitFunction - 'others': [], + 'others': [ + { + 'path': 'doc_alias::Struct', + 'name': 'function', + 'alias': 'ImplTraitFunction', + 'href': '../doc_alias/struct.Struct.html#method.function', + 'is_alias': true + }, + ], }, { 'others': [ @@ -74,7 +84,8 @@ const EXPECTED = [ 'path': 'doc_alias', 'name': 'Enum', 'alias': 'EnumItem', - 'href': '../doc_alias/enum.Enum.html' + 'href': '../doc_alias/enum.Enum.html', + 'is_alias': true }, ], }, @@ -84,7 +95,8 @@ const EXPECTED = [ 'path': 'doc_alias::Enum', 'name': 'Variant', 'alias': 'VariantItem', - 'href': '../doc_alias/enum.Enum.html#variant.Variant' + 'href': '../doc_alias/enum.Enum.html#variant.Variant', + 'is_alias': true }, ], }, @@ -94,7 +106,8 @@ const EXPECTED = [ 'path': 'doc_alias::Enum', 'name': 'method', 'alias': 'EnumMethodItem', - 'href': '../doc_alias/enum.Enum.html#method.method' + 'href': '../doc_alias/enum.Enum.html#method.method', + 'is_alias': true }, ], }, @@ -104,7 +117,8 @@ const EXPECTED = [ 'path': 'doc_alias', 'name': 'Typedef', 'alias': 'TypedefItem', - 'href': '../doc_alias/type.Typedef.html' + 'href': '../doc_alias/type.Typedef.html', + 'is_alias': true }, ], }, @@ -114,7 +128,8 @@ const EXPECTED = [ 'path': 'doc_alias', 'name': 'Trait', 'alias': 'TraitItem', - 'href': '../doc_alias/trait.Trait.html' + 'href': '../doc_alias/trait.Trait.html', + 'is_alias': true }, ], }, @@ -124,7 +139,8 @@ const EXPECTED = [ 'path': 'doc_alias::Trait', 'name': 'Target', 'alias': 'TraitTypeItem', - 'href': '../doc_alias/trait.Trait.html#associatedtype.Target' + 'href': '../doc_alias/trait.Trait.html#associatedtype.Target', + 'is_alias': true }, ], }, @@ -134,7 +150,8 @@ const EXPECTED = [ 'path': 'doc_alias::Trait', 'name': 'AssociatedConst', 'alias': 'AssociatedConstItem', - 'href': '../doc_alias/trait.Trait.html#associatedconstant.AssociatedConst' + 'href': '../doc_alias/trait.Trait.html#associatedconstant.AssociatedConst', + 'is_alias': true }, ], }, @@ -144,7 +161,8 @@ const EXPECTED = [ 'path': 'doc_alias::Trait', 'name': 'function', 'alias': 'TraitFunctionItem', - 'href': '../doc_alias/trait.Trait.html#tymethod.function' + 'href': '../doc_alias/trait.Trait.html#tymethod.function', + 'is_alias': true }, ], }, @@ -154,7 +172,8 @@ const EXPECTED = [ 'path': 'doc_alias', 'name': 'function', 'alias': 'FunctionItem', - 'href': '../doc_alias/fn.function.html' + 'href': '../doc_alias/fn.function.html', + 'is_alias': true }, ], }, @@ -164,7 +183,8 @@ const EXPECTED = [ 'path': 'doc_alias', 'name': 'Module', 'alias': 'ModuleItem', - 'href': '../doc_alias/Module/index.html' + 'href': '../doc_alias/Module/index.html', + 'is_alias': true }, ], }, @@ -174,7 +194,8 @@ const EXPECTED = [ 'path': 'doc_alias', 'name': 'Const', 'alias': 'ConstItem', - 'href': '../doc_alias/constant.Const.html' + 'href': '../doc_alias/constant.Const.html', + 'is_alias': true }, ], }, @@ -184,7 +205,8 @@ const EXPECTED = [ 'path': 'doc_alias', 'name': 'Static', 'alias': 'StaticItem', - 'href': '../doc_alias/static.Static.html' + 'href': '../doc_alias/static.Static.html', + 'is_alias': true }, ], }, @@ -194,7 +216,8 @@ const EXPECTED = [ 'path': 'doc_alias', 'name': 'Union', 'alias': 'UnionItem', - 'href': '../doc_alias/union.Union.html' + 'href': '../doc_alias/union.Union.html', + 'is_alias': true }, // Not an alias! { @@ -210,7 +233,8 @@ const EXPECTED = [ 'path': 'doc_alias::Union', 'name': 'union_item', 'alias': 'UnionFieldItem', - 'href': '../doc_alias/union.Union.html#structfield.union_item' + 'href': '../doc_alias/union.Union.html#structfield.union_item', + 'is_alias': true }, ], }, @@ -220,7 +244,8 @@ const EXPECTED = [ 'path': 'doc_alias::Union', 'name': 'method', 'alias': 'UnionMethodItem', - 'href': '../doc_alias/union.Union.html#method.method' + 'href': '../doc_alias/union.Union.html#method.method', + 'is_alias': true }, ], }, @@ -230,7 +255,8 @@ const EXPECTED = [ 'path': 'doc_alias', 'name': 'Macro', 'alias': 'MacroItem', - 'href': '../doc_alias/macro.Macro.html' + 'href': '../doc_alias/macro.Macro.html', + 'is_alias': true }, ], }, diff --git a/src/test/rustdoc-js/doc-alias.rs b/src/test/rustdoc-js/doc-alias.rs index 8cd0a8299741..84c638a19950 100644 --- a/src/test/rustdoc-js/doc-alias.rs +++ b/src/test/rustdoc-js/doc-alias.rs @@ -19,7 +19,6 @@ impl Trait for Struct { #[doc(alias = "ImplAssociatedConstItem")] const AssociatedConst: i32 = 12; - // Shouldn't be listed in aliases! #[doc(alias = "ImplTraitFunction")] fn function() -> Self::Target { 0 } } diff --git a/src/tools/rustdoc-js/tester.js b/src/tools/rustdoc-js/tester.js index 90315d6f6443..1fa46ce99f5e 100644 --- a/src/tools/rustdoc-js/tester.js +++ b/src/tools/rustdoc-js/tester.js @@ -218,7 +218,7 @@ function lookForEntry(entry, data) { return null; } -function loadMainJsAndIndex(mainJs, searchIndex, crate) { +function loadMainJsAndIndex(mainJs, searchIndex, storageJs, crate) { if (searchIndex[searchIndex.length - 1].length === 0) { searchIndex.pop(); } @@ -241,6 +241,7 @@ function loadMainJsAndIndex(mainJs, searchIndex, crate) { ALIASES = {}; finalJS += 'window = { "currentCrate": "' + crate + '" };\n'; finalJS += 'var rootPath = "../";\n'; + finalJS += loadThings(["onEach"], 'function', extractFunction, storageJs); finalJS += loadThings(arraysToLoad, 'array', extractArrayVariable, mainJs); finalJS += loadThings(variablesToLoad, 'variable', extractVariable, mainJs); finalJS += loadThings(functionsToLoad, 'function', extractFunction, mainJs); @@ -338,10 +339,11 @@ function runChecks(testFile, loaded, index) { function load_files(doc_folder, resource_suffix, crate) { var mainJs = readFile(path.join(doc_folder, "main" + resource_suffix + ".js")); + var storageJs = readFile(path.join(doc_folder, "storage" + resource_suffix + ".js")); var searchIndex = readFile( path.join(doc_folder, "search-index" + resource_suffix + ".js")).split("\n"); - return loadMainJsAndIndex(mainJs, searchIndex, crate); + return loadMainJsAndIndex(mainJs, searchIndex, storageJs, crate); } function showHelp() { From e17ac668997410a1a9d2da8725329afb8b5f2901 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 13 May 2020 17:03:37 +0200 Subject: [PATCH 173/203] * Update aliases data struct from HashMap to BTreeMap to have more deterministic results * Update Javascript to take this change into account * Update CrateData::aliases field to take a reference instead (it allowed to remove a conversion loop) --- src/librustdoc/html/render/cache.rs | 16 +++++++--------- src/librustdoc/html/static/main.js | 7 ++++--- 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/src/librustdoc/html/render/cache.rs b/src/librustdoc/html/render/cache.rs index b8d97c2ac503..57d385de3209 100644 --- a/src/librustdoc/html/render/cache.rs +++ b/src/librustdoc/html/render/cache.rs @@ -120,7 +120,7 @@ crate struct Cache { /// Aliases added through `#[doc(alias = "...")]`. Since a few items can have the same alias, /// we need the alias element to have an array of items. - pub(super) aliases: FxHashMap>, + pub(super) aliases: BTreeMap>, } impl Cache { @@ -331,7 +331,7 @@ impl DocFolder for Cache { for alias in item.attrs.get_doc_aliases() { self.aliases .entry(alias.to_lowercase()) - .or_insert(Vec::with_capacity(1)) + .or_insert(Vec::new()) .push(self.search_index.len() - 1); } } @@ -553,10 +553,10 @@ fn build_index(krate: &clean::Crate, cache: &mut Cache) -> String { parent_idx: None, search_type: get_index_search_type(&item), }); - for alias in item.attrs.get_doc_aliases().into_iter() { + for alias in item.attrs.get_doc_aliases() { aliases .entry(alias.to_lowercase()) - .or_insert(Vec::with_capacity(1)) + .or_insert(Vec::new()) .push(search_index.len() - 1); } } @@ -600,9 +600,6 @@ fn build_index(krate: &clean::Crate, cache: &mut Cache) -> String { .map(|module| shorten(plain_summary_line(module.doc_value()))) .unwrap_or(String::new()); - let crate_aliases = - aliases.iter().map(|(k, values)| (k.clone(), values.clone())).collect::>(); - #[derive(Serialize)] struct CrateData<'a> { doc: String, @@ -614,7 +611,8 @@ fn build_index(krate: &clean::Crate, cache: &mut Cache) -> String { // // To be noted: the `usize` elements are indexes to `items`. #[serde(rename = "a")] - aliases: Option)>>, + #[serde(skip_serializing_if = "BTreeMap::is_empty")] + aliases: &'a BTreeMap>, } // Collect the index into a string @@ -625,7 +623,7 @@ fn build_index(krate: &clean::Crate, cache: &mut Cache) -> String { doc: crate_doc, items: crate_items, paths: crate_paths, - aliases: if crate_aliases.is_empty() { None } else { Some(crate_aliases) }, + aliases, }) .expect("failed serde conversion") // All these `replace` calls are because we have to go through JS string for JSON content. diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js index 7592331dd656..9b498d66249e 100644 --- a/src/librustdoc/html/static/main.js +++ b/src/librustdoc/html/static/main.js @@ -1781,12 +1781,13 @@ function getSearchElement() { if (aliases) { ALIASES[crate] = {}; var j, local_aliases; - for (i = 0; i < aliases.length; ++i) { - var alias_name = aliases[i][0]; + for (var alias_name in aliases) { + if (!aliases.hasOwnProperty(alias_name)) { continue; } + if (!ALIASES[crate].hasOwnProperty(alias_name)) { ALIASES[crate][alias_name] = []; } - local_aliases = aliases[i][1]; + local_aliases = aliases[alias_name]; for (j = 0; j < local_aliases.length; ++j) { ALIASES[crate][alias_name].push(local_aliases[j] + currentIndex); } From 31fbf33679a9b018576058d37b4f6cf9beec1b14 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 14 May 2020 11:51:39 +0200 Subject: [PATCH 174/203] Clean up E0589 explanation --- src/librustc_error_codes/error_codes/E0589.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/librustc_error_codes/error_codes/E0589.md b/src/librustc_error_codes/error_codes/E0589.md index 5e15a875b0ba..8a4f8d217258 100644 --- a/src/librustc_error_codes/error_codes/E0589.md +++ b/src/librustc_error_codes/error_codes/E0589.md @@ -1,6 +1,8 @@ The value of `N` that was specified for `repr(align(N))` was not a power of two, or was greater than 2^29. +Erroneous code example: + ```compile_fail,E0589 #[repr(align(15))] // error: invalid `repr(align)` attribute: not a power of two enum Foo { From 425723f5b384ba75af4b9a6b4e0186f8bf2e99a3 Mon Sep 17 00:00:00 2001 From: Marko Mijalkovic Date: Thu, 14 May 2020 06:19:36 -0400 Subject: [PATCH 175/203] Rewrite link script from scratch This absolves previous licensing issues. --- .../spec/mipsel_sony_psp_linker_script.ld | 291 ++---------------- 1 file changed, 18 insertions(+), 273 deletions(-) diff --git a/src/librustc_target/spec/mipsel_sony_psp_linker_script.ld b/src/librustc_target/spec/mipsel_sony_psp_linker_script.ld index 9dd38f5ce919..1bd436d6f94c 100644 --- a/src/librustc_target/spec/mipsel_sony_psp_linker_script.ld +++ b/src/librustc_target/spec/mipsel_sony_psp_linker_script.ld @@ -1,151 +1,24 @@ -/* - * Copyright (c) 2005 adresd - * Copyright (c) 2005 Marcus R. Brown - * Copyright (c) 2005 James Forshaw - * Copyright (c) 2005 John Kelley - * Copyright (c) 2005 Jesper Svennevid - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. The names of the authors may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -OUTPUT_ARCH(mips:allegrex) ENTRY(module_start) SECTIONS { - /* Read-only sections, merged into text segment: */ - PROVIDE (__executable_start = 0x0); . = 0x0; - .interp : { *(.interp) } - .dynamic : { *(.dynamic) } - .hash : { *(.hash) } - .dynsym : { *(.dynsym) } - .dynstr : { *(.dynstr) } - .gnu.version : { *(.gnu.version) } - .gnu.version_d : { *(.gnu.version_d) } - .gnu.version_r : { *(.gnu.version_r) } - .rel.text : { *(.rel.text .rel.text.* .rel.gnu.linkonce.t.*) } - .rela.text : { *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*) } - .rel.init : { *(.rel.init) } - .rela.init : { *(.rela.init) } - .rel.fini : { *(.rel.fini) } - .rela.fini : { *(.rela.fini) } - /* PSP-specific relocations. */ - .rel.sceStub.text : { *(.rel.sceStub.text) *(SORT(.rel.sceStub.text.*)) } - .rel.lib.ent.top : { *(.rel.lib.ent.top) } - .rel.lib.ent : { *(.rel.lib.ent) } - .rel.lib.ent.btm : { *(.rel.lib.ent.btm) } - .rel.lib.stub.top : { *(.rel.lib.stub.top) } - .rel.lib.stub : { *(.rel.lib.stub) } - .rel.lib.stub.btm : { *(.rel.lib.stub.btm) } - .rel.rodata.sceModuleInfo : { *(.rel.rodata.sceModuleInfo) } - .rel.rodata.sceResident : { *(.rel.rodata.sceResident) } - .rel.rodata.sceNid : { *(.rel.rodata.sceNid) *(SORT(.rel.rodata.sceNid.*)) } - .rel.rodata.sceVstub : { *(.rel.rodata.sceVstub) *(SORT(.rel.rodata.sceVstub.*)) } - .rel.rodata : { *(.rel.rodata .rel.rodata.* .rel.gnu.linkonce.r.*) } - .rela.rodata : { *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*) } - .rel.data.rel.ro : { *(.rel.data.rel.ro*) } - .rela.data.rel.ro : { *(.rel.data.rel.ro*) } - .rel.data : { *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*) } - .rela.data : { *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*) } - .rel.tdata : { *(.rel.tdata .rel.tdata.* .rel.gnu.linkonce.td.*) } - .rela.tdata : { *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*) } - .rel.tbss : { *(.rel.tbss .rel.tbss.* .rel.gnu.linkonce.tb.*) } - .rela.tbss : { *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*) } - .rel.ctors : { *(.rel.ctors) } - .rela.ctors : { *(.rela.ctors) } - .rel.dtors : { *(.rel.dtors) } - .rela.dtors : { *(.rela.dtors) } - .rel.got : { *(.rel.got) } - .rela.got : { *(.rela.got) } - .rel.sdata : { *(.rel.sdata .rel.sdata.* .rel.gnu.linkonce.s.*) } - .rela.sdata : { *(.rela.sdata .rela.sdata.* .rela.gnu.linkonce.s.*) } - .rel.sbss : { *(.rel.sbss .rel.sbss.* .rel.gnu.linkonce.sb.*) } - .rela.sbss : { *(.rela.sbss .rela.sbss.* .rela.gnu.linkonce.sb.*) } - .rel.sdata2 : { *(.rel.sdata2 .rel.sdata2.* .rel.gnu.linkonce.s2.*) } - .rela.sdata2 : { *(.rela.sdata2 .rela.sdata2.* .rela.gnu.linkonce.s2.*) } - .rel.sbss2 : { *(.rel.sbss2 .rel.sbss2.* .rel.gnu.linkonce.sb2.*) } - .rela.sbss2 : { *(.rela.sbss2 .rela.sbss2.* .rela.gnu.linkonce.sb2.*) } - .rel.bss : { *(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*) } - .rela.bss : { *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*) } - .rel.plt : { *(.rel.plt) } - .rela.plt : { *(.rela.plt) } + /* PRX format requires text to begin at 0 */ + .text 0 : { *(.text .text.*) } - /* Start the text section at 0x0 for PRX generation */ - . = 0; + /* Sort stubs for convenient ordering */ + .sceStub.text : { *(.sceStub.text) *(SORT(.sceStub.text.*)) } - .text : - { - _ftext = . ; - *(.text .stub .text.* .gnu.linkonce.t.*) - KEEP (*(.text.*personality*)) - /* .gnu.warning sections are handled specially by elf32.em. */ - *(.gnu.warning) - *(.mips16.fn.*) *(.mips16.call.*) - } =0 - .init : - { - KEEP (*(.init)) - } =0 - .plt : { *(.plt) } - .fini : - { - KEEP (*(.fini)) - } =0 - /* PSP library stub functions. */ - .sceStub.text : { *(.sceStub.text) *(SORT(.sceStub.text.*)) } - PROVIDE (__etext = .); - PROVIDE (_etext = .); - PROVIDE (etext = .); - /* PSP library entry table and library stub table. */ - .lib.ent.top : { *(.lib.ent.top) } - .lib.ent : { *(.lib.ent) } - .lib.ent.btm : { *(.lib.ent.btm) } - .lib.stub.top : { *(.lib.stub.top) } - .lib.stub : { *(.lib.stub) } - .lib.stub.btm : { *(.lib.stub.btm) } - /* PSP read-only data for module info, NIDs, and Vstubs. The - .rodata.sceModuleInfo section must appear before the .rodata section - otherwise it would get absorbed into .rodata and the PSP bootloader - would be unable to locate the module info structure. */ - .rodata.sceModuleInfo : { *(.rodata.sceModuleInfo) } - .rodata.sceResident : { *(.rodata.sceResident) } - .rodata.sceNid : { KEEP(*(.rodata.sceNid)) KEEP(*(SORT(.rodata.sceNid.*))) } - .rodata.sceVstub : { *(.rodata.sceVstub) *(SORT(.rodata.sceVstub.*)) } - .rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) } - .rodata1 : { *(.rodata1) } - .sdata2 : { *(.sdata2 .sdata2.* .gnu.linkonce.s2.*) } - .sbss2 : { *(.sbss2 .sbss2.* .gnu.linkonce.sb2.*) } - .gcc_except_table : ONLY_IF_RO { KEEP (*(.gcc_except_table)) *(.gcc_except_table.*) } - - /* Exception handling */ - .eh_frame_hdr : - { - KEEP(*(.eh_frame_hdr)) - } + /* Keep these sections around, even though they may appear unused to the linker */ + .lib.ent.top : { KEEP(*(.lib.ent.top)) } + .lib.ent : { KEEP(*(.lib.ent)) } + .lib.ent.btm : { KEEP(*(.lib.ent.btm)) } + .lib.stub.top : { KEEP(*(.lib.stub.top)) } + .lib.stub : { KEEP(*(.lib.stub)) } + .lib.stub.btm : { KEEP(*(.lib.stub.btm)) } + .eh_frame_hdr : { KEEP(*(.eh_frame_hdr)) } + /* Add symbols for LLVM's libunwind */ __eh_frame_hdr_start = SIZEOF(.eh_frame_hdr) > 0 ? ADDR(.eh_frame_hdr) : 0; __eh_frame_hdr_end = SIZEOF(.eh_frame_hdr) > 0 ? . : 0; - .eh_frame : { __eh_frame_start = .; @@ -153,137 +26,9 @@ SECTIONS __eh_frame_end = .; } - /* Adjust the address for the data segment. We want to adjust up to - the same address within the page on the next page up. */ - . = ALIGN(256) + (. & (256 - 1)); - - .gcc_except_table : ONLY_IF_RW { KEEP (*(.gcc_except_table)) *(.gcc_except_table.*) } - /* Thread Local Storage sections */ - .tdata : { *(.tdata .tdata.* .gnu.linkonce.td.*) } - .tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) } - /* Ensure the __preinit_array_start label is properly aligned. We - could instead move the label definition inside the section, but - the linker would then create the section even if it turns out to - be empty, which isn't pretty. */ - . = ALIGN(32 / 8); - PROVIDE (__preinit_array_start = .); - .preinit_array : { KEEP (*(.preinit_array)) } - PROVIDE (__preinit_array_end = .); - PROVIDE (__init_array_start = .); - .init_array : { KEEP (*(.init_array)) } - PROVIDE (__init_array_end = .); - PROVIDE (__fini_array_start = .); - .fini_array : { KEEP (*(.fini_array)) } - PROVIDE (__fini_array_end = .); - .ctors : - { - /* gcc uses crtbegin.o to find the start of - the constructors, so we make sure it is - first. Because this is a wildcard, it - doesn't matter if the user does not - actually link against crtbegin.o; the - linker won't look for a file to match a - wildcard. The wildcard also means that it - doesn't matter which directory crtbegin.o - is in. */ - KEEP (*crtbegin*.o(.ctors)) - /* We don't want to include the .ctor section from - from the crtend.o file until after the sorted ctors. - The .ctor section from the crtend file contains the - end of ctors marker and it must be last */ - KEEP (*(EXCLUDE_FILE (*crtend*.o ) .ctors)) - KEEP (*(SORT(.ctors.*))) - KEEP (*(.ctors)) - } - .dtors : - { - KEEP (*crtbegin*.o(.dtors)) - KEEP (*(EXCLUDE_FILE (*crtend*.o ) .dtors)) - KEEP (*(SORT(.dtors.*))) - KEEP (*(.dtors)) - } - .jcr : { KEEP (*(.jcr)) } - .data.rel.ro : { *(.data.rel.ro.local) *(.data.rel.ro*) } - .data : - { - _fdata = . ; - *(.data .data.* .gnu.linkonce.d.*) - KEEP (*(.gnu.linkonce.d.*personality*)) - SORT(CONSTRUCTORS) - } - .data1 : { *(.data1) } - . = .; - _gp = ALIGN(16) + 0x7ff0; - .got : { *(.got.plt) *(.got) } - /* We want the small data sections together, so single-instruction offsets - can access them all, and initialized data all before uninitialized, so - we can shorten the on-disk segment size. */ - .sdata : - { - *(.sdata .sdata.* .gnu.linkonce.s.*) - } - .lit8 : { *(.lit8) } - .lit4 : { *(.lit4) } - _edata = .; - PROVIDE (edata = .); - __bss_start = .; - _fbss = .; - .sbss : - { - PROVIDE (__sbss_start = .); - PROVIDE (___sbss_start = .); - *(.dynsbss) - *(.sbss .sbss.* .gnu.linkonce.sb.*) - *(.scommon) - PROVIDE (__sbss_end = .); - PROVIDE (___sbss_end = .); - } - .bss : - { - *(.dynbss) - *(.bss .bss.* .gnu.linkonce.b.*) - *(COMMON) - /* Align here to ensure that the .bss section occupies space up to - _end. Align after .bss to ensure correct alignment even if the - .bss section disappears because there are no input sections. */ - . = ALIGN(32 / 8); - } - . = ALIGN(32 / 8); - _end = .; - PROVIDE (end = .); - /* Stabs debugging sections. */ - .stab 0 : { *(.stab) } - .stabstr 0 : { *(.stabstr) } - .stab.excl 0 : { *(.stab.excl) } - .stab.exclstr 0 : { *(.stab.exclstr) } - .stab.index 0 : { *(.stab.index) } - .stab.indexstr 0 : { *(.stab.indexstr) } - .comment 0 : { *(.comment) } - /* DWARF debug sections. - Symbols in the DWARF debugging sections are relative to the beginning - of the section so we begin them at 0. */ - /* DWARF 1 */ - .debug 0 : { *(.debug) } - .line 0 : { *(.line) } - /* GNU DWARF 1 extensions */ - .debug_srcinfo 0 : { *(.debug_srcinfo) } - .debug_sfnames 0 : { *(.debug_sfnames) } - /* DWARF 1.1 and DWARF 2 */ - .debug_aranges 0 : { *(.debug_aranges) } - .debug_pubnames 0 : { *(.debug_pubnames) } - /* DWARF 2 */ - .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } - .debug_abbrev 0 : { *(.debug_abbrev) } - .debug_line 0 : { *(.debug_line) } - .debug_frame 0 : { *(.debug_frame) } - .debug_str 0 : { *(.debug_str) } - .debug_loc 0 : { *(.debug_loc) } - .debug_macinfo 0 : { *(.debug_macinfo) } - /* SGI/MIPS DWARF 2 extensions */ - .debug_weaknames 0 : { *(.debug_weaknames) } - .debug_funcnames 0 : { *(.debug_funcnames) } - .debug_typenames 0 : { *(.debug_typenames) } - .debug_varnames 0 : { *(.debug_varnames) } - /DISCARD/ : { *(.comment) *(.pdr) } - /DISCARD/ : { *(.note.GNU-stack) } + /* These are explicitly listed to avoid being merged into .rodata */ + .rodata.sceResident : { *(.rodata.sceResident) } + .rodata.sceModuleInfo : { *(.rodata.sceModuleInfo) } + /* Sort NIDs for convenient ordering */ + .rodata.sceNid : { *(.rodata.sceNid) *(SORT(.rodata.sceNid.*)) } } From bbb63d4554b03feee481bc799a04f183abaff1d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= Date: Wed, 13 May 2020 00:00:00 +0000 Subject: [PATCH 176/203] Consistently use LLVM lifetime markers during codegen Ensure that inliner inserts lifetime markers if they have been emitted during codegen. Otherwise if allocas from inlined functions are merged together, lifetime markers from one function might invalidate load & stores performed by the other one. --- src/librustc_codegen_llvm/back/write.rs | 5 +-- src/librustc_codegen_llvm/builder.rs | 10 +----- src/librustc_codegen_llvm/llvm/ffi.rs | 1 + src/librustc_codegen_ssa/back/write.rs | 2 ++ src/librustc_session/session.rs | 10 ++++++ src/rustllvm/PassWrapper.cpp | 4 +-- .../sanitize/issue-72154-lifetime-markers.rs | 31 +++++++++++++++++++ 7 files changed, 50 insertions(+), 13 deletions(-) create mode 100644 src/test/ui/sanitize/issue-72154-lifetime-markers.rs diff --git a/src/librustc_codegen_llvm/back/write.rs b/src/librustc_codegen_llvm/back/write.rs index dd9ada0b95da..a08235b304dc 100644 --- a/src/librustc_codegen_llvm/back/write.rs +++ b/src/librustc_codegen_llvm/back/write.rs @@ -394,6 +394,7 @@ pub(crate) unsafe fn optimize_with_new_llvm_pass_manager( config.vectorize_slp, config.vectorize_loop, config.no_builtins, + config.emit_lifetime_markers, sanitizer_options.as_ref(), pgo_gen_path.as_ref().map_or(std::ptr::null(), |s| s.as_ptr()), pgo_use_path.as_ref().map_or(std::ptr::null(), |s| s.as_ptr()), @@ -934,10 +935,10 @@ pub unsafe fn with_llvm_pmb( llvm::LLVMPassManagerBuilderUseInlinerWithThreshold(builder, 25); } (llvm::CodeGenOptLevel::None, ..) => { - llvm::LLVMRustAddAlwaysInlinePass(builder, false); + llvm::LLVMRustAddAlwaysInlinePass(builder, config.emit_lifetime_markers); } (llvm::CodeGenOptLevel::Less, ..) => { - llvm::LLVMRustAddAlwaysInlinePass(builder, true); + llvm::LLVMRustAddAlwaysInlinePass(builder, config.emit_lifetime_markers); } (llvm::CodeGenOptLevel::Default, ..) => { llvm::LLVMPassManagerBuilderUseInlinerWithThreshold(builder, 225); diff --git a/src/librustc_codegen_llvm/builder.rs b/src/librustc_codegen_llvm/builder.rs index 89bd96c1fe21..f5ae9824df89 100644 --- a/src/librustc_codegen_llvm/builder.rs +++ b/src/librustc_codegen_llvm/builder.rs @@ -18,7 +18,6 @@ use rustc_data_structures::small_c_str::SmallCStr; use rustc_hir::def_id::DefId; use rustc_middle::ty::layout::TyAndLayout; use rustc_middle::ty::{self, Ty, TyCtxt}; -use rustc_session::config::{self, Sanitizer}; use rustc_target::abi::{self, Align, Size}; use rustc_target::spec::{HasTargetSpec, Target}; use std::borrow::Cow; @@ -1243,14 +1242,7 @@ impl Builder<'a, 'll, 'tcx> { return; } - let opts = &self.cx.sess().opts; - let emit = match opts.debugging_opts.sanitizer { - // Some sanitizer use lifetime intrinsics. When they are in use, - // emit lifetime intrinsics regardless of optimization level. - Some(Sanitizer::Address | Sanitizer::Memory) => true, - _ => opts.optimize != config::OptLevel::No, - }; - if !emit { + if !self.cx().sess().emit_lifetime_markers() { return; } diff --git a/src/librustc_codegen_llvm/llvm/ffi.rs b/src/librustc_codegen_llvm/llvm/ffi.rs index 0d466c2cd745..713cb2324f7f 100644 --- a/src/librustc_codegen_llvm/llvm/ffi.rs +++ b/src/librustc_codegen_llvm/llvm/ffi.rs @@ -2000,6 +2000,7 @@ extern "C" { SLPVectorize: bool, LoopVectorize: bool, DisableSimplifyLibCalls: bool, + EmitLifetimeMarkers: bool, SanitizerOptions: Option<&SanitizerOptions>, PGOGenPath: *const c_char, PGOUsePath: *const c_char, diff --git a/src/librustc_codegen_ssa/back/write.rs b/src/librustc_codegen_ssa/back/write.rs index 6210559251de..a88fef5aaacf 100644 --- a/src/librustc_codegen_ssa/back/write.rs +++ b/src/librustc_codegen_ssa/back/write.rs @@ -110,6 +110,7 @@ pub struct ModuleConfig { pub merge_functions: bool, pub inline_threshold: Option, pub new_llvm_pass_manager: bool, + pub emit_lifetime_markers: bool, } impl ModuleConfig { @@ -244,6 +245,7 @@ impl ModuleConfig { inline_threshold: sess.opts.cg.inline_threshold, new_llvm_pass_manager: sess.opts.debugging_opts.new_llvm_pass_manager, + emit_lifetime_markers: sess.emit_lifetime_markers(), } } diff --git a/src/librustc_session/session.rs b/src/librustc_session/session.rs index b39b15dc2442..cb5bd37442a7 100644 --- a/src/librustc_session/session.rs +++ b/src/librustc_session/session.rs @@ -936,6 +936,16 @@ impl Session { // then try to skip it where possible. dbg_opts.plt.unwrap_or(needs_plt || !full_relro) } + + /// Checks if LLVM lifetime markers should be emitted. + pub fn emit_lifetime_markers(&self) -> bool { + match self.opts.debugging_opts.sanitizer { + // AddressSanitizer uses lifetimes to detect use after scope bugs. + // MemorySanitizer uses lifetimes to detect use of uninitialized stack variables. + Some(Sanitizer::Address | Sanitizer::Memory) => true, + _ => self.opts.optimize != config::OptLevel::No, + } + } } pub fn build_session( diff --git a/src/rustllvm/PassWrapper.cpp b/src/rustllvm/PassWrapper.cpp index 84bde9a52f7c..b17fa57c5c1e 100644 --- a/src/rustllvm/PassWrapper.cpp +++ b/src/rustllvm/PassWrapper.cpp @@ -717,7 +717,7 @@ LLVMRustOptimizeWithNewPassManager( LLVMRustOptStage OptStage, bool NoPrepopulatePasses, bool VerifyIR, bool UseThinLTOBuffers, bool MergeFunctions, bool UnrollLoops, bool SLPVectorize, bool LoopVectorize, - bool DisableSimplifyLibCalls, + bool DisableSimplifyLibCalls, bool EmitLifetimeMarkers, LLVMRustSanitizerOptions *SanitizerOptions, const char *PGOGenPath, const char *PGOUsePath, void* LlvmSelfProfiler, @@ -853,7 +853,7 @@ LLVMRustOptimizeWithNewPassManager( MPM.addPass(createModuleToFunctionPassAdaptor(std::move(FPM))); } - MPM.addPass(AlwaysInlinerPass(/*InsertLifetimeIntrinsics=*/false)); + MPM.addPass(AlwaysInlinerPass(EmitLifetimeMarkers)); #if LLVM_VERSION_GE(10, 0) if (PGOOpt) { diff --git a/src/test/ui/sanitize/issue-72154-lifetime-markers.rs b/src/test/ui/sanitize/issue-72154-lifetime-markers.rs new file mode 100644 index 000000000000..458f99143b64 --- /dev/null +++ b/src/test/ui/sanitize/issue-72154-lifetime-markers.rs @@ -0,0 +1,31 @@ +// Regression test for issue 72154, where the use of AddressSanitizer enabled +// emission of lifetime markers during codegen, while at the same time asking +// always inliner pass not to insert them. This eventually lead to a +// miscompilation which was subsequently detected by AddressSanitizer as UB. +// +// needs-sanitizer-support +// only-x86_64 +// +// compile-flags: -Copt-level=0 -Zsanitizer=address +// run-pass + +pub struct Wrap { + pub t: [usize; 1] +} + +impl Wrap { + #[inline(always)] + pub fn new(t: [usize; 1]) -> Self { + Wrap { t } + } +} + +#[inline(always)] +pub fn assume_init() -> [usize; 1] { + [1234] +} + +fn main() { + let x: [usize; 1] = assume_init(); + Wrap::new(x); +} From f6aa161936887bf4a0aaebbd5cfc743132a1ab0b Mon Sep 17 00:00:00 2001 From: Nathan Corbyn Date: Thu, 14 May 2020 11:37:58 +0100 Subject: [PATCH 177/203] Don't ICE on missing `Unsize` impl --- .../traits/error_reporting/mod.rs | 29 +++++++++++++++---- src/test/ui/issues/issue-71036.rs | 17 +++++++++++ src/test/ui/issues/issue-71036.stderr | 12 ++++++++ 3 files changed, 52 insertions(+), 6 deletions(-) create mode 100644 src/test/ui/issues/issue-71036.rs create mode 100644 src/test/ui/issues/issue-71036.stderr diff --git a/src/librustc_trait_selection/traits/error_reporting/mod.rs b/src/librustc_trait_selection/traits/error_reporting/mod.rs index 405c656bad56..784fc36e67e6 100644 --- a/src/librustc_trait_selection/traits/error_reporting/mod.rs +++ b/src/librustc_trait_selection/traits/error_reporting/mod.rs @@ -283,6 +283,8 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { .unwrap_or(false); let is_from = format!("{}", trait_ref.print_only_trait_path()) .starts_with("std::convert::From<"); + let is_unsize = + { Some(trait_ref.def_id()) == self.tcx.lang_items().unsize_trait() }; let (message, note) = if is_try && is_from { ( Some(format!( @@ -405,6 +407,17 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { return; } + if is_unsize { + // If the obligation failed due to a missing implementation of the + // `Unsize` trait, give a pointer to why that might be the case + err.note( + "all implementations of `Unsize` are provided \ + automatically by the compiler, see \ + \ + for more information", + ); + } + // Try to report a help message if !trait_ref.has_infer_types_or_consts() && self.predicate_can_apply(obligation.param_env, trait_ref) @@ -427,12 +440,16 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { let impl_candidates = self.find_similar_impl_candidates(trait_ref); self.report_similar_impl_candidates(impl_candidates, &mut err); } - self.suggest_change_mut( - &obligation, - &mut err, - &trait_ref, - points_at_arg, - ); + // Changing mutability doesn't make a difference to whether we have + // an `Unsize` impl (Fixes ICE in #71036) + if !is_unsize { + self.suggest_change_mut( + &obligation, + &mut err, + &trait_ref, + points_at_arg, + ); + } } // If this error is due to `!: Trait` not implemented but `(): Trait` is diff --git a/src/test/ui/issues/issue-71036.rs b/src/test/ui/issues/issue-71036.rs new file mode 100644 index 000000000000..01d1cff42e4b --- /dev/null +++ b/src/test/ui/issues/issue-71036.rs @@ -0,0 +1,17 @@ +#![feature(unsize, dispatch_from_dyn)] + +use std::marker::Unsize; +use std::ops::DispatchFromDyn; + +#[allow(unused)] +struct Foo<'a, T: ?Sized> { + _inner: &'a &'a T, +} + +impl<'a, T: ?Sized + Unsize, U: ?Sized> DispatchFromDyn> for Foo<'a, T> {} +//~^ ERROR the trait bound `&'a T: std::marker::Unsize<&'a U>` is not satisfied +//~| NOTE the trait `std::marker::Unsize<&'a U>` is not implemented for `&'a T` +//~| NOTE all implementations of `Unsize` are provided automatically by the compiler +//~| NOTE required because of the requirements on the impl + +fn main() {} diff --git a/src/test/ui/issues/issue-71036.stderr b/src/test/ui/issues/issue-71036.stderr new file mode 100644 index 000000000000..57cf24689454 --- /dev/null +++ b/src/test/ui/issues/issue-71036.stderr @@ -0,0 +1,12 @@ +error[E0277]: the trait bound `&'a T: std::marker::Unsize<&'a U>` is not satisfied + --> $DIR/issue-71036.rs:11:1 + | +LL | impl<'a, T: ?Sized + Unsize, U: ?Sized> DispatchFromDyn> for Foo<'a, T> {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Unsize<&'a U>` is not implemented for `&'a T` + | + = note: all implementations of `Unsize` are provided automatically by the compiler, see for more information + = note: required because of the requirements on the impl of `std::ops::DispatchFromDyn<&'a &'a U>` for `&'a &'a T` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. From 0dc74dc0c6beb0bf2fd4fcc32cf3461a07f44521 Mon Sep 17 00:00:00 2001 From: sergey-melnychuk Date: Thu, 14 May 2020 20:02:40 +0200 Subject: [PATCH 178/203] cleanup stale FIXME(#64197) --- src/librustc_expand/parse/lexer/tests.rs | 4 ++-- src/librustc_parse/lexer/mod.rs | 7 +++++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/librustc_expand/parse/lexer/tests.rs b/src/librustc_expand/parse/lexer/tests.rs index 2cb6267e0f6a..2932475430bb 100644 --- a/src/librustc_expand/parse/lexer/tests.rs +++ b/src/librustc_expand/parse/lexer/tests.rs @@ -50,13 +50,13 @@ fn t1() { assert_eq!(string_reader.next_token(), token::Whitespace); // Read another token. let tok3 = string_reader.next_token(); - assert_eq!(string_reader.pos.clone(), BytePos(28)); + assert_eq!(string_reader.pos(), BytePos(28)); let tok4 = Token::new(mk_ident("main"), Span::with_root_ctxt(BytePos(24), BytePos(28))); assert_eq!(tok3.kind, tok4.kind); assert_eq!(tok3.span, tok4.span); assert_eq!(string_reader.next_token(), token::OpenDelim(token::Paren)); - assert_eq!(string_reader.pos.clone(), BytePos(29)) + assert_eq!(string_reader.pos(), BytePos(29)) }) } diff --git a/src/librustc_parse/lexer/mod.rs b/src/librustc_parse/lexer/mod.rs index f676a34a1d12..aa048d682c2d 100644 --- a/src/librustc_parse/lexer/mod.rs +++ b/src/librustc_parse/lexer/mod.rs @@ -31,8 +31,7 @@ pub struct StringReader<'a> { /// Initial position, read-only. start_pos: BytePos, /// The absolute offset within the source_map of the current character. - // FIXME(#64197): `pub` is needed by tests for now. - pub pos: BytePos, + pos: BytePos, /// Stop reading src at this index. end_src_index: usize, /// Source text to tokenize. @@ -436,6 +435,10 @@ impl<'a> StringReader<'a> { } } + pub fn pos(&self) -> BytePos { + self.pos + } + #[inline] fn src_index(&self, pos: BytePos) -> usize { (pos - self.start_pos).to_usize() From 15c22922989774cb2102fc5c52f078f0f899cc62 Mon Sep 17 00:00:00 2001 From: Tyler Mandry Date: Thu, 14 May 2020 11:46:36 -0700 Subject: [PATCH 179/203] Don't pass --dynamic-linker for Fuchsia dylibs This was causing a PT_INTERP header in Fuchsia dylibs (implying that they're executable when they're not). --- src/librustc_codegen_ssa/back/link.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_codegen_ssa/back/link.rs b/src/librustc_codegen_ssa/back/link.rs index 7a0e1e2c6388..dc712e509c23 100644 --- a/src/librustc_codegen_ssa/back/link.rs +++ b/src/librustc_codegen_ssa/back/link.rs @@ -1422,7 +1422,7 @@ fn linker_with_args<'a, B: ArchiveBuilder<'a>>( add_pre_link_args(cmd, sess, flavor, crate_type); // NO-OPT-OUT, OBJECT-FILES-NO, AUDIT-ORDER - if sess.target.target.options.is_like_fuchsia { + if sess.target.target.options.is_like_fuchsia && crate_type == CrateType::Executable { let prefix = match sess.opts.debugging_opts.sanitizer { Some(Sanitizer::Address) => "asan/", _ => "", From c919a6ea09108d3c45bcfb9e95c6289a04606f53 Mon Sep 17 00:00:00 2001 From: JOE1994 Date: Thu, 14 May 2020 16:39:36 -0400 Subject: [PATCH 180/203] Minor fixes to comments * In 'src/librustc_ast_passes/node_count.rs' * typo fix ('rought' -> 'rough') * In 'src/librustc_middle/middle/region.rs', * fixed broken link to 'rustc-dev-guide' * typo fix ('aluded' -> 'alluded') Thank you for reviewing this PR :) --- src/librustc_ast_passes/node_count.rs | 2 +- src/librustc_middle/middle/region.rs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/librustc_ast_passes/node_count.rs b/src/librustc_ast_passes/node_count.rs index 3cf562b927e2..34db59b1b458 100644 --- a/src/librustc_ast_passes/node_count.rs +++ b/src/librustc_ast_passes/node_count.rs @@ -1,4 +1,4 @@ -// Simply gives a rought count of the number of nodes in an AST. +// Simply gives a rough count of the number of nodes in an AST. use rustc_ast::ast::*; use rustc_ast::visit::*; diff --git a/src/librustc_middle/middle/region.rs b/src/librustc_middle/middle/region.rs index c3eeea7662ba..f02d8fe8ad60 100644 --- a/src/librustc_middle/middle/region.rs +++ b/src/librustc_middle/middle/region.rs @@ -4,7 +4,7 @@ //! For more information about how MIR-based region-checking works, //! see the [rustc dev guide]. //! -//! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/mir/borrowck.html +//! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/borrow_check.html use crate::ich::{NodeIdHashingMode, StableHashingContext}; use crate::ty::{self, DefIdTree, TyCtxt}; @@ -181,7 +181,7 @@ impl Scope { // `blk`; reuse span of `blk` and shift `lo` // forward to end of indexed statement. // - // (This is the special case aluded to in the + // (This is the special case alluded to in the // doc-comment for this method) let stmt_span = blk.stmts[first_statement_index.index()].span; From d53068e3ea607ba757eeb496376fc955c5a85055 Mon Sep 17 00:00:00 2001 From: CAD97 Date: Thu, 14 May 2020 16:57:02 -0400 Subject: [PATCH 181/203] improve step_integer_impls macro --- src/libcore/iter/range.rs | 35 ++++++----------------------------- 1 file changed, 6 insertions(+), 29 deletions(-) diff --git a/src/libcore/iter/range.rs b/src/libcore/iter/range.rs index 7a08d6d1ff37..bae673408c67 100644 --- a/src/libcore/iter/range.rs +++ b/src/libcore/iter/range.rs @@ -196,9 +196,6 @@ macro_rules! step_identical_methods { unsafe fn backward_unchecked(start: Self, n: usize) -> Self { start.unchecked_sub(n as Self) } - }; - ( [$u:ident $i:ident] ) => { - step_identical_methods!(); #[inline] fn forward(start: Self, n: usize) -> Self { @@ -207,8 +204,8 @@ macro_rules! step_identical_methods { if Self::forward_checked(start, n).is_none() { let _ = Add::add(Self::MAX, 1); } - // Do wrapping math to allow e.g. `Step::forward(-128u8, 255)`. - start.wrapping_add(n as Self) as Self + // Do wrapping math to allow e.g. `Step::forward(-128i8, 255)`. + start.wrapping_add(n as Self) } #[inline] @@ -218,8 +215,8 @@ macro_rules! step_identical_methods { if Self::backward_checked(start, n).is_none() { let _ = Sub::sub(Self::MIN, 1); } - // Do wrapping math to allow e.g. `Step::backward(127u8, 255)`. - start.wrapping_sub(n as Self) as Self + // Do wrapping math to allow e.g. `Step::backward(127i8, 255)`. + start.wrapping_sub(n as Self) } }; } @@ -235,7 +232,7 @@ macro_rules! step_integer_impls { #[allow(unreachable_patterns)] #[unstable(feature = "step_trait", reason = "recently redesigned", issue = "42168")] unsafe impl Step for $u_narrower { - step_identical_methods!( [ $u_narrower $i_narrower ] ); + step_identical_methods!(); #[inline] fn steps_between(start: &Self, end: &Self) -> Option { @@ -267,7 +264,7 @@ macro_rules! step_integer_impls { #[allow(unreachable_patterns)] #[unstable(feature = "step_trait", reason = "recently redesigned", issue = "42168")] unsafe impl Step for $i_narrower { - step_identical_methods!( [ $u_narrower $i_narrower ] ); + step_identical_methods!(); #[inline] fn steps_between(start: &Self, end: &Self) -> Option { @@ -347,20 +344,10 @@ macro_rules! step_integer_impls { start.checked_add(n as Self) } - #[inline] - fn forward(start: Self, n: usize) -> Self { - Add::add(start, n as Self) - } - #[inline] fn backward_checked(start: Self, n: usize) -> Option { start.checked_sub(n as Self) } - - #[inline] - fn backward(start: Self, n: usize) -> Self { - Sub::sub(start, n as Self) - } } #[allow(unreachable_patterns)] @@ -387,20 +374,10 @@ macro_rules! step_integer_impls { start.checked_add(n as Self) } - #[inline] - fn forward(start: Self, n: usize) -> Self { - Add::add(start, n as Self) - } - #[inline] fn backward_checked(start: Self, n: usize) -> Option { start.checked_sub(n as Self) } - - #[inline] - fn backward(start: Self, n: usize) -> Self { - Sub::sub(start, n as Self) - } } )+ }; From 89543793126b142b8c40b4cc83e284a91cccb499 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 14 May 2020 23:29:50 +0200 Subject: [PATCH 182/203] make sure even unleashed miri does not do pointer stuff --- .../ui/consts/miri_unleashed/ptr_arith.rs | 29 ++++++++++++++ .../ui/consts/miri_unleashed/ptr_arith.stderr | 39 +++++++++++++++++++ 2 files changed, 68 insertions(+) create mode 100644 src/test/ui/consts/miri_unleashed/ptr_arith.rs create mode 100644 src/test/ui/consts/miri_unleashed/ptr_arith.stderr diff --git a/src/test/ui/consts/miri_unleashed/ptr_arith.rs b/src/test/ui/consts/miri_unleashed/ptr_arith.rs new file mode 100644 index 000000000000..81985f9f625a --- /dev/null +++ b/src/test/ui/consts/miri_unleashed/ptr_arith.rs @@ -0,0 +1,29 @@ +// compile-flags: -Zunleash-the-miri-inside-of-you +#![feature(core_intrinsics)] +#![allow(const_err)] + +// A test demonstrating that we prevent doing even trivial +// pointer arithmetic or comparison during CTFE. + +static CMP: () = { + let x = &0 as *const _; + let _v = x == x; + //~^ ERROR could not evaluate static initializer + //~| NOTE pointer arithmetic or comparison +}; + +static INT_PTR_ARITH: () = unsafe { + let x: usize = std::mem::transmute(&0); + let _v = x + 0; + //~^ ERROR could not evaluate static initializer + //~| NOTE pointer-to-integer cast +}; + +static PTR_ARITH: () = unsafe { + let x = &0 as *const _; + let _v = core::intrinsics::offset(x, 0); + //~^ ERROR could not evaluate static initializer + //~| NOTE calling intrinsic `offset` +}; + +fn main() {} diff --git a/src/test/ui/consts/miri_unleashed/ptr_arith.stderr b/src/test/ui/consts/miri_unleashed/ptr_arith.stderr new file mode 100644 index 000000000000..5bd534a16b86 --- /dev/null +++ b/src/test/ui/consts/miri_unleashed/ptr_arith.stderr @@ -0,0 +1,39 @@ +error[E0080]: could not evaluate static initializer + --> $DIR/ptr_arith.rs:10:14 + | +LL | let _v = x == x; + | ^^^^^^ "pointer arithmetic or comparison" needs an rfc before being allowed inside constants + +error[E0080]: could not evaluate static initializer + --> $DIR/ptr_arith.rs:17:14 + | +LL | let _v = x + 0; + | ^^^^^ "pointer-to-integer cast" needs an rfc before being allowed inside constants + +error[E0080]: could not evaluate static initializer + --> $DIR/ptr_arith.rs:24:14 + | +LL | let _v = core::intrinsics::offset(x, 0); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ "calling intrinsic `offset`" needs an rfc before being allowed inside constants + +warning: skipping const checks + | +help: skipping check for `const_compare_raw_pointers` feature + --> $DIR/ptr_arith.rs:10:14 + | +LL | let _v = x == x; + | ^^^^^^ +help: skipping check that does not even have a feature gate + --> $DIR/ptr_arith.rs:16:20 + | +LL | let x: usize = std::mem::transmute(&0); + | ^^^^^^^^^^^^^^^^^^^^^^^ +help: skipping check that does not even have a feature gate + --> $DIR/ptr_arith.rs:24:14 + | +LL | let _v = core::intrinsics::offset(x, 0); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 3 previous errors; 1 warning emitted + +For more information about this error, try `rustc --explain E0080`. From 00d42bbd2aa6222dc62177ebcecefd76ca977b9b Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Thu, 14 May 2020 13:03:33 -0300 Subject: [PATCH 183/203] Add prioritize_on attribute to triagebot --- triagebot.toml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/triagebot.toml b/triagebot.toml index 56d29994a8df..2210a8ff8e65 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -36,4 +36,6 @@ label = "ICEBreaker-Cleanup-Crew" [prioritize] label = "I-prioritize" +prioritize_on = ["regression-from-stable-to-stable", "regression-from-stable-to-beta", "regression-from-stable-to-nightly"] +priority_labels = "P-*" zulip_stream = 227806 From e84b379351577cae8cc3e89bf66c71bcabf547d7 Mon Sep 17 00:00:00 2001 From: Wesley Wiser Date: Thu, 23 Apr 2020 17:09:21 -0400 Subject: [PATCH 184/203] [const-prop] Don't replace Rvalues that are already constants --- src/librustc_mir/transform/const_prop.rs | 7 +++++++ .../const_prop/mutable_variable/rustc.main.ConstProp.diff | 3 +-- .../mutable_variable_aggregate/rustc.main.ConstProp.diff | 3 +-- .../rustc.arg_src.CopyPropagation.diff | 2 +- .../copy_propagation_arg/rustc.bar.CopyPropagation.diff | 2 +- 5 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index e898f22ec230..bdf2193c6af4 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -616,6 +616,13 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { value: OpTy<'tcx>, source_info: SourceInfo, ) { + if let Rvalue::Use(Operand::Constant(c)) = rval { + if !matches!(c.literal.val, ConstKind::Unevaluated(..)) { + trace!("skipping replace of Rvalue::Use({:?} because it is already a const", c); + return; + } + } + trace!("attepting to replace {:?} with {:?}", rval, value); if let Err(e) = self.ecx.const_validate_operand( value, diff --git a/src/test/mir-opt/const_prop/mutable_variable/rustc.main.ConstProp.diff b/src/test/mir-opt/const_prop/mutable_variable/rustc.main.ConstProp.diff index c6c5b0cf7263..187c17454350 100644 --- a/src/test/mir-opt/const_prop/mutable_variable/rustc.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/mutable_variable/rustc.main.ConstProp.diff @@ -26,8 +26,7 @@ // + ty: i32 // + val: Value(Scalar(0x00000063)) // mir::Constant -- // + span: $DIR/mutable_variable.rs:6:9: 6:11 -+ // + span: $DIR/mutable_variable.rs:6:5: 6:11 + // + span: $DIR/mutable_variable.rs:6:9: 6:11 // + literal: Const { ty: i32, val: Value(Scalar(0x00000063)) } StorageLive(_2); // scope 1 at $DIR/mutable_variable.rs:7:9: 7:10 - _2 = _1; // scope 1 at $DIR/mutable_variable.rs:7:13: 7:14 diff --git a/src/test/mir-opt/const_prop/mutable_variable_aggregate/rustc.main.ConstProp.diff b/src/test/mir-opt/const_prop/mutable_variable_aggregate/rustc.main.ConstProp.diff index 26f0250d94c0..cf432b2acc1c 100644 --- a/src/test/mir-opt/const_prop/mutable_variable_aggregate/rustc.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/mutable_variable_aggregate/rustc.main.ConstProp.diff @@ -34,8 +34,7 @@ // + ty: i32 // + val: Value(Scalar(0x00000063)) // mir::Constant -- // + span: $DIR/mutable_variable_aggregate.rs:6:11: 6:13 -+ // + span: $DIR/mutable_variable_aggregate.rs:6:5: 6:13 + // + span: $DIR/mutable_variable_aggregate.rs:6:11: 6:13 // + literal: Const { ty: i32, val: Value(Scalar(0x00000063)) } StorageLive(_2); // scope 1 at $DIR/mutable_variable_aggregate.rs:7:9: 7:10 - _2 = _1; // scope 1 at $DIR/mutable_variable_aggregate.rs:7:13: 7:14 diff --git a/src/test/mir-opt/copy_propagation_arg/rustc.arg_src.CopyPropagation.diff b/src/test/mir-opt/copy_propagation_arg/rustc.arg_src.CopyPropagation.diff index b976449ca6d3..1e0271a560f6 100644 --- a/src/test/mir-opt/copy_propagation_arg/rustc.arg_src.CopyPropagation.diff +++ b/src/test/mir-opt/copy_propagation_arg/rustc.arg_src.CopyPropagation.diff @@ -17,7 +17,7 @@ // + ty: i32 // + val: Value(Scalar(0x0000007b)) // mir::Constant - // + span: $DIR/copy_propagation_arg.rs:29:5: 29:12 + // + span: $DIR/copy_propagation_arg.rs:29:9: 29:12 // + literal: Const { ty: i32, val: Value(Scalar(0x0000007b)) } _0 = _2; // scope 1 at $DIR/copy_propagation_arg.rs:30:5: 30:6 StorageDead(_2); // scope 0 at $DIR/copy_propagation_arg.rs:31:1: 31:2 diff --git a/src/test/mir-opt/copy_propagation_arg/rustc.bar.CopyPropagation.diff b/src/test/mir-opt/copy_propagation_arg/rustc.bar.CopyPropagation.diff index 26f8068f674e..b875bbea67bd 100644 --- a/src/test/mir-opt/copy_propagation_arg/rustc.bar.CopyPropagation.diff +++ b/src/test/mir-opt/copy_propagation_arg/rustc.bar.CopyPropagation.diff @@ -28,7 +28,7 @@ // + ty: u8 // + val: Value(Scalar(0x05)) // mir::Constant - // + span: $DIR/copy_propagation_arg.rs:17:5: 17:10 + // + span: $DIR/copy_propagation_arg.rs:17:9: 17:10 // + literal: Const { ty: u8, val: Value(Scalar(0x05)) } _0 = const (); // scope 0 at $DIR/copy_propagation_arg.rs:15:19: 18:2 // ty::Const From 257e3772cb1b434a3c3fc8ac61ef808929036558 Mon Sep 17 00:00:00 2001 From: Lzu Tao Date: Fri, 15 May 2020 04:49:23 +0000 Subject: [PATCH 185/203] doc: add links to rotate_(left|right) --- src/libcore/num/mod.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index a259e293b0c1..9039e71b8286 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -1448,8 +1448,8 @@ any high-order bits of `rhs` that would cause the shift to exceed the bitwidth o Note that this is *not* the same as a rotate-left; the RHS of a wrapping shift-left is restricted to the range of the type, rather than the bits shifted out of the LHS being returned to the other end. -The primitive integer types all implement a `rotate_left` function, which may be what you want -instead. +The primitive integer types all implement a `[`rotate_left`](#method.rotate_left) function, +which may be what you want instead. # Examples @@ -1480,8 +1480,8 @@ removes any high-order bits of `rhs` that would cause the shift to exceed the bi Note that this is *not* the same as a rotate-right; the RHS of a wrapping shift-right is restricted to the range of the type, rather than the bits shifted out of the LHS being returned to the other -end. The primitive integer types all implement a `rotate_right` function, which may be what you want -instead. +end. The primitive integer types all implement a [`rotate_right`](#method.rotate_right) function, +which may be what you want instead. # Examples @@ -3508,8 +3508,8 @@ Note that this is *not* the same as a rotate-left; the RHS of a wrapping shift-left is restricted to the range of the type, rather than the bits shifted out of the LHS being returned to the other end. The primitive integer -types all implement a `rotate_left` function, which may -be what you want instead. +types all implement a [`rotate_left`](#method.rotate_left) function, +which may be what you want instead. # Examples @@ -3542,8 +3542,8 @@ Note that this is *not* the same as a rotate-right; the RHS of a wrapping shift-right is restricted to the range of the type, rather than the bits shifted out of the LHS being returned to the other end. The primitive integer -types all implement a `rotate_right` function, which may -be what you want instead. +types all implement a [`rotate_right`](#method.rotate_right) function, +which may be what you want instead. # Examples From 10d7da4e0b07f469c9d2b8215b563528adfc7e99 Mon Sep 17 00:00:00 2001 From: csmoe Date: Thu, 14 May 2020 23:07:46 +0800 Subject: [PATCH 186/203] implement type_implments_trait query --- src/librustc_middle/hir/map/mod.rs | 2 +- src/librustc_middle/query/mod.rs | 6 +++ src/librustc_middle/ty/query/keys.rs | 12 ++++++ .../traits/error_reporting/suggestions.rs | 37 ++++++++-------- src/librustc_trait_selection/traits/mod.rs | 42 ++++++++++++++++++- src/test/ui/async-await/issue-61076.rs | 20 +++++++++ src/test/ui/async-await/issue-61076.stderr | 16 ++++++- .../ui/async-await/try-on-option-in-async.rs | 3 +- .../async-await/try-on-option-in-async.stderr | 6 +-- .../clippy/clippy_lints/src/utils/mod.rs | 18 +------- 10 files changed, 120 insertions(+), 42 deletions(-) diff --git a/src/librustc_middle/hir/map/mod.rs b/src/librustc_middle/hir/map/mod.rs index a3f8cd1ee36f..b823516d64f3 100644 --- a/src/librustc_middle/hir/map/mod.rs +++ b/src/librustc_middle/hir/map/mod.rs @@ -390,7 +390,7 @@ impl<'hir> Map<'hir> { /// Given a `HirId`, returns the `BodyId` associated with it, /// if the node is a body owner, otherwise returns `None`. pub fn maybe_body_owned_by(&self, hir_id: HirId) -> Option { - if let Some(node) = self.find(hir_id) { associated_body(node) } else { None } + self.find(hir_id).map(associated_body).flatten() } /// Given a body owner's id, returns the `BodyId` associated with it. diff --git a/src/librustc_middle/query/mod.rs b/src/librustc_middle/query/mod.rs index 2ceba5194942..13cf9a934b72 100644 --- a/src/librustc_middle/query/mod.rs +++ b/src/librustc_middle/query/mod.rs @@ -1164,6 +1164,12 @@ rustc_queries! { desc { "evaluating trait selection obligation `{}`", goal.value } } + query type_implements_trait( + key: (DefId, Ty<'tcx>, SubstsRef<'tcx>, ty::ParamEnv<'tcx>, ) + ) -> bool { + desc { "evaluating `type_implements_trait` `{:?}`", key } + } + /// Do not call this query directly: part of the `Eq` type-op query type_op_ascribe_user_type( goal: CanonicalTypeOpAscribeUserTypeGoal<'tcx> diff --git a/src/librustc_middle/ty/query/keys.rs b/src/librustc_middle/ty/query/keys.rs index 239691dbd17a..4acf766f033d 100644 --- a/src/librustc_middle/ty/query/keys.rs +++ b/src/librustc_middle/ty/query/keys.rs @@ -295,3 +295,15 @@ impl Key for (Symbol, u32, u32) { DUMMY_SP } } + +impl<'tcx> Key for (DefId, Ty<'tcx>, SubstsRef<'tcx>, ty::ParamEnv<'tcx>) { + type CacheSelector = DefaultCacheSelector; + + fn query_crate(&self) -> CrateNum { + LOCAL_CRATE + } + + fn default_span(&self, _tcx: TyCtxt<'_>) -> Span { + DUMMY_SP + } +} diff --git a/src/librustc_trait_selection/traits/error_reporting/suggestions.rs b/src/librustc_trait_selection/traits/error_reporting/suggestions.rs index 5e3b383ff258..d5b2b765e939 100644 --- a/src/librustc_trait_selection/traits/error_reporting/suggestions.rs +++ b/src/librustc_trait_selection/traits/error_reporting/suggestions.rs @@ -11,6 +11,7 @@ use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_hir::def_id::DefId; use rustc_hir::intravisit::Visitor; +use rustc_hir::lang_items; use rustc_hir::{AsyncGeneratorKind, GeneratorKind, Node}; use rustc_middle::ty::TypeckTables; use rustc_middle::ty::{ @@ -1785,29 +1786,30 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { span: Span, ) { debug!( - "suggest_await_befor_try: obligation={:?}, span={:?}, trait_ref={:?}", - obligation, span, trait_ref + "suggest_await_befor_try: obligation={:?}, span={:?}, trait_ref={:?}, trait_ref_self_ty={:?}", + obligation, + span, + trait_ref, + trait_ref.self_ty() ); let body_hir_id = obligation.cause.body_id; let item_id = self.tcx.hir().get_parent_node(body_hir_id); - let mut is_future = false; - if let ty::Opaque(def_id, substs) = trait_ref.self_ty().kind { - let preds = self.tcx.predicates_of(def_id).instantiate(self.tcx, substs); - for p in preds.predicates { - if let Some(trait_ref) = p.to_opt_poly_trait_ref() { - if Some(trait_ref.def_id()) == self.tcx.lang_items().future_trait() { - is_future = true; - break; - } - } - } - } - if let Some(body_id) = self.tcx.hir().maybe_body_owned_by(item_id) { let body = self.tcx.hir().body(body_id); if let Some(hir::GeneratorKind::Async(_)) = body.generator_kind { - let future_trait = self.tcx.lang_items().future_trait().unwrap(); + let future_trait = + self.tcx.require_lang_item(lang_items::FutureTraitLangItem, None); + + let self_ty = self.resolve_vars_if_possible(&trait_ref.self_ty()); + + let impls_future = self.tcx.type_implements_trait(( + future_trait, + self_ty, + ty::List::empty(), + obligation.param_env, + )); + let item_def_id = self .tcx .associated_items(future_trait) @@ -1815,7 +1817,6 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { .next() .unwrap() .def_id; - debug!("trait_ref_self_ty: {:?}", trait_ref.self_ty()); // `::Output` let projection_ty = ty::ProjectionTy { // `T` @@ -1850,7 +1851,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { obligation.param_env, ); debug!("suggest_await_befor_try: try_trait_obligation {:?}", try_obligation); - if self.predicate_may_hold(&try_obligation) && is_future { + if self.predicate_may_hold(&try_obligation) && impls_future { if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) { if snippet.ends_with('?') { err.span_suggestion( diff --git a/src/librustc_trait_selection/traits/mod.rs b/src/librustc_trait_selection/traits/mod.rs index 778430fc2ca9..9592f93ce2e7 100644 --- a/src/librustc_trait_selection/traits/mod.rs +++ b/src/librustc_trait_selection/traits/mod.rs @@ -31,7 +31,9 @@ use rustc_hir::def_id::DefId; use rustc_middle::middle::region; use rustc_middle::ty::fold::TypeFoldable; use rustc_middle::ty::subst::{InternalSubsts, SubstsRef}; -use rustc_middle::ty::{self, GenericParamDefKind, ToPredicate, Ty, TyCtxt, WithConstness}; +use rustc_middle::ty::{ + self, GenericParamDefKind, ParamEnv, ToPredicate, Ty, TyCtxt, WithConstness, +}; use rustc_span::Span; use std::fmt::Debug; @@ -523,6 +525,43 @@ fn vtable_methods<'tcx>( })) } +/// Check whether a `ty` implements given trait(trait_def_id). +/// +/// NOTE: Always return `false` for a type which needs inference. +fn type_implements_trait<'tcx>( + tcx: TyCtxt<'tcx>, + key: ( + DefId, // trait_def_id, + Ty<'tcx>, // type + SubstsRef<'tcx>, + ParamEnv<'tcx>, + ), +) -> bool { + let (trait_def_id, ty, params, param_env) = key; + + debug!( + "type_implements_trait: trait_def_id={:?}, type={:?}, params={:?}, param_env={:?}", + trait_def_id, ty, params, param_env + ); + + // Do not check on infer_types to avoid panic in evaluate_obligation. + if ty.has_infer_types() { + return false; + } + + let ty = tcx.erase_regions(&ty); + + let trait_ref = ty::TraitRef { def_id: trait_def_id, substs: tcx.mk_substs_trait(ty, params) }; + + let obligation = Obligation { + cause: ObligationCause::dummy(), + param_env, + recursion_depth: 0, + predicate: trait_ref.without_const().to_predicate(), + }; + tcx.infer_ctxt().enter(|infcx| infcx.predicate_must_hold_modulo_regions(&obligation)) +} + pub fn provide(providers: &mut ty::query::Providers<'_>) { object_safety::provide(providers); *providers = ty::query::Providers { @@ -531,6 +570,7 @@ pub fn provide(providers: &mut ty::query::Providers<'_>) { codegen_fulfill_obligation: codegen::codegen_fulfill_obligation, vtable_methods, substitute_normalize_and_test_predicates, + type_implements_trait, ..*providers }; } diff --git a/src/test/ui/async-await/issue-61076.rs b/src/test/ui/async-await/issue-61076.rs index 04a9148ae241..13b45df64eab 100644 --- a/src/test/ui/async-await/issue-61076.rs +++ b/src/test/ui/async-await/issue-61076.rs @@ -1,5 +1,19 @@ // edition:2018 +use core::future::Future; +use core::pin::Pin; +use core::task::{Context, Poll}; + +struct T; + +impl Future for T { + type Output = Result<(), ()>; + + fn poll(self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll { + Poll::Pending + } +} + async fn foo() -> Result<(), ()> { Ok(()) } @@ -9,4 +23,10 @@ async fn bar() -> Result<(), ()> { Ok(()) } +async fn baz() -> Result<(), ()> { + let t = T; + t?; //~ ERROR the `?` operator can only be applied to values that implement `std::ops::Try` + Ok(()) +} + fn main() {} diff --git a/src/test/ui/async-await/issue-61076.stderr b/src/test/ui/async-await/issue-61076.stderr index fb1eead04e6b..e71f4e7136da 100644 --- a/src/test/ui/async-await/issue-61076.stderr +++ b/src/test/ui/async-await/issue-61076.stderr @@ -1,5 +1,5 @@ error[E0277]: the `?` operator can only be applied to values that implement `std::ops::Try` - --> $DIR/issue-61076.rs:8:5 + --> $DIR/issue-61076.rs:22:5 | LL | foo()?; | ^^^^^^ @@ -10,6 +10,18 @@ LL | foo()?; = help: the trait `std::ops::Try` is not implemented for `impl std::future::Future` = note: required by `std::ops::Try::into_result` -error: aborting due to previous error +error[E0277]: the `?` operator can only be applied to values that implement `std::ops::Try` + --> $DIR/issue-61076.rs:28:5 + | +LL | t?; + | ^^ + | | + | the `?` operator cannot be applied to type `T` + | help: consider using `.await` here: `t.await?` + | + = help: the trait `std::ops::Try` is not implemented for `T` + = note: required by `std::ops::Try::into_result` + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/async-await/try-on-option-in-async.rs b/src/test/ui/async-await/try-on-option-in-async.rs index 51ac522017cb..c520a07abc17 100644 --- a/src/test/ui/async-await/try-on-option-in-async.rs +++ b/src/test/ui/async-await/try-on-option-in-async.rs @@ -7,7 +7,8 @@ async fn an_async_block() -> u32 { let x: Option = None; x?; //~ ERROR the `?` operator 22 - }.await + } + .await } async fn async_closure_containing_fn() -> u32 { diff --git a/src/test/ui/async-await/try-on-option-in-async.stderr b/src/test/ui/async-await/try-on-option-in-async.stderr index 46f8f41076bf..700296d67478 100644 --- a/src/test/ui/async-await/try-on-option-in-async.stderr +++ b/src/test/ui/async-await/try-on-option-in-async.stderr @@ -7,14 +7,14 @@ LL | | let x: Option = None; LL | | x?; | | ^^ cannot use the `?` operator in an async block that returns `{integer}` LL | | 22 -LL | | }.await +LL | | } | |_____- this function should return `Result` or `Option` to accept `?` | = help: the trait `std::ops::Try` is not implemented for `{integer}` = note: required by `std::ops::Try::from_error` error[E0277]: the `?` operator can only be used in an async closure that returns `Result` or `Option` (or another type that implements `std::ops::Try`) - --> $DIR/try-on-option-in-async.rs:16:9 + --> $DIR/try-on-option-in-async.rs:17:9 | LL | let async_closure = async || { | __________________________________- @@ -29,7 +29,7 @@ LL | | }; = note: required by `std::ops::Try::from_error` error[E0277]: the `?` operator can only be used in an async function that returns `Result` or `Option` (or another type that implements `std::ops::Try`) - --> $DIR/try-on-option-in-async.rs:25:5 + --> $DIR/try-on-option-in-async.rs:26:5 | LL | async fn an_async_function() -> u32 { | _____________________________________- diff --git a/src/tools/clippy/clippy_lints/src/utils/mod.rs b/src/tools/clippy/clippy_lints/src/utils/mod.rs index 2fd080e9ef0f..84a324f76c5b 100644 --- a/src/tools/clippy/clippy_lints/src/utils/mod.rs +++ b/src/tools/clippy/clippy_lints/src/utils/mod.rs @@ -40,15 +40,12 @@ use rustc_hir::{ use rustc_infer::infer::TyCtxtInferExt; use rustc_lint::{LateContext, Level, Lint, LintContext}; use rustc_middle::hir::map::Map; -use rustc_middle::traits; use rustc_middle::ty::{self, layout::IntegerExt, subst::GenericArg, Binder, Ty, TyCtxt, TypeFoldable}; use rustc_span::hygiene::{ExpnKind, MacroKind}; use rustc_span::source_map::original_sp; use rustc_span::symbol::{self, kw, Symbol}; use rustc_span::{BytePos, Pos, Span, DUMMY_SP}; use rustc_target::abi::Integer; -use rustc_trait_selection::traits::predicate_for_trait_def; -use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt; use rustc_trait_selection::traits::query::normalize::AtExt; use smallvec::SmallVec; @@ -326,19 +323,8 @@ pub fn implements_trait<'a, 'tcx>( trait_id: DefId, ty_params: &[GenericArg<'tcx>], ) -> bool { - let ty = cx.tcx.erase_regions(&ty); - let obligation = predicate_for_trait_def( - cx.tcx, - cx.param_env, - traits::ObligationCause::dummy(), - trait_id, - 0, - ty, - ty_params, - ); - cx.tcx - .infer_ctxt() - .enter(|infcx| infcx.predicate_must_hold_modulo_regions(&obligation)) + let ty_params = cx.tcx.mk_substs(ty_params.iter()); + cx.tcx.type_implements_trait((trait_id, ty, ty_params, cx.param_env)) } /// Gets the `hir::TraitRef` of the trait the given method is implemented for. From 00268be9da13215398d779b2e344ffa3e300693c Mon Sep 17 00:00:00 2001 From: Nathan Corbyn Date: Thu, 14 May 2020 22:06:44 +0100 Subject: [PATCH 187/203] Remove lang_items\(\).*\.unwrap\(\) --- src/librustc_mir/monomorphize/mod.rs | 4 +++- .../hair/pattern/const_to_pat.rs | 3 ++- .../traits/structural_match.rs | 5 +++-- src/librustc_typeck/check/closure.rs | 6 +++--- src/librustc_typeck/check/demand.rs | 8 ++++---- src/librustc_typeck/check/mod.rs | 16 ++++++++-------- src/librustc_typeck/coherence/builtin.rs | 19 +++++++++++-------- 7 files changed, 34 insertions(+), 27 deletions(-) diff --git a/src/librustc_mir/monomorphize/mod.rs b/src/librustc_mir/monomorphize/mod.rs index 98a3d9584f58..28edd87a3add 100644 --- a/src/librustc_mir/monomorphize/mod.rs +++ b/src/librustc_mir/monomorphize/mod.rs @@ -2,6 +2,8 @@ use rustc_middle::traits; use rustc_middle::ty::adjustment::CustomCoerceUnsized; use rustc_middle::ty::{self, Ty, TyCtxt}; +use rustc_hir::lang_items::CoerceUnsizedTraitLangItem; + pub mod collector; pub mod partitioning; @@ -10,7 +12,7 @@ pub fn custom_coerce_unsize_info<'tcx>( source_ty: Ty<'tcx>, target_ty: Ty<'tcx>, ) -> CustomCoerceUnsized { - let def_id = tcx.lang_items().coerce_unsized_trait().unwrap(); + let def_id = tcx.require_lang_item(CoerceUnsizedTraitLangItem, None); let trait_ref = ty::Binder::bind(ty::TraitRef { def_id, diff --git a/src/librustc_mir_build/hair/pattern/const_to_pat.rs b/src/librustc_mir_build/hair/pattern/const_to_pat.rs index d3129751586a..28ec2ca13d5a 100644 --- a/src/librustc_mir_build/hair/pattern/const_to_pat.rs +++ b/src/librustc_mir_build/hair/pattern/const_to_pat.rs @@ -141,7 +141,8 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> { // code at the moment, because types like `for <'a> fn(&'a ())` do // not *yet* implement `PartialEq`. So for now we leave this here. let ty_is_partial_eq: bool = { - let partial_eq_trait_id = self.tcx().require_lang_item(EqTraitLangItem, None); + let partial_eq_trait_id = + self.tcx().require_lang_item(EqTraitLangItem, Some(self.span)); let obligation: PredicateObligation<'_> = predicate_for_trait_def( self.tcx(), self.param_env, diff --git a/src/librustc_trait_selection/traits/structural_match.rs b/src/librustc_trait_selection/traits/structural_match.rs index 8007290f35d8..eb63505b69b4 100644 --- a/src/librustc_trait_selection/traits/structural_match.rs +++ b/src/librustc_trait_selection/traits/structural_match.rs @@ -4,6 +4,7 @@ use crate::traits::{self, ConstPatternStructural, TraitEngine}; use rustc_data_structures::fx::FxHashSet; use rustc_hir as hir; +use rustc_hir::lang_items::{StructuralPeqTraitLangItem, StructuralTeqTraitLangItem}; use rustc_middle::ty::{self, AdtDef, Ty, TyCtxt, TypeFoldable, TypeVisitor}; use rustc_span::Span; @@ -69,7 +70,7 @@ pub fn type_marked_structural( let mut fulfillment_cx = traits::FulfillmentContext::new(); let cause = ObligationCause::new(span, id, ConstPatternStructural); // require `#[derive(PartialEq)]` - let structural_peq_def_id = infcx.tcx.lang_items().structural_peq_trait().unwrap(); + let structural_peq_def_id = infcx.tcx.require_lang_item(StructuralPeqTraitLangItem, Some(span)); fulfillment_cx.register_bound( infcx, ty::ParamEnv::empty(), @@ -80,7 +81,7 @@ pub fn type_marked_structural( // for now, require `#[derive(Eq)]`. (Doing so is a hack to work around // the type `for<'a> fn(&'a ())` failing to implement `Eq` itself.) let cause = ObligationCause::new(span, id, ConstPatternStructural); - let structural_teq_def_id = infcx.tcx.lang_items().structural_teq_trait().unwrap(); + let structural_teq_def_id = infcx.tcx.require_lang_item(StructuralTeqTraitLangItem, Some(span)); fulfillment_cx.register_bound( infcx, ty::ParamEnv::empty(), diff --git a/src/librustc_typeck/check/closure.rs b/src/librustc_typeck/check/closure.rs index 035e5880dc52..87a6f119acb0 100644 --- a/src/librustc_typeck/check/closure.rs +++ b/src/librustc_typeck/check/closure.rs @@ -6,7 +6,7 @@ use crate::astconv::AstConv; use crate::middle::region; use rustc_hir as hir; use rustc_hir::def_id::DefId; -use rustc_hir::lang_items; +use rustc_hir::lang_items::{FutureTraitLangItem, GeneratorTraitLangItem}; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_infer::infer::LateBoundRegionConversionTime; use rustc_infer::infer::{InferOk, InferResult}; @@ -245,7 +245,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let trait_ref = projection.to_poly_trait_ref(tcx); let is_fn = tcx.fn_trait_kind_from_lang_item(trait_ref.def_id()).is_some(); - let gen_trait = tcx.require_lang_item(lang_items::GeneratorTraitLangItem, cause_span); + let gen_trait = tcx.require_lang_item(GeneratorTraitLangItem, cause_span); let is_gen = gen_trait == trait_ref.def_id(); if !is_fn && !is_gen { debug!("deduce_sig_from_projection: not fn or generator"); @@ -678,7 +678,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Check that this is a projection from the `Future` trait. let trait_ref = predicate.projection_ty.trait_ref(self.tcx); - let future_trait = self.tcx.lang_items().future_trait().unwrap(); + let future_trait = self.tcx.require_lang_item(FutureTraitLangItem, Some(cause_span)); if trait_ref.def_id != future_trait { debug!("deduce_future_output_from_projection: not a future"); return None; diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs index 64de94ea58cf..9694ce9450c2 100644 --- a/src/librustc_typeck/check/demand.rs +++ b/src/librustc_typeck/check/demand.rs @@ -7,7 +7,7 @@ use rustc_trait_selection::traits::{self, ObligationCause}; use rustc_ast::util::parser::PREC_POSTFIX; use rustc_errors::{Applicability, DiagnosticBuilder}; use rustc_hir as hir; -use rustc_hir::lang_items::DerefTraitLangItem; +use rustc_hir::lang_items::{CloneTraitLangItem, DerefTraitLangItem}; use rustc_hir::{is_range_literal, Node}; use rustc_middle::ty::adjustment::AllowTwoPhase; use rustc_middle::ty::{self, AssocItem, Ty, TypeAndMut}; @@ -456,8 +456,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; if self.can_coerce(ref_ty, expected) { let mut sugg_sp = sp; - if let hir::ExprKind::MethodCall(segment, _sp, args) = &expr.kind { - let clone_trait = self.tcx.lang_items().clone_trait().unwrap(); + if let hir::ExprKind::MethodCall(ref segment, sp, ref args) = expr.kind { + let clone_trait = self.tcx.require_lang_item(CloneTraitLangItem, Some(sp)); if let ([arg], Some(true), sym::clone) = ( &args[..], self.tables.borrow().type_dependent_def_id(expr.hir_id).map(|did| { @@ -635,7 +635,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { _ if sp == expr.span && !is_macro => { // Check for `Deref` implementations by constructing a predicate to // prove: `::Output == U` - let deref_trait = self.tcx.require_lang_item(DerefTraitLangItem, Some(expr.span)); + let deref_trait = self.tcx.require_lang_item(DerefTraitLangItem, Some(sp)); let item_def_id = self .tcx .associated_items(deref_trait) diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 956e09ec52b4..f06303ecff98 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -100,7 +100,9 @@ use rustc_hir::def::{CtorOf, DefKind, Res}; use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, DefIdSet, LocalDefId, LOCAL_CRATE}; use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor}; use rustc_hir::itemlikevisit::ItemLikeVisitor; -use rustc_hir::lang_items; +use rustc_hir::lang_items::{ + FutureTraitLangItem, PinTypeLangItem, SizedTraitLangItem, VaListTypeLangItem, +}; use rustc_hir::{ExprKind, GenericArg, HirIdMap, Item, ItemKind, Node, PatKind, QPath}; use rustc_index::bit_set::BitSet; use rustc_index::vec::Idx; @@ -1342,10 +1344,8 @@ fn check_fn<'a, 'tcx>( // C-variadic fns also have a `VaList` input that's not listed in `fn_sig` // (as it's created inside the body itself, not passed in from outside). let maybe_va_list = if fn_sig.c_variadic { - let va_list_did = tcx.require_lang_item( - lang_items::VaListTypeLangItem, - Some(body.params.last().unwrap().span), - ); + let va_list_did = + tcx.require_lang_item(VaListTypeLangItem, Some(body.params.last().unwrap().span)); let region = tcx.mk_region(ty::ReScope(region::Scope { id: body.value.hir_id.local_id, data: region::ScopeData::CallSite, @@ -3303,7 +3303,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { code: traits::ObligationCauseCode<'tcx>, ) { if !ty.references_error() { - let lang_item = self.tcx.require_lang_item(lang_items::SizedTraitLangItem, None); + let lang_item = self.tcx.require_lang_item(SizedTraitLangItem, None); self.require_type_meets(ty, span, code, lang_item); } } @@ -5142,7 +5142,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { _ => {} } let boxed_found = self.tcx.mk_box(found); - let new_found = self.tcx.mk_lang_item(boxed_found, lang_items::PinTypeLangItem).unwrap(); + let new_found = self.tcx.mk_lang_item(boxed_found, PinTypeLangItem).unwrap(); if let (true, Ok(snippet)) = ( self.can_coerce(new_found, expected), self.sess().source_map().span_to_snippet(expr.span), @@ -5298,7 +5298,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let sp = expr.span; // Check for `Future` implementations by constructing a predicate to // prove: `::Output == U` - let future_trait = self.tcx.lang_items().future_trait().unwrap(); + let future_trait = self.tcx.require_lang_item(FutureTraitLangItem, Some(sp)); let item_def_id = self .tcx .associated_items(future_trait) diff --git a/src/librustc_typeck/coherence/builtin.rs b/src/librustc_typeck/coherence/builtin.rs index c01c4d90c8e1..efa3cd9955b4 100644 --- a/src/librustc_typeck/coherence/builtin.rs +++ b/src/librustc_typeck/coherence/builtin.rs @@ -4,7 +4,9 @@ use rustc_errors::struct_span_err; use rustc_hir as hir; use rustc_hir::def_id::{DefId, LocalDefId}; -use rustc_hir::lang_items::UnsizeTraitLangItem; +use rustc_hir::lang_items::{ + CoerceUnsizedTraitLangItem, DispatchFromDynTraitLangItem, UnsizeTraitLangItem, +}; use rustc_hir::ItemKind; use rustc_infer::infer; use rustc_infer::infer::outlives::env::OutlivesEnvironment; @@ -145,11 +147,11 @@ fn visit_implementation_of_coerce_unsized(tcx: TyCtxt<'tcx>, impl_did: LocalDefI fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDefId) { debug!("visit_implementation_of_dispatch_from_dyn: impl_did={:?}", impl_did); - let dispatch_from_dyn_trait = tcx.lang_items().dispatch_from_dyn_trait().unwrap(); - let impl_hir_id = tcx.hir().as_local_hir_id(impl_did); let span = tcx.hir().span(impl_hir_id); + let dispatch_from_dyn_trait = tcx.require_lang_item(DispatchFromDynTraitLangItem, Some(span)); + let source = tcx.type_of(impl_did); assert!(!source.has_escaping_bound_vars()); let target = { @@ -314,22 +316,23 @@ fn visit_implementation_of_dispatch_from_dyn(tcx: TyCtxt<'_>, impl_did: LocalDef pub fn coerce_unsized_info(tcx: TyCtxt<'tcx>, impl_did: DefId) -> CoerceUnsizedInfo { debug!("compute_coerce_unsized_info(impl_did={:?})", impl_did); - let coerce_unsized_trait = tcx.lang_items().coerce_unsized_trait().unwrap(); + + // this provider should only get invoked for local def-ids + let impl_hir_id = tcx.hir().as_local_hir_id(impl_did.expect_local()); + let span = tcx.hir().span(impl_hir_id); + + let coerce_unsized_trait = tcx.require_lang_item(CoerceUnsizedTraitLangItem, Some(span)); let unsize_trait = tcx.lang_items().require(UnsizeTraitLangItem).unwrap_or_else(|err| { tcx.sess.fatal(&format!("`CoerceUnsized` implementation {}", err)); }); - // this provider should only get invoked for local def-ids - let impl_hir_id = tcx.hir().as_local_hir_id(impl_did.expect_local()); - let source = tcx.type_of(impl_did); let trait_ref = tcx.impl_trait_ref(impl_did).unwrap(); assert_eq!(trait_ref.def_id, coerce_unsized_trait); let target = trait_ref.substs.type_at(1); debug!("visit_implementation_of_coerce_unsized: {:?} -> {:?} (bound)", source, target); - let span = tcx.hir().span(impl_hir_id); let param_env = tcx.param_env(impl_did); assert!(!source.has_escaping_bound_vars()); From 084cdde976e2485104bc14b8079238b37ab8aac1 Mon Sep 17 00:00:00 2001 From: SOFe Date: Fri, 15 May 2020 22:41:36 +0800 Subject: [PATCH 188/203] Updated documentation of Prefix::VerbatimDisk PrefixComponent with Prefix::VerbatimDisk does not contain the trailing slash. The documentation here is also inconsistent with the documentation on other variants that reflect the `PrefixComponent::as_os_str()` return value. --- src/libstd/path.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libstd/path.rs b/src/libstd/path.rs index 173d6d1cfa7e..8516e80f3b87 100644 --- a/src/libstd/path.rs +++ b/src/libstd/path.rs @@ -157,10 +157,10 @@ pub enum Prefix<'a> { #[stable(feature = "rust1", since = "1.0.0")] &'a OsStr, ), - /// Verbatim disk prefix, e.g., `\\?\C:\`. + /// Verbatim disk prefix, e.g., `\\?\C:`. /// /// Verbatim disk prefixes consist of `\\?\` immediately followed by the - /// drive letter and `:\`. + /// drive letter and `:`. #[stable(feature = "rust1", since = "1.0.0")] VerbatimDisk(#[stable(feature = "rust1", since = "1.0.0")] u8), From 45ee3360072a4bed1a2625dc03bdae1bd5aee5c4 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Thu, 14 May 2020 22:36:17 -0700 Subject: [PATCH 189/203] Fix {:#?} representation of proc_macro::Literal Before: TokenStream [ Ident { ident: "name", span: #0 bytes(37..41), }, Punct { ch: '=', spacing: Alone, span: #0 bytes(42..43), }, Literal { lit: Lit { kind: Str, symbol: "SNPP", suffix: None }, span: Span { lo: BytePos(44), hi: BytePos(50), ctxt: #0 } }, Punct { ch: ',', spacing: Alone, span: #0 bytes(50..51), }, Ident { ident: "owner", span: #0 bytes(56..61), }, Punct { ch: '=', spacing: Alone, span: #0 bytes(62..63), }, Literal { lit: Lit { kind: Str, symbol: "Canary M Burns", suffix: None }, span: Span { lo: BytePos(64), hi: BytePos(80), ctxt: #0 } }, ] After: TokenStream [ Ident { ident: "name", span: #0 bytes(37..41), }, Punct { ch: '=', spacing: Alone, span: #0 bytes(42..43), }, Literal { kind: Str, symbol: "SNPP", suffix: None, span: #0 bytes(44..50), }, Punct { ch: ',', spacing: Alone, span: #0 bytes(50..51), }, Ident { ident: "owner", span: #0 bytes(56..61), }, Punct { ch: '=', spacing: Alone, span: #0 bytes(62..63), }, Literal { kind: Str, symbol: "Canary M Burns", suffix: None, span: #0 bytes(64..80), }, ] --- src/libproc_macro/bridge/client.rs | 9 +++++++-- src/libproc_macro/bridge/mod.rs | 5 +++-- src/libproc_macro/lib.rs | 1 - src/librustc_expand/proc_macro_server.rs | 11 ++++++++--- .../redundant-semi-proc-macro.stderr | 2 +- 5 files changed, 19 insertions(+), 9 deletions(-) diff --git a/src/libproc_macro/bridge/client.rs b/src/libproc_macro/bridge/client.rs index d2222d12623f..a8f6a90ef763 100644 --- a/src/libproc_macro/bridge/client.rs +++ b/src/libproc_macro/bridge/client.rs @@ -202,10 +202,15 @@ impl Clone for Literal { } } -// FIXME(eddyb) `Literal` should not expose internal `Debug` impls. impl fmt::Debug for Literal { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.write_str(&self.debug()) + f.debug_struct("Literal") + .field("kind", &format_args!("{}", &self.debug_kind())) + .field("symbol", &self.symbol()) + // format `Some("...")` on one line even in {:#?} mode + .field("suffix", &format_args!("{:?}", &self.suffix())) + .field("span", &self.span()) + .finish() } } diff --git a/src/libproc_macro/bridge/mod.rs b/src/libproc_macro/bridge/mod.rs index a0e7d90f4974..bf0d8fcee5b8 100644 --- a/src/libproc_macro/bridge/mod.rs +++ b/src/libproc_macro/bridge/mod.rs @@ -103,8 +103,9 @@ macro_rules! with_api { Literal { fn drop($self: $S::Literal); fn clone($self: &$S::Literal) -> $S::Literal; - // FIXME(eddyb) `Literal` should not expose internal `Debug` impls. - fn debug($self: &$S::Literal) -> String; + fn debug_kind($self: &$S::Literal) -> String; + fn symbol($self: &$S::Literal) -> String; + fn suffix($self: &$S::Literal) -> Option; fn integer(n: &str) -> $S::Literal; fn typed_integer(n: &str, kind: &str) -> $S::Literal; fn float(n: &str) -> $S::Literal; diff --git a/src/libproc_macro/lib.rs b/src/libproc_macro/lib.rs index 31bc61263abe..f34a39996fe3 100644 --- a/src/libproc_macro/lib.rs +++ b/src/libproc_macro/lib.rs @@ -1134,7 +1134,6 @@ impl fmt::Display for Literal { #[stable(feature = "proc_macro_lib2", since = "1.29.0")] impl fmt::Debug for Literal { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - // FIXME(eddyb) `Literal` should not expose internal `Debug` impls. self.0.fmt(f) } } diff --git a/src/librustc_expand/proc_macro_server.rs b/src/librustc_expand/proc_macro_server.rs index afc6dc36eb43..b9693c2c8627 100644 --- a/src/librustc_expand/proc_macro_server.rs +++ b/src/librustc_expand/proc_macro_server.rs @@ -507,9 +507,14 @@ impl server::Ident for Rustc<'_> { } impl server::Literal for Rustc<'_> { - // FIXME(eddyb) `Literal` should not expose internal `Debug` impls. - fn debug(&mut self, literal: &Self::Literal) -> String { - format!("{:?}", literal) + fn debug_kind(&mut self, literal: &Self::Literal) -> String { + format!("{:?}", literal.lit.kind) + } + fn symbol(&mut self, literal: &Self::Literal) -> String { + literal.lit.symbol.to_string() + } + fn suffix(&mut self, literal: &Self::Literal) -> Option { + literal.lit.suffix.as_ref().map(Symbol::to_string) } fn integer(&mut self, n: &str) -> Self::Literal { self.lit(token::Integer, Symbol::intern(n), None) diff --git a/src/test/ui/lint/redundant-semicolon/redundant-semi-proc-macro.stderr b/src/test/ui/lint/redundant-semicolon/redundant-semi-proc-macro.stderr index a79fba9bf3f0..bc0c53303241 100644 --- a/src/test/ui/lint/redundant-semicolon/redundant-semi-proc-macro.stderr +++ b/src/test/ui/lint/redundant-semicolon/redundant-semi-proc-macro.stderr @@ -1,4 +1,4 @@ -TokenStream [Ident { ident: "fn", span: #0 bytes(198..200) }, Ident { ident: "span_preservation", span: #0 bytes(201..218) }, Group { delimiter: Parenthesis, stream: TokenStream [], span: #0 bytes(218..220) }, Group { delimiter: Brace, stream: TokenStream [Ident { ident: "let", span: #0 bytes(228..231) }, Ident { ident: "tst", span: #0 bytes(232..235) }, Punct { ch: '=', spacing: Alone, span: #0 bytes(236..237) }, Literal { lit: Lit { kind: Integer, symbol: "123", suffix: None }, span: Span { lo: BytePos(238), hi: BytePos(241), ctxt: #0 } }, Punct { ch: ';', spacing: Joint, span: #0 bytes(241..242) }, Punct { ch: ';', spacing: Alone, span: #0 bytes(242..243) }, Ident { ident: "match", span: #0 bytes(289..294) }, Ident { ident: "tst", span: #0 bytes(295..298) }, Group { delimiter: Brace, stream: TokenStream [Literal { lit: Lit { kind: Integer, symbol: "123", suffix: None }, span: Span { lo: BytePos(483), hi: BytePos(486), ctxt: #0 } }, Punct { ch: '=', spacing: Joint, span: #0 bytes(487..489) }, Punct { ch: '>', spacing: Alone, span: #0 bytes(487..489) }, Group { delimiter: Parenthesis, stream: TokenStream [], span: #0 bytes(490..492) }, Punct { ch: ',', spacing: Alone, span: #0 bytes(492..493) }, Ident { ident: "_", span: #0 bytes(502..503) }, Punct { ch: '=', spacing: Joint, span: #0 bytes(504..506) }, Punct { ch: '>', spacing: Alone, span: #0 bytes(504..506) }, Group { delimiter: Parenthesis, stream: TokenStream [], span: #0 bytes(507..509) }], span: #0 bytes(299..515) }, Punct { ch: ';', spacing: Joint, span: #0 bytes(515..516) }, Punct { ch: ';', spacing: Joint, span: #0 bytes(516..517) }, Punct { ch: ';', spacing: Alone, span: #0 bytes(517..518) }], span: #0 bytes(222..562) }] +TokenStream [Ident { ident: "fn", span: #0 bytes(198..200) }, Ident { ident: "span_preservation", span: #0 bytes(201..218) }, Group { delimiter: Parenthesis, stream: TokenStream [], span: #0 bytes(218..220) }, Group { delimiter: Brace, stream: TokenStream [Ident { ident: "let", span: #0 bytes(228..231) }, Ident { ident: "tst", span: #0 bytes(232..235) }, Punct { ch: '=', spacing: Alone, span: #0 bytes(236..237) }, Literal { kind: Integer, symbol: "123", suffix: None, span: #0 bytes(238..241) }, Punct { ch: ';', spacing: Joint, span: #0 bytes(241..242) }, Punct { ch: ';', spacing: Alone, span: #0 bytes(242..243) }, Ident { ident: "match", span: #0 bytes(289..294) }, Ident { ident: "tst", span: #0 bytes(295..298) }, Group { delimiter: Brace, stream: TokenStream [Literal { kind: Integer, symbol: "123", suffix: None, span: #0 bytes(483..486) }, Punct { ch: '=', spacing: Joint, span: #0 bytes(487..489) }, Punct { ch: '>', spacing: Alone, span: #0 bytes(487..489) }, Group { delimiter: Parenthesis, stream: TokenStream [], span: #0 bytes(490..492) }, Punct { ch: ',', spacing: Alone, span: #0 bytes(492..493) }, Ident { ident: "_", span: #0 bytes(502..503) }, Punct { ch: '=', spacing: Joint, span: #0 bytes(504..506) }, Punct { ch: '>', spacing: Alone, span: #0 bytes(504..506) }, Group { delimiter: Parenthesis, stream: TokenStream [], span: #0 bytes(507..509) }], span: #0 bytes(299..515) }, Punct { ch: ';', spacing: Joint, span: #0 bytes(515..516) }, Punct { ch: ';', spacing: Joint, span: #0 bytes(516..517) }, Punct { ch: ';', spacing: Alone, span: #0 bytes(517..518) }], span: #0 bytes(222..562) }] error: unnecessary trailing semicolon --> $DIR/redundant-semi-proc-macro.rs:9:19 | From 4c4b4c4ab407f0ccdfc71caf443735e5ba62539c Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Fri, 15 May 2020 09:01:26 -0700 Subject: [PATCH 190/203] Add test of proc_macro::TokenStream's Debug --- .../debug/auxiliary/macro-dump-debug.rs | 15 ++ src/test/ui/proc-macro/debug/dump-debug.rs | 40 +++++ .../ui/proc-macro/debug/dump-debug.stderr | 166 ++++++++++++++++++ 3 files changed, 221 insertions(+) create mode 100644 src/test/ui/proc-macro/debug/auxiliary/macro-dump-debug.rs create mode 100644 src/test/ui/proc-macro/debug/dump-debug.rs create mode 100644 src/test/ui/proc-macro/debug/dump-debug.stderr diff --git a/src/test/ui/proc-macro/debug/auxiliary/macro-dump-debug.rs b/src/test/ui/proc-macro/debug/auxiliary/macro-dump-debug.rs new file mode 100644 index 000000000000..56ad0612f74b --- /dev/null +++ b/src/test/ui/proc-macro/debug/auxiliary/macro-dump-debug.rs @@ -0,0 +1,15 @@ +// force-host +// no-prefer-dynamic + +#![crate_type = "proc-macro"] +#![crate_name = "macro_dump_debug"] + +extern crate proc_macro; +use proc_macro::TokenStream; + +#[proc_macro] +pub fn dump_debug(tokens: TokenStream) -> TokenStream { + eprintln!("{:?}", tokens); + eprintln!("{:#?}", tokens); + TokenStream::new() +} diff --git a/src/test/ui/proc-macro/debug/dump-debug.rs b/src/test/ui/proc-macro/debug/dump-debug.rs new file mode 100644 index 000000000000..0ed36b690f49 --- /dev/null +++ b/src/test/ui/proc-macro/debug/dump-debug.rs @@ -0,0 +1,40 @@ +// run-pass +// aux-build:macro-dump-debug.rs + +extern crate macro_dump_debug; +use macro_dump_debug::dump_debug; + +dump_debug! { + ident // ident + r#ident // raw ident + , // alone punct + ==> // joint punct + () // empty group + [_] // nonempty group + + // unsuffixed literals + 0 + 1.0 + "S" + b"B" + r"R" + r##"R"## + br"BR" + br##"BR"## + 'C' + b'B' + + // suffixed literals + 0q + 1.0q + "S"q + b"B"q + r"R"q + r##"R"##q + br"BR"q + br##"BR"##q + 'C'q + b'B'q +} + +fn main() {} diff --git a/src/test/ui/proc-macro/debug/dump-debug.stderr b/src/test/ui/proc-macro/debug/dump-debug.stderr new file mode 100644 index 000000000000..0aedefd4e609 --- /dev/null +++ b/src/test/ui/proc-macro/debug/dump-debug.stderr @@ -0,0 +1,166 @@ +TokenStream [Ident { ident: "ident", span: #0 bytes(130..135) }, Ident { ident: "r#ident", span: #0 bytes(151..158) }, Punct { ch: ',', spacing: Alone, span: #0 bytes(176..177) }, Punct { ch: '=', spacing: Joint, span: #0 bytes(203..205) }, Punct { ch: '=', spacing: Joint, span: #0 bytes(203..205) }, Punct { ch: '>', spacing: Alone, span: #0 bytes(205..206) }, Group { delimiter: Parenthesis, stream: TokenStream [], span: #0 bytes(230..232) }, Group { delimiter: Bracket, stream: TokenStream [Ident { ident: "_", span: #0 bytes(258..259) }], span: #0 bytes(257..260) }, Literal { kind: Integer, symbol: "0", suffix: None, span: #0 bytes(315..316) }, Literal { kind: Float, symbol: "1.0", suffix: None, span: #0 bytes(321..324) }, Literal { kind: Str, symbol: "S", suffix: None, span: #0 bytes(329..332) }, Literal { kind: ByteStr, symbol: "B", suffix: None, span: #0 bytes(337..341) }, Literal { kind: StrRaw(0), symbol: "R", suffix: None, span: #0 bytes(346..350) }, Literal { kind: StrRaw(2), symbol: "R", suffix: None, span: #0 bytes(355..363) }, Literal { kind: ByteStrRaw(0), symbol: "BR", suffix: None, span: #0 bytes(368..374) }, Literal { kind: ByteStrRaw(2), symbol: "BR", suffix: None, span: #0 bytes(379..389) }, Literal { kind: Char, symbol: "C", suffix: None, span: #0 bytes(394..397) }, Literal { kind: Byte, symbol: "B", suffix: None, span: #0 bytes(402..406) }, Literal { kind: Integer, symbol: "0", suffix: Some("q"), span: #0 bytes(437..439) }, Literal { kind: Float, symbol: "1.0", suffix: Some("q"), span: #0 bytes(444..448) }, Literal { kind: Str, symbol: "S", suffix: Some("q"), span: #0 bytes(453..457) }, Literal { kind: ByteStr, symbol: "B", suffix: Some("q"), span: #0 bytes(462..467) }, Literal { kind: StrRaw(0), symbol: "R", suffix: Some("q"), span: #0 bytes(472..477) }, Literal { kind: StrRaw(2), symbol: "R", suffix: Some("q"), span: #0 bytes(482..491) }, Literal { kind: ByteStrRaw(0), symbol: "BR", suffix: Some("q"), span: #0 bytes(496..503) }, Literal { kind: ByteStrRaw(2), symbol: "BR", suffix: Some("q"), span: #0 bytes(508..519) }, Literal { kind: Char, symbol: "C", suffix: Some("q"), span: #0 bytes(524..528) }, Literal { kind: Byte, symbol: "B", suffix: Some("q"), span: #0 bytes(533..538) }] +TokenStream [ + Ident { + ident: "ident", + span: #0 bytes(130..135), + }, + Ident { + ident: "r#ident", + span: #0 bytes(151..158), + }, + Punct { + ch: ',', + spacing: Alone, + span: #0 bytes(176..177), + }, + Punct { + ch: '=', + spacing: Joint, + span: #0 bytes(203..205), + }, + Punct { + ch: '=', + spacing: Joint, + span: #0 bytes(203..205), + }, + Punct { + ch: '>', + spacing: Alone, + span: #0 bytes(205..206), + }, + Group { + delimiter: Parenthesis, + stream: TokenStream [], + span: #0 bytes(230..232), + }, + Group { + delimiter: Bracket, + stream: TokenStream [ + Ident { + ident: "_", + span: #0 bytes(258..259), + }, + ], + span: #0 bytes(257..260), + }, + Literal { + kind: Integer, + symbol: "0", + suffix: None, + span: #0 bytes(315..316), + }, + Literal { + kind: Float, + symbol: "1.0", + suffix: None, + span: #0 bytes(321..324), + }, + Literal { + kind: Str, + symbol: "S", + suffix: None, + span: #0 bytes(329..332), + }, + Literal { + kind: ByteStr, + symbol: "B", + suffix: None, + span: #0 bytes(337..341), + }, + Literal { + kind: StrRaw(0), + symbol: "R", + suffix: None, + span: #0 bytes(346..350), + }, + Literal { + kind: StrRaw(2), + symbol: "R", + suffix: None, + span: #0 bytes(355..363), + }, + Literal { + kind: ByteStrRaw(0), + symbol: "BR", + suffix: None, + span: #0 bytes(368..374), + }, + Literal { + kind: ByteStrRaw(2), + symbol: "BR", + suffix: None, + span: #0 bytes(379..389), + }, + Literal { + kind: Char, + symbol: "C", + suffix: None, + span: #0 bytes(394..397), + }, + Literal { + kind: Byte, + symbol: "B", + suffix: None, + span: #0 bytes(402..406), + }, + Literal { + kind: Integer, + symbol: "0", + suffix: Some("q"), + span: #0 bytes(437..439), + }, + Literal { + kind: Float, + symbol: "1.0", + suffix: Some("q"), + span: #0 bytes(444..448), + }, + Literal { + kind: Str, + symbol: "S", + suffix: Some("q"), + span: #0 bytes(453..457), + }, + Literal { + kind: ByteStr, + symbol: "B", + suffix: Some("q"), + span: #0 bytes(462..467), + }, + Literal { + kind: StrRaw(0), + symbol: "R", + suffix: Some("q"), + span: #0 bytes(472..477), + }, + Literal { + kind: StrRaw(2), + symbol: "R", + suffix: Some("q"), + span: #0 bytes(482..491), + }, + Literal { + kind: ByteStrRaw(0), + symbol: "BR", + suffix: Some("q"), + span: #0 bytes(496..503), + }, + Literal { + kind: ByteStrRaw(2), + symbol: "BR", + suffix: Some("q"), + span: #0 bytes(508..519), + }, + Literal { + kind: Char, + symbol: "C", + suffix: Some("q"), + span: #0 bytes(524..528), + }, + Literal { + kind: Byte, + symbol: "B", + suffix: Some("q"), + span: #0 bytes(533..538), + }, +] From d5ea92526549e40ff43b34f25fe6bee4418a3186 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Fri, 15 May 2020 09:12:41 -0700 Subject: [PATCH 191/203] Implement Default for proc_macro::TokenStream --- src/libproc_macro/lib.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/libproc_macro/lib.rs b/src/libproc_macro/lib.rs index 31bc61263abe..b6544341fa95 100644 --- a/src/libproc_macro/lib.rs +++ b/src/libproc_macro/lib.rs @@ -158,6 +158,13 @@ impl fmt::Debug for TokenStream { } } +#[stable(feature = "proc_macro_token_stream_default", since = "1.45.0")] +impl Default for TokenStream { + fn default() -> Self { + TokenStream::new() + } +} + #[unstable(feature = "proc_macro_quote", issue = "54722")] pub use quote::{quote, quote_span}; From bea2c59ea56cb3daa7e3bacabd7c95f002f9aca0 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Fri, 15 May 2020 09:35:46 -0700 Subject: [PATCH 192/203] Clarify use of format_args in Debug for Literal --- src/libproc_macro/bridge/client.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libproc_macro/bridge/client.rs b/src/libproc_macro/bridge/client.rs index a8f6a90ef763..283aa25b0ea1 100644 --- a/src/libproc_macro/bridge/client.rs +++ b/src/libproc_macro/bridge/client.rs @@ -205,6 +205,7 @@ impl Clone for Literal { impl fmt::Debug for Literal { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("Literal") + // format the kind without quotes, as in `kind: Float` .field("kind", &format_args!("{}", &self.debug_kind())) .field("symbol", &self.symbol()) // format `Some("...")` on one line even in {:#?} mode From 7433c4ddf3c226fc6beeed7a79f7d48777a3e807 Mon Sep 17 00:00:00 2001 From: Diggory Blake Date: Mon, 27 Apr 2020 22:50:55 +0100 Subject: [PATCH 193/203] Improve the documentation for ManuallyDrop to resolve conflicting usage of terminology. --- src/libcore/mem/manually_drop.rs | 39 ++++++++++++++++++++++++-------- src/libcore/ptr/mod.rs | 8 ++++++- 2 files changed, 36 insertions(+), 11 deletions(-) diff --git a/src/libcore/mem/manually_drop.rs b/src/libcore/mem/manually_drop.rs index 9e5c2b10d0d9..17863dd38afe 100644 --- a/src/libcore/mem/manually_drop.rs +++ b/src/libcore/mem/manually_drop.rs @@ -7,14 +7,14 @@ use crate::ptr; /// /// `ManuallyDrop` is subject to the same layout optimizations as `T`. /// As a consequence, it has *no effect* on the assumptions that the compiler makes -/// about all values being initialized at their type. In particular, initializing -/// a `ManuallyDrop<&mut T>` with [`mem::zeroed`] is undefined behavior. +/// about its contents. For example, initializing a `ManuallyDrop<&mut T>` +/// with [`mem::zeroed`] is undefined behavior. /// If you need to handle uninitialized data, use [`MaybeUninit`] instead. /// /// # Examples /// -/// This wrapper helps with explicitly documenting the drop order dependencies between fields of -/// the type: +/// This wrapper can be used to enforce a particular drop order on fields, regardless +/// of how they are defined in the struct: /// /// ```rust /// use std::mem::ManuallyDrop; @@ -43,8 +43,18 @@ use crate::ptr; /// } /// ``` /// +/// However, care should be taken when using this pattern as it can lead to *leak amplification*. +/// In this example, if the `Drop` implementation for `Peach` were to panic, the `banana` field +/// would also be leaked. +/// +/// In contrast, the automatically-generated compiler drop implementation would have ensured +/// that all fields are dropped even in the presence of panics. This is especially important when +/// working with [pinned] data, where reusing the memory without calling the destructor could lead +/// to Undefined Behaviour. +/// /// [`mem::zeroed`]: fn.zeroed.html /// [`MaybeUninit`]: union.MaybeUninit.html +/// [pinned]: ../pin/index.html #[stable(feature = "manually_drop", since = "1.20.0")] #[lang = "manually_drop"] #[derive(Copy, Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)] @@ -113,19 +123,28 @@ impl ManuallyDrop { } impl ManuallyDrop { - /// Manually drops the contained value. + /// Manually drops the contained value. This is exactly equivalent to calling + /// [`ptr::drop_in_place`] with a pointer to the contained value. As such, unless + /// the contained value is a packed struct, the destructor will be called in-place + /// without moving the value, and thus can be used to safely drop [pinned] data. /// /// If you have ownership of the value, you can use [`ManuallyDrop::into_inner`] instead. /// /// # Safety /// - /// This function runs the destructor of the contained value and thus the wrapped value - /// now represents uninitialized data. It is up to the user of this method to ensure the - /// uninitialized data is not actually used. - /// In particular, this function can only be called at most once - /// for a given instance of `ManuallyDrop`. + /// This function runs the destructor of the contained value. Other than changes made by + /// the destructor itself, the memory is left unchanged, and so as far as the compiler is + /// concerned still holds a bit-pattern which is valid for the type `T`. + /// + /// However, this "zombie" value should not be exposed to safe code, and this function + /// should not be called more than once. To use a value after it's been dropped, or drop + /// a value multiple times, can cause Undefined Behavior (depending on what `drop` does). + /// This is normally prevented by the type system, but users of `ManuallyDrop` must + /// uphold those guarantees without assistance from the compiler. /// /// [`ManuallyDrop::into_inner`]: #method.into_inner + /// [`ptr::drop_in_place`]: ../ptr/fn.drop_in_place.html + /// [pinned]: ../pin/index.html #[stable(feature = "manually_drop", since = "1.20.0")] #[inline] pub unsafe fn drop(slot: &mut ManuallyDrop) { diff --git a/src/libcore/ptr/mod.rs b/src/libcore/ptr/mod.rs index 84f28488c74b..115194a65a0c 100644 --- a/src/libcore/ptr/mod.rs +++ b/src/libcore/ptr/mod.rs @@ -112,11 +112,17 @@ mod mut_ptr; /// as the compiler doesn't need to prove that it's sound to elide the /// copy. /// +/// * It can be used to drop [pinned] data when `T` is not `repr(packed)` +/// (pinned data must not be moved before it is dropped). +/// /// Unaligned values cannot be dropped in place, they must be copied to an aligned -/// location first using [`ptr::read_unaligned`]. +/// location first using [`ptr::read_unaligned`]. For packed structs, this move is +/// done automatically by the compiler. This means the fields of packed structs +/// are not dropped in-place. /// /// [`ptr::read`]: ../ptr/fn.read.html /// [`ptr::read_unaligned`]: ../ptr/fn.read_unaligned.html +/// [pinned]: ../pin/index.html /// /// # Safety /// From 004f4f389e5cf5cbb1f9604c5f7691cd16b1966e Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Fri, 15 May 2020 20:51:12 -0700 Subject: [PATCH 194/203] Remove redundant backtick in error message. The value passed in already has backticks surrounding the text. --- src/librustc_parse/parser/diagnostics.rs | 2 +- src/test/ui/parser/issue-3036.stderr | 2 +- src/test/ui/parser/recover-missing-semi.stderr | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/librustc_parse/parser/diagnostics.rs b/src/librustc_parse/parser/diagnostics.rs index 437d0ffa1196..93c7faf22a73 100644 --- a/src/librustc_parse/parser/diagnostics.rs +++ b/src/librustc_parse/parser/diagnostics.rs @@ -927,7 +927,7 @@ impl<'a> Parser<'a> { return Ok(()); } let sm = self.sess.source_map(); - let msg = format!("expected `;`, found `{}`", super::token_descr(&self.token)); + let msg = format!("expected `;`, found {}", super::token_descr(&self.token)); let appl = Applicability::MachineApplicable; if self.token.span == DUMMY_SP || self.prev_token.span == DUMMY_SP { // Likely inside a macro, can't provide meaningful suggestions. diff --git a/src/test/ui/parser/issue-3036.stderr b/src/test/ui/parser/issue-3036.stderr index b6557163d452..e5f5a7d8968d 100644 --- a/src/test/ui/parser/issue-3036.stderr +++ b/src/test/ui/parser/issue-3036.stderr @@ -1,4 +1,4 @@ -error: expected `;`, found ``}`` +error: expected `;`, found `}` --> $DIR/issue-3036.rs:5:14 | LL | let x = 3 diff --git a/src/test/ui/parser/recover-missing-semi.stderr b/src/test/ui/parser/recover-missing-semi.stderr index 2f2464d3629c..ba4798285387 100644 --- a/src/test/ui/parser/recover-missing-semi.stderr +++ b/src/test/ui/parser/recover-missing-semi.stderr @@ -1,4 +1,4 @@ -error: expected `;`, found `keyword `let`` +error: expected `;`, found keyword `let` --> $DIR/recover-missing-semi.rs:2:22 | LL | let _: usize = () @@ -7,7 +7,7 @@ LL | let _: usize = () LL | let _ = 3; | --- unexpected token -error: expected `;`, found `keyword `return`` +error: expected `;`, found keyword `return` --> $DIR/recover-missing-semi.rs:9:22 | LL | let _: usize = () From 78eb64f35acf2c998c2ea6d9007f18d247d4ce88 Mon Sep 17 00:00:00 2001 From: Rustin-Liu Date: Sat, 16 May 2020 14:40:45 +0800 Subject: [PATCH 195/203] Fix typo Arbintrary to Arbitrary Signed-off-by: Rustin-Liu --- src/librustc_error_codes/error_codes/E0307.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_error_codes/error_codes/E0307.md b/src/librustc_error_codes/error_codes/E0307.md index 52707b93acc8..0d29d56ea1a7 100644 --- a/src/librustc_error_codes/error_codes/E0307.md +++ b/src/librustc_error_codes/error_codes/E0307.md @@ -64,7 +64,7 @@ impl Trait for Foo { } ``` -The nightly feature [Arbintrary self types][AST] extends the accepted +The nightly feature [Arbitrary self types][AST] extends the accepted set of receiver types to also include any type that can dereference to `Self`: From 2e1c2a6d0a0d3785802c73d13039a0f0eea36b7c Mon Sep 17 00:00:00 2001 From: csmoe Date: Sat, 16 May 2020 18:29:46 +0800 Subject: [PATCH 196/203] break out earlier on empty snippet --- src/librustc_span/source_map.rs | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/src/librustc_span/source_map.rs b/src/librustc_span/source_map.rs index d27aae0d6ed9..51f554176630 100644 --- a/src/librustc_span/source_map.rs +++ b/src/librustc_span/source_map.rs @@ -910,14 +910,23 @@ impl SourceMap { pub fn generate_fn_name_span(&self, span: Span) -> Option { let prev_span = self.span_extend_to_prev_str(span, "fn", true); - self.span_to_snippet(prev_span) - .map(|snippet| { - let len = snippet - .find(|c: char| !c.is_alphanumeric() && c != '_') - .expect("no label after fn"); - prev_span.with_hi(BytePos(prev_span.lo().0 + len as u32)) - }) - .ok() + if let Ok(snippet) = self.span_to_snippet(prev_span) { + debug!( + "generate_fn_name_span: span={:?}, prev_span={:?}, snippet={:?}", + span, prev_span, snippet + ); + + if snippet.is_empty() { + return None; + }; + + let len = snippet + .find(|c: char| !c.is_alphanumeric() && c != '_') + .expect("no label after fn"); + Some(prev_span.with_hi(BytePos(prev_span.lo().0 + len as u32))) + } else { + None + } } /// Takes the span of a type parameter in a function signature and try to generate a span for From de24ddac0a80a6e16de1bfbfade772648cf66e18 Mon Sep 17 00:00:00 2001 From: Charles Lew Date: Sat, 16 May 2020 14:09:01 +0800 Subject: [PATCH 197/203] Disallow forbidden usage of non-ascii identifiers. --- src/librustc_ast_passes/ast_validation.rs | 39 ++++++++++++++++++- src/librustc_error_codes/error_codes.rs | 1 + src/librustc_error_codes/error_codes/E0754.md | 33 ++++++++++++++++ ...mod_file_nonascii_with_path_allowed-aux.rs | 1 + .../rfc-2457/mod_file_nonascii_forbidden.rs | 6 +++ .../mod_file_nonascii_forbidden.stderr | 20 ++++++++++ .../mod_file_nonascii_with_path_allowed.rs | 7 ++++ .../rfc-2457/mod_inline_nonascii_allowed.rs | 8 ++++ .../rfc-2457/no_mangle_nonascii_forbidden.rs | 6 +++ .../no_mangle_nonascii_forbidden.stderr | 9 +++++ 10 files changed, 128 insertions(+), 2 deletions(-) create mode 100644 src/librustc_error_codes/error_codes/E0754.md create mode 100644 src/test/ui/rfc-2457/auxiliary/mod_file_nonascii_with_path_allowed-aux.rs create mode 100644 src/test/ui/rfc-2457/mod_file_nonascii_forbidden.rs create mode 100644 src/test/ui/rfc-2457/mod_file_nonascii_forbidden.stderr create mode 100644 src/test/ui/rfc-2457/mod_file_nonascii_with_path_allowed.rs create mode 100644 src/test/ui/rfc-2457/mod_inline_nonascii_allowed.rs create mode 100644 src/test/ui/rfc-2457/no_mangle_nonascii_forbidden.rs create mode 100644 src/test/ui/rfc-2457/no_mangle_nonascii_forbidden.stderr diff --git a/src/librustc_ast_passes/ast_validation.rs b/src/librustc_ast_passes/ast_validation.rs index 46c415413e92..8eb125e44405 100644 --- a/src/librustc_ast_passes/ast_validation.rs +++ b/src/librustc_ast_passes/ast_validation.rs @@ -572,6 +572,35 @@ impl<'a> AstValidator<'a> { .emit(); } + fn check_nomangle_item_asciionly(&self, ident: Ident, item_span: Span) { + if ident.name.as_str().is_ascii() { + return; + } + let head_span = self.session.source_map().guess_head_span(item_span); + struct_span_err!( + self.session, + head_span, + E0754, + "`#[no_mangle]` requires ASCII identifier" + ) + .emit(); + } + + fn check_mod_file_item_asciionly(&self, ident: Ident) { + if ident.name.as_str().is_ascii() { + return; + } + struct_span_err!( + self.session, + ident.span, + E0754, + "trying to load file for module `{}` with non ascii identifer name", + ident.name + ) + .help("consider using `#[path]` attribute to specify filesystem path") + .emit(); + } + fn deny_generic_params(&self, generics: &Generics, ident_span: Span) { if !generics.params.is_empty() { struct_span_err!( @@ -866,6 +895,10 @@ impl<'a> Visitor<'a> for AstValidator<'a> { self.has_proc_macro_decls = true; } + if attr::contains_name(&item.attrs, sym::no_mangle) { + self.check_nomangle_item_asciionly(item.ident, item.span); + } + match item.kind { ItemKind::Impl { unsafety, @@ -992,9 +1025,11 @@ impl<'a> Visitor<'a> for AstValidator<'a> { walk_list!(self, visit_attribute, &item.attrs); return; } - ItemKind::Mod(_) => { + ItemKind::Mod(Mod { inline, .. }) => { // Ensure that `path` attributes on modules are recorded as used (cf. issue #35584). - attr::first_attr_value_str_by_name(&item.attrs, sym::path); + if !inline && !attr::contains_name(&item.attrs, sym::path) { + self.check_mod_file_item_asciionly(item.ident); + } } ItemKind::Union(ref vdata, _) => { if let VariantData::Tuple(..) | VariantData::Unit(..) = vdata { diff --git a/src/librustc_error_codes/error_codes.rs b/src/librustc_error_codes/error_codes.rs index 2399e99a3099..d6863c615f64 100644 --- a/src/librustc_error_codes/error_codes.rs +++ b/src/librustc_error_codes/error_codes.rs @@ -436,6 +436,7 @@ E0750: include_str!("./error_codes/E0750.md"), E0751: include_str!("./error_codes/E0751.md"), E0752: include_str!("./error_codes/E0752.md"), E0753: include_str!("./error_codes/E0753.md"), +E0754: include_str!("./error_codes/E0754.md"), ; // E0006, // merged with E0005 // E0008, // cannot bind by-move into a pattern guard diff --git a/src/librustc_error_codes/error_codes/E0754.md b/src/librustc_error_codes/error_codes/E0754.md new file mode 100644 index 000000000000..abdc01ed21ab --- /dev/null +++ b/src/librustc_error_codes/error_codes/E0754.md @@ -0,0 +1,33 @@ +An non-ascii identifier was used in an invalid context. + +Erroneous code example: + +```compile_fail,E0754 +# #![feature(non_ascii_idents)] + +mod řųśť; +// ^ error! +fn main() {} +``` + +```compile_fail,E0754 +# #![feature(non_ascii_idents)] + +#[no_mangle] +fn řųśť() {} +// ^ error! +fn main() {} +``` + +Non-ascii can be used as module names if it is inline +or a #\[path\] attribute is specified. For example: + +``` +# #![feature(non_ascii_idents)] + +mod řųśť { + const IS_GREAT: bool = true; +} + +fn main() {} +``` diff --git a/src/test/ui/rfc-2457/auxiliary/mod_file_nonascii_with_path_allowed-aux.rs b/src/test/ui/rfc-2457/auxiliary/mod_file_nonascii_with_path_allowed-aux.rs new file mode 100644 index 000000000000..e373b64384f9 --- /dev/null +++ b/src/test/ui/rfc-2457/auxiliary/mod_file_nonascii_with_path_allowed-aux.rs @@ -0,0 +1 @@ +pub trait Foo {} diff --git a/src/test/ui/rfc-2457/mod_file_nonascii_forbidden.rs b/src/test/ui/rfc-2457/mod_file_nonascii_forbidden.rs new file mode 100644 index 000000000000..efd2932f1529 --- /dev/null +++ b/src/test/ui/rfc-2457/mod_file_nonascii_forbidden.rs @@ -0,0 +1,6 @@ +#![feature(non_ascii_idents)] + +mod řųśť; //~ trying to load file for +//~^ file not found for + +fn main() {} diff --git a/src/test/ui/rfc-2457/mod_file_nonascii_forbidden.stderr b/src/test/ui/rfc-2457/mod_file_nonascii_forbidden.stderr new file mode 100644 index 000000000000..be729836f4f2 --- /dev/null +++ b/src/test/ui/rfc-2457/mod_file_nonascii_forbidden.stderr @@ -0,0 +1,20 @@ +error[E0583]: file not found for module `řųśť` + --> $DIR/mod_file_nonascii_forbidden.rs:3:1 + | +LL | mod řųśť; + | ^^^^^^^^^ + | + = help: to create the module `řųśť`, create file "$DIR/řųśť.rs" + +error[E0754]: trying to load file for module `řųśť` with non ascii identifer name + --> $DIR/mod_file_nonascii_forbidden.rs:3:5 + | +LL | mod řųśť; + | ^^^^ + | + = help: consider using `#[path]` attribute to specify filesystem path + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0583, E0754. +For more information about an error, try `rustc --explain E0583`. diff --git a/src/test/ui/rfc-2457/mod_file_nonascii_with_path_allowed.rs b/src/test/ui/rfc-2457/mod_file_nonascii_with_path_allowed.rs new file mode 100644 index 000000000000..e9f3fba2fb01 --- /dev/null +++ b/src/test/ui/rfc-2457/mod_file_nonascii_with_path_allowed.rs @@ -0,0 +1,7 @@ +// check-pass +#![feature(non_ascii_idents)] + +#[path="auxiliary/mod_file_nonascii_with_path_allowed-aux.rs"] +mod řųśť; + +fn main() {} diff --git a/src/test/ui/rfc-2457/mod_inline_nonascii_allowed.rs b/src/test/ui/rfc-2457/mod_inline_nonascii_allowed.rs new file mode 100644 index 000000000000..dd27da432ba6 --- /dev/null +++ b/src/test/ui/rfc-2457/mod_inline_nonascii_allowed.rs @@ -0,0 +1,8 @@ +// check-pass +#![feature(non_ascii_idents)] + +mod řųśť { + const IS_GREAT: bool = true; +} + +fn main() {} diff --git a/src/test/ui/rfc-2457/no_mangle_nonascii_forbidden.rs b/src/test/ui/rfc-2457/no_mangle_nonascii_forbidden.rs new file mode 100644 index 000000000000..a408c9757165 --- /dev/null +++ b/src/test/ui/rfc-2457/no_mangle_nonascii_forbidden.rs @@ -0,0 +1,6 @@ +#![feature(non_ascii_idents)] + +#[no_mangle] +pub fn řųśť() {} //~ `#[no_mangle]` requires ASCII identifier + +fn main() {} diff --git a/src/test/ui/rfc-2457/no_mangle_nonascii_forbidden.stderr b/src/test/ui/rfc-2457/no_mangle_nonascii_forbidden.stderr new file mode 100644 index 000000000000..4ca83e410320 --- /dev/null +++ b/src/test/ui/rfc-2457/no_mangle_nonascii_forbidden.stderr @@ -0,0 +1,9 @@ +error[E0754]: `#[no_mangle]` requires ASCII identifier + --> $DIR/no_mangle_nonascii_forbidden.rs:4:1 + | +LL | pub fn řųśť() {} + | ^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0754`. From 993c4480ac0ad6233068b02f1f4c1d4096111cbe Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 16 May 2020 11:14:00 +0200 Subject: [PATCH 198/203] emphasize that ManuallyDrop is safe-to-access and unsafe-to-drop --- src/libcore/mem/manually_drop.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/libcore/mem/manually_drop.rs b/src/libcore/mem/manually_drop.rs index 17863dd38afe..18767c482c77 100644 --- a/src/libcore/mem/manually_drop.rs +++ b/src/libcore/mem/manually_drop.rs @@ -2,7 +2,6 @@ use crate::ops::{Deref, DerefMut}; use crate::ptr; /// A wrapper to inhibit compiler from automatically calling `T`’s destructor. -/// /// This wrapper is 0-cost. /// /// `ManuallyDrop` is subject to the same layout optimizations as `T`. @@ -11,6 +10,11 @@ use crate::ptr; /// with [`mem::zeroed`] is undefined behavior. /// If you need to handle uninitialized data, use [`MaybeUninit`] instead. /// +/// Note that accessing the value inside a `ManuallyDrop` is safe. +/// This means that a `ManuallyDrop` whose content has been dropped must not +/// be exposed through a public safe API. +/// Correspondingly, `ManuallyDrop::drop` is unsafe. +/// /// # Examples /// /// This wrapper can be used to enforce a particular drop order on fields, regardless From 47034db8510ec4ea2a82ce3b8779b3b4816b1134 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sat, 16 May 2020 12:56:21 -0700 Subject: [PATCH 199/203] Fix whitespace in `?Sized` structured suggestion --- src/librustc_trait_selection/traits/error_reporting/mod.rs | 2 +- src/test/ui/unsized3.stderr | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/librustc_trait_selection/traits/error_reporting/mod.rs b/src/librustc_trait_selection/traits/error_reporting/mod.rs index 6bd4455e1e3f..0d53df3bf4b4 100644 --- a/src/librustc_trait_selection/traits/error_reporting/mod.rs +++ b/src/librustc_trait_selection/traits/error_reporting/mod.rs @@ -1655,7 +1655,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> { { let (span, separator) = match param.bounds { [] => (span.shrink_to_hi(), ":"), - [.., bound] => (bound.span().shrink_to_hi(), " + "), + [.., bound] => (bound.span().shrink_to_hi(), " +"), }; err.span_suggestion_verbose( span, diff --git a/src/test/ui/unsized3.stderr b/src/test/ui/unsized3.stderr index cf8459609b69..828e8bc9f4aa 100644 --- a/src/test/ui/unsized3.stderr +++ b/src/test/ui/unsized3.stderr @@ -31,8 +31,8 @@ LL | fn f4(x: &X) { = note: to learn more, visit help: consider relaxing the implicit `Sized` restriction | -LL | fn f4(x: &X) { - | ^^^^^^^^^ +LL | fn f4(x: &X) { + | ^^^^^^^^ error[E0277]: the size for values of type `X` cannot be known at compilation time --> $DIR/unsized3.rs:33:8 From 9271f998d176c7e5adf35a39fd2d6642bc399858 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Sat, 16 May 2020 22:10:28 +0200 Subject: [PATCH 200/203] Fix issue number typo in note --- .../traits/error_reporting/suggestions.rs | 2 +- .../feature-gate-const_in_array_repeat_expressions.stderr | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/librustc_trait_selection/traits/error_reporting/suggestions.rs b/src/librustc_trait_selection/traits/error_reporting/suggestions.rs index 503daf56b49e..c098e44fa065 100644 --- a/src/librustc_trait_selection/traits/error_reporting/suggestions.rs +++ b/src/librustc_trait_selection/traits/error_reporting/suggestions.rs @@ -1685,7 +1685,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { if suggest_const_in_array_repeat_expressions { err.note( "this array initializer can be evaluated at compile-time, see issue \ - #48147 \ + #49147 \ for more information", ); if tcx.sess.opts.unstable_features.is_nightly_build() { diff --git a/src/test/ui/feature-gates/feature-gate-const_in_array_repeat_expressions.stderr b/src/test/ui/feature-gates/feature-gate-const_in_array_repeat_expressions.stderr index 632afb24aa55..677217806828 100644 --- a/src/test/ui/feature-gates/feature-gate-const_in_array_repeat_expressions.stderr +++ b/src/test/ui/feature-gates/feature-gate-const_in_array_repeat_expressions.stderr @@ -7,7 +7,7 @@ LL | let arr: [Option; 2] = [None::; 2]; = help: the following implementations were found: as std::marker::Copy> = note: the `Copy` trait is required because the repeated element will be copied - = note: this array initializer can be evaluated at compile-time, see issue #48147 for more information + = note: this array initializer can be evaluated at compile-time, see issue #49147 for more information = help: add `#![feature(const_in_array_repeat_expressions)]` to the crate attributes to enable error[E0277]: the trait bound `std::option::Option: std::marker::Copy` is not satisfied From 27c818bc56afd28b60dd9f71af11773d177745c8 Mon Sep 17 00:00:00 2001 From: Wesley Wiser Date: Sat, 16 May 2020 22:12:01 -0400 Subject: [PATCH 201/203] Bless mir-opt tests to account for #72220 --- .../rustc.main.ConstProp.diff | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/test/mir-opt/const_prop/mutable_variable_aggregate_partial_read/rustc.main.ConstProp.diff b/src/test/mir-opt/const_prop/mutable_variable_aggregate_partial_read/rustc.main.ConstProp.diff index 3cf05f135783..6834bb6bdd4f 100644 --- a/src/test/mir-opt/const_prop/mutable_variable_aggregate_partial_read/rustc.main.ConstProp.diff +++ b/src/test/mir-opt/const_prop/mutable_variable_aggregate_partial_read/rustc.main.ConstProp.diff @@ -29,16 +29,14 @@ // + ty: i32 // + val: Value(Scalar(0x00000063)) // mir::Constant -- // + span: $DIR/mutable_variable_aggregate_partial_read.rs:6:11: 6:13 -+ // + span: $DIR/mutable_variable_aggregate_partial_read.rs:6:5: 6:13 + // + span: $DIR/mutable_variable_aggregate_partial_read.rs:6:11: 6:13 // + literal: Const { ty: i32, val: Value(Scalar(0x00000063)) } (_1.0: i32) = const 42i32; // scope 1 at $DIR/mutable_variable_aggregate_partial_read.rs:7:5: 7:13 // ty::Const // + ty: i32 // + val: Value(Scalar(0x0000002a)) // mir::Constant -- // + span: $DIR/mutable_variable_aggregate_partial_read.rs:7:11: 7:13 -+ // + span: $DIR/mutable_variable_aggregate_partial_read.rs:7:5: 7:13 + // + span: $DIR/mutable_variable_aggregate_partial_read.rs:7:11: 7:13 // + literal: Const { ty: i32, val: Value(Scalar(0x0000002a)) } StorageLive(_2); // scope 1 at $DIR/mutable_variable_aggregate_partial_read.rs:8:9: 8:10 - _2 = (_1.1: i32); // scope 1 at $DIR/mutable_variable_aggregate_partial_read.rs:8:13: 8:16 From 5980d972d1911225e38e98fe81974973349793a0 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 17 May 2020 11:06:59 +0200 Subject: [PATCH 202/203] make abort intrinsic safe, and correct its documentation --- src/liballoc/rc.rs | 4 ++++ src/liballoc/sync.rs | 5 +++++ src/libcore/cell.rs | 5 ++--- src/libcore/intrinsics.rs | 2 +- src/libcore/panicking.rs | 18 +++++++++++++++--- src/libpanic_unwind/seh.rs | 5 ++++- src/librustc_typeck/check/intrinsic.rs | 6 ++++-- src/libstd/panicking.rs | 20 ++++++++++++++++---- src/libstd/sync/mpsc/shared.rs | 2 ++ src/libstd/sync/mpsc/sync.rs | 2 ++ 10 files changed, 55 insertions(+), 14 deletions(-) diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index 2f9505ec79ff..0b2622b6ce38 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -2035,6 +2035,8 @@ trait RcBoxPtr { // nevertheless, we insert an abort here to hint LLVM at // an otherwise missed optimization. if strong == 0 || strong == usize::max_value() { + // remove `unsafe` on bootstrap bump + #[cfg_attr(not(bootstrap), allow(unused_unsafe))] unsafe { abort(); } @@ -2061,6 +2063,8 @@ trait RcBoxPtr { // nevertheless, we insert an abort here to hint LLVM at // an otherwise missed optimization. if weak == 0 || weak == usize::max_value() { + // remove `unsafe` on bootstrap bump + #[cfg_attr(not(bootstrap), allow(unused_unsafe))] unsafe { abort(); } diff --git a/src/liballoc/sync.rs b/src/liballoc/sync.rs index dbee9d27d8ac..12232520ef42 100644 --- a/src/liballoc/sync.rs +++ b/src/liballoc/sync.rs @@ -1096,6 +1096,8 @@ impl Clone for Arc { // We abort because such a program is incredibly degenerate, and we // don't care to support it. if old_size > MAX_REFCOUNT { + // remove `unsafe` on bootstrap bump + #[cfg_attr(not(bootstrap), allow(unused_unsafe))] unsafe { abort(); } @@ -1614,6 +1616,8 @@ impl Weak { // See comments in `Arc::clone` for why we do this (for `mem::forget`). if n > MAX_REFCOUNT { + // remove `unsafe` on bootstrap bump + #[cfg_attr(not(bootstrap), allow(unused_unsafe))] unsafe { abort(); } @@ -1753,6 +1757,7 @@ impl Clone for Weak { // See comments in Arc::clone() for why we do this (for mem::forget). if old_size > MAX_REFCOUNT { + #[cfg_attr(not(bootstrap), allow(unused_unsafe))] // remove `unsafe` on bootstrap bump unsafe { abort(); } diff --git a/src/libcore/cell.rs b/src/libcore/cell.rs index 0f2665eba6f2..fad3095f8a3f 100644 --- a/src/libcore/cell.rs +++ b/src/libcore/cell.rs @@ -133,10 +133,9 @@ //! `Cell`. //! //! ``` -//! #![feature(core_intrinsics)] //! use std::cell::Cell; //! use std::ptr::NonNull; -//! use std::intrinsics::abort; +//! use std::process::abort; //! use std::marker::PhantomData; //! //! struct Rc { @@ -173,7 +172,7 @@ //! .strong //! .set(self.strong() //! .checked_add(1) -//! .unwrap_or_else(|| unsafe { abort() })); +//! .unwrap_or_else(|| abort() )); //! } //! } //! diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs index 962bcbe61985..43512f7a2366 100644 --- a/src/libcore/intrinsics.rs +++ b/src/libcore/intrinsics.rs @@ -918,7 +918,7 @@ extern "rust-intrinsic" { /// Aborts the execution of the process. /// - /// The stabilized version of this intrinsic is + /// A more user-friendly and stable version of this operation is /// [`std::process::abort`](../../std/process/fn.abort.html). pub fn abort() -> !; diff --git a/src/libcore/panicking.rs b/src/libcore/panicking.rs index 94ea9b78828d..16739b4a1afd 100644 --- a/src/libcore/panicking.rs +++ b/src/libcore/panicking.rs @@ -39,8 +39,12 @@ use crate::panic::{Location, PanicInfo}; #[lang = "panic"] // needed by codegen for panic on overflow and other `Assert` MIR terminators pub fn panic(expr: &str) -> ! { if cfg!(feature = "panic_immediate_abort") { + // remove `unsafe` (and safety comment) on bootstrap bump + #[cfg_attr(not(bootstrap), allow(unused_unsafe))] // SAFETY: the `abort` intrinsic has no requirements to be called. - unsafe { super::intrinsics::abort() } + unsafe { + super::intrinsics::abort() + } } // Use Arguments::new_v1 instead of format_args!("{}", expr) to potentially @@ -58,8 +62,12 @@ pub fn panic(expr: &str) -> ! { #[lang = "panic_bounds_check"] // needed by codegen for panic on OOB array/slice access fn panic_bounds_check(index: usize, len: usize) -> ! { if cfg!(feature = "panic_immediate_abort") { + // remove `unsafe` (and safety comment) on bootstrap bump + #[cfg_attr(not(bootstrap), allow(unused_unsafe))] // SAFETY: the `abort` intrinsic has no requirements to be called. - unsafe { super::intrinsics::abort() } + unsafe { + super::intrinsics::abort() + } } panic!("index out of bounds: the len is {} but the index is {}", len, index) @@ -72,8 +80,12 @@ fn panic_bounds_check(index: usize, len: usize) -> ! { #[track_caller] pub fn panic_fmt(fmt: fmt::Arguments<'_>) -> ! { if cfg!(feature = "panic_immediate_abort") { + // remove `unsafe` (and safety comment) on bootstrap bump + #[cfg_attr(not(bootstrap), allow(unused_unsafe))] // SAFETY: the `abort` intrinsic has no requirements to be called. - unsafe { super::intrinsics::abort() } + unsafe { + super::intrinsics::abort() + } } // NOTE This function never crosses the FFI boundary; it's a Rust-to-Rust call diff --git a/src/libpanic_unwind/seh.rs b/src/libpanic_unwind/seh.rs index 8d8276b4159a..b1e87a7cac26 100644 --- a/src/libpanic_unwind/seh.rs +++ b/src/libpanic_unwind/seh.rs @@ -327,5 +327,8 @@ pub unsafe fn cleanup(payload: *mut u8) -> Box { #[lang = "eh_personality"] #[cfg(not(test))] fn rust_eh_personality() { - unsafe { core::intrinsics::abort() } + #[cfg_attr(not(bootstrap), allow(unused_unsafe))] // remove `unsafe` on bootstrap bump + unsafe { + core::intrinsics::abort() + } } diff --git a/src/librustc_typeck/check/intrinsic.rs b/src/librustc_typeck/check/intrinsic.rs index 05028ff0b2c2..db6c30adb04c 100644 --- a/src/librustc_typeck/check/intrinsic.rs +++ b/src/librustc_typeck/check/intrinsic.rs @@ -69,7 +69,7 @@ fn equate_intrinsic_type<'tcx>( /// Returns `true` if the given intrinsic is unsafe to call or not. pub fn intrinsic_operation_unsafety(intrinsic: &str) -> hir::Unsafety { match intrinsic { - "size_of" | "min_align_of" | "needs_drop" | "caller_location" | "size_of_val" + "abort" | "size_of" | "min_align_of" | "needs_drop" | "caller_location" | "size_of_val" | "min_align_of_val" | "add_with_overflow" | "sub_with_overflow" | "mul_with_overflow" | "wrapping_add" | "wrapping_sub" | "wrapping_mul" | "saturating_add" | "saturating_sub" | "rotate_left" | "rotate_right" | "ctpop" | "ctlz" | "cttz" @@ -130,7 +130,9 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) { } }; (n_tps, inputs, output, hir::Unsafety::Unsafe) - } else if &name[..] == "abort" || &name[..] == "unreachable" { + } else if &name[..] == "abort" { + (0, Vec::new(), tcx.types.never, hir::Unsafety::Normal) + } else if &name[..] == "unreachable" { (0, Vec::new(), tcx.types.never, hir::Unsafety::Unsafe) } else { let unsafety = intrinsic_operation_unsafety(&name[..]); diff --git a/src/libstd/panicking.rs b/src/libstd/panicking.rs index 343b2ee12735..bf381896a22b 100644 --- a/src/libstd/panicking.rs +++ b/src/libstd/panicking.rs @@ -332,7 +332,10 @@ pub fn panicking() -> bool { #[cfg_attr(feature = "panic_immediate_abort", inline)] pub fn begin_panic_fmt(msg: &fmt::Arguments<'_>) -> ! { if cfg!(feature = "panic_immediate_abort") { - unsafe { intrinsics::abort() } + #[cfg_attr(not(bootstrap), allow(unused_unsafe))] // remove `unsafe` on bootstrap bump + unsafe { + intrinsics::abort() + } } let info = PanicInfo::internal_constructor(Some(msg), Location::caller()); @@ -398,7 +401,10 @@ pub fn begin_panic_handler(info: &PanicInfo<'_>) -> ! { #[track_caller] pub fn begin_panic(msg: M) -> ! { if cfg!(feature = "panic_immediate_abort") { - unsafe { intrinsics::abort() } + #[cfg_attr(not(bootstrap), allow(unused_unsafe))] // remove `unsafe` on bootstrap bump + unsafe { + intrinsics::abort() + } } rust_panic_with_hook(&mut PanicPayload::new(msg), None, Location::caller()); @@ -458,7 +464,10 @@ fn rust_panic_with_hook( "thread panicked while processing \ panic. aborting.\n" )); - unsafe { intrinsics::abort() } + #[cfg_attr(not(bootstrap), allow(unused_unsafe))] // remove `unsafe` on bootstrap bump + unsafe { + intrinsics::abort() + } } unsafe { @@ -493,7 +502,10 @@ fn rust_panic_with_hook( "thread panicked while panicking. \ aborting.\n" )); - unsafe { intrinsics::abort() } + #[cfg_attr(not(bootstrap), allow(unused_unsafe))] // remove `unsafe` on bootstrap bump + unsafe { + intrinsics::abort() + } } rust_panic(payload) diff --git a/src/libstd/sync/mpsc/shared.rs b/src/libstd/sync/mpsc/shared.rs index fd9d61e99c2c..d1a46c517574 100644 --- a/src/libstd/sync/mpsc/shared.rs +++ b/src/libstd/sync/mpsc/shared.rs @@ -354,6 +354,8 @@ impl Packet { // See comments on Arc::clone() on why we do this (for `mem::forget`). if old_count > MAX_REFCOUNT { + // remove `unsafe` on bootstrap bump + #[cfg_attr(not(bootstrap), allow(unused_unsafe))] unsafe { abort(); } diff --git a/src/libstd/sync/mpsc/sync.rs b/src/libstd/sync/mpsc/sync.rs index 79123903e92a..603764922c5a 100644 --- a/src/libstd/sync/mpsc/sync.rs +++ b/src/libstd/sync/mpsc/sync.rs @@ -358,6 +358,8 @@ impl Packet { // See comments on Arc::clone() on why we do this (for `mem::forget`). if old_count > MAX_REFCOUNT { + // remove `unsafe` on bootstrap bump + #[cfg_attr(not(bootstrap), allow(unused_unsafe))] unsafe { abort(); } From 4caddaeeeaf0d6018325085b436256800c05b56c Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 17 May 2020 11:40:58 +0200 Subject: [PATCH 203/203] bootstrap: fix typo --- src/bootstrap/format.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bootstrap/format.rs b/src/bootstrap/format.rs index 6653c505bf53..390b7e96b9a5 100644 --- a/src/bootstrap/format.rs +++ b/src/bootstrap/format.rs @@ -23,7 +23,7 @@ fn rustfmt(src: &Path, rustfmt: &Path, path: &Path, check: bool) { if !status.success() { eprintln!( "Running `{}` failed.\nIf you're running `tidy`, \ - try again with `--bless` flag. Or, you just want to format \ + try again with `--bless`. Or, if you just want to format \ code, run `./x.py fmt` instead.", cmd_debug, );