From b70e7fd0db5d23a2e045e89b8bc7e5564acce9b7 Mon Sep 17 00:00:00 2001 From: CAD97 Date: Mon, 3 Feb 2020 14:54:02 -0500 Subject: 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 7ba4004d860..db533d154c9 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`. -- cgit 1.4.1-3-g733a5 From 2fcfd233f755c548ddc4d5fda517a7dbb9f04ba3 Mon Sep 17 00:00:00 2001 From: CAD97 Date: Tue, 18 Feb 2020 13:18:33 -0500 Subject: Redesign the Step trait --- src/libcore/iter/range.rs | 606 +++++++++++++++++++++-------- 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, 550 insertions(+), 248 deletions(-) diff --git a/src/libcore/iter/range.rs b/src/libcore/iter/range.rs index 28fbd00f36b..ae88fb471a0 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`. - /// - /// Returns `None` if it is not possible to calculate `steps_between` - /// without overflow. +/// 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 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. + /// + /// If this would overflow the range of values supported by `Self`, returns `None`. + /// + /// # Invariants /// - /// The output of this method should always be greater than the output of replace_zero. - fn replace_one(&mut self) -> Self; + /// 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; - /// Replaces this step with `0`, returning a clone of itself. + /// 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: /// - /// The output of this method should always be less than the output of replace_one. - fn replace_zero(&mut self) -> Self; + /// * `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`") + } - /// 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. + /// + /// # 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) + } - /// 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. + /// + /// 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; - /// Adds a `usize`, returning `None` on overflow. - fn add_usize(&self, n: usize) -> Option; + /// 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`") + } - /// 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. + /// + /// # 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 add_one(&self) -> Self { - Add::add(*self, 1) + 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 sub_one(&self) -> Self { - Sub::sub(*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 + } + } } - } + }; } -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) +macro_rules! step_integer_impls { + { + narrower than or same width as usize: + $( [ $u_narrower:ident $i_narrower:ident ] ),+; + wider than usize: + $( [ $u_wider:ident $i_wider:ident ] ),+; + } => { + $( + #[allow(unreachable_patterns)] + #[unstable(feature = "step_trait", reason = "recently redesigned", issue = "42168")] + unsafe impl Step for $u_narrower { + step_identical_methods!( [ $u_narrower $i_narrower ] ); + + #[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 + } } - } - #[inline] - #[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, + #[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 + } } } - #[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, + #[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 + } } - } - 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] + 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, + } } } + )+ - #[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 - } + #[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 } - Err(_) => 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) } } - #[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 + #[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 } - Err(_) => 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_identical_methods!(); - } - )*) +#[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]; } -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 = "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 1a1dbcd7b87..13c05dadbde 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)); + + // Skip u64/i64 to avoid differences with 32-bit vs 64-bit platforms - x = 5; - let y = x.replace_one(); - assert_eq!(x, 1); - assert_eq!(y, 5); + 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 05f958cbe81..3d6abb818e4 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 a84f89c7cd9..67dcea58cf8 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 f1b1656745e..fafab8a102a 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!() } } -- cgit 1.4.1-3-g733a5 From f34322d71f6ba523fb2c0ebef258d7e51a7531c8 Mon Sep 17 00:00:00 2001 From: CAD97 Date: Sat, 14 Mar 2020 15:13:18 -0400 Subject: 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 ae88fb471a0..1b096893902 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 13c05dadbde..e142641b8b5 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 } } } -- cgit 1.4.1-3-g733a5 From db1fbd4a11db579436f68be3a8f5fe03484aa45d Mon Sep 17 00:00:00 2001 From: Mohsen Zohrevandi Date: Wed, 25 Mar 2020 19:28:14 -0700 Subject: Process termination tests Related issues: - https://github.com/fortanix/rust-sgx/issues/109 --- .../process-termination-blocking-io.rs | 18 ++++++++++++++++++ .../process-termination/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 00000000000..d9027fc89e2 --- /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 00000000000..7098a34512e --- /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(); +} -- cgit 1.4.1-3-g733a5 From 079817d62481ca8d84ca87dde9a276a1d5d663cf Mon Sep 17 00:00:00 2001 From: Donough Liu Date: Sat, 25 Apr 2020 08:56:07 +0800 Subject: 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 7db376b20aa..7e33bb8c2a7 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, ); -- cgit 1.4.1-3-g733a5 From cb2703945ca3c6c9664a5a9ec606430cb79ba2c8 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sun, 19 Apr 2020 12:34:00 +0100 Subject: 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 099687bd6b0..61d2295ba8c 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 ecec1fb039b..3ebb5662350 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 2f9505ec79f..307f6714f32 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 a81e0cf7e1d..2b71378619c 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 b4a9da84787..624ca2820d7 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 404cc84495c..a9ba3908c38 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 09a8b417e6e..339b07119c6 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. } -- cgit 1.4.1-3-g733a5 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: 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 cb44eccae68..f16b98883b8 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 { -- cgit 1.4.1-3-g733a5 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: 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 f16b98883b8..6b5a8498dc9 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 3dbb2155d4d..ec80f6070d6 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 -- cgit 1.4.1-3-g733a5 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: Do not trigger `manual_memcpy` for `RangeTo` --- clippy_lints/src/loops.rs | 50 ++++++++++++++++++++----------------------- tests/ui/manual_memcpy.rs | 5 +++++ tests/ui/manual_memcpy.stderr | 2 +- 3 files changed, 29 insertions(+), 28 deletions(-) diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 6b5a8498dc9..ca61c97e3e3 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, "..")), - }; + 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() - } + 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 aa347288875..1f41838fa16 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 ec80f6070d6..95114c46f36 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[..])` -- cgit 1.4.1-3-g733a5 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: 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 ca61c97e3e3..502bd42214e 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); -- cgit 1.4.1-3-g733a5 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: 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 502bd42214e..3dd3a79b287 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 -- cgit 1.4.1-3-g733a5 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: 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 3dd3a79b287..321d5265d0c 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); -- cgit 1.4.1-3-g733a5 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: 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 321d5265d0c..e37c44dc026 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! { -- cgit 1.4.1-3-g733a5 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: 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 e37c44dc026..2dc95f53078 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 -- cgit 1.4.1-3-g733a5 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: 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 2dc95f53078..0753b23e45b 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 = 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) - }; + 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); + + // Source and destination must be different + if offset_left.var_name != offset_right.var_name; + then { + Some((offset_left, offset_right)) + } else { + return None + } + } + }) + }) + .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) + }; - format!( - "{}.clone_from_slice(&{}[{}..{}])", - dst, src_var.var_name, src_offset, src_limit - ) + format!( + "{}.clone_from_slice(&{}[{}..{}])", + dst, src_var.var_name, src_offset, src_limit + ) + }) }) - .join("\n "); + .collect::>>() + .filter(|v| !v.is_empty()) + .map(|v| v.join("\n ")); - if !big_sugg.is_empty() { + if let Some(big_sugg) = big_sugg { span_lint_and_sugg( cx, MANUAL_MEMCPY, -- cgit 1.4.1-3-g733a5 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: 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 0753b23e45b..75955997af2 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; - } - - 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 - }; + 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 } } }) -- cgit 1.4.1-3-g733a5 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: 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 75955997af2..8ab35556670 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 ) }) }) -- cgit 1.4.1-3-g733a5 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: 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 8ab35556670..7cf3e16bef9 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 ")); -- cgit 1.4.1-3-g733a5 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: 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 7cf3e16bef9..5f7f0897943 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 { -- cgit 1.4.1-3-g733a5 From 1afb6e6e3b23bd5555f34cc4dcd20349dfd789de Mon Sep 17 00:00:00 2001 From: Stanislav Tkach Date: Tue, 28 Apr 2020 12:08:38 +0300 Subject: 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 adfd8dfb1c1..62ee051624b 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, -- cgit 1.4.1-3-g733a5 From bdfdc71d0f56a592fd888fcd89e6e9c6188b156c Mon Sep 17 00:00:00 2001 From: Mike Hommey Date: Wed, 29 Apr 2020 18:13:52 +0900 Subject: 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 4fde3316973..7a05aaf71f2 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::*; -- cgit 1.4.1-3-g733a5 From cf5e4a749c13d3a472a6aed4097df5dc90194057 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Wed, 29 Apr 2020 10:58:36 -0400 Subject: 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 e6da7426eb4..56cf9be3391 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 c1a57f2ce61..ca06457291c 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 { -- cgit 1.4.1-3-g733a5 From 9d8f1170b1fa923373766e26a2847390e0a2ea91 Mon Sep 17 00:00:00 2001 From: Mohsen Zohrevandi Date: Wed, 29 Apr 2020 10:36:56 -0700 Subject: Ignore wasm in process termination tests --- src/test/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 d9027fc89e2..864fb776e86 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 7098a34512e..3660f95b05b 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}; -- cgit 1.4.1-3-g733a5 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: 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 1f41838fa16..9c24d6d4db1 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 95114c46f36..bad84a58900 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 -- cgit 1.4.1-3-g733a5 From f072ded3bf6286668ff8eade5b58e471dbe66f2a Mon Sep 17 00:00:00 2001 From: Eduardo Broto Date: Fri, 1 May 2020 01:44:17 +0200 Subject: 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 575773580c0..facf363e371 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 c995be5edc2..64f3a8a0ebb 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 00000000000..ca2a2cf2e1e --- /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 72675c25175..c5360002fa0 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 00000000000..9c239db6e00 --- /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 00000000000..d6719bca0d4 --- /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 + -- cgit 1.4.1-3-g733a5 From c66d02e3ba0d5ace4e42bab88e4df246f03b91d5 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 1 May 2020 11:16:38 +0200 Subject: 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 1ad40eca93b..1c003983df9 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 085f734ed91..b8c93a28bba 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 0a3f3300323..fc2ec7908e8 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 edc2820ee22..4a5cc9aa591 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(); -- cgit 1.4.1-3-g733a5 From 42b0b4754c881101cefb0307c489d6159c19b2f3 Mon Sep 17 00:00:00 2001 From: Eduardo Broto Date: Fri, 1 May 2020 22:37:14 +0200 Subject: 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 ca2a2cf2e1e..a4273da1d74 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 9c239db6e00..7a788f48520 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 d6719bca0d4..613c5e8ca1d 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: 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:76:5 + | +LL | / struct Sp { 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:79: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: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 -- cgit 1.4.1-3-g733a5 From 10e3f9bdb854e3cabbc4fda69ed713388344d524 Mon Sep 17 00:00:00 2001 From: flip1995 Date: Fri, 1 May 2020 23:02:31 +0200 Subject: 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 c995be5edc2..06e21a5272e 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 4071406cc84..421571d2f2f 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 72675c25175..f337db72ba0 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", -- cgit 1.4.1-3-g733a5 From 350c17de24c0bc7ee1b17981fe02f88ca6ec50a4 Mon Sep 17 00:00:00 2001 From: ebroto Date: Fri, 1 May 2020 23:00:16 +0200 Subject: 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 a4273da1d74..f3b8902e26f 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) -- cgit 1.4.1-3-g733a5 From 2e749a5ecd3831f8cb947761b15b2b108ca0ec7c Mon Sep 17 00:00:00 2001 From: Mohsen Zohrevandi Date: Fri, 1 May 2020 17:03:39 -0700 Subject: Correction: ignore emscripten in process termination tests --- src/test/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 864fb776e86..df1a768ebbd 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 3660f95b05b..8f2e5b94c3a 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}; -- cgit 1.4.1-3-g733a5 From 72ce6d5be9c54775b847bc0641f8d909b2977126 Mon Sep 17 00:00:00 2001 From: ThibsG Date: Fri, 24 Apr 2020 16:46:56 +0200 Subject: Fix unwrap lint when checks are done in parameters --- clippy_lints/src/unwrap.rs | 21 ++++++++++++----- tests/ui/checked_unwrap/simple_conditionals.rs | 27 ++++++++++++++++++++++ tests/ui/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 5235c98efab..f3844c7d3b6 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 b0fc26ff76d..3e7b4b390ba 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 e40542e2e4f..4013d1ed667 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 -- cgit 1.4.1-3-g733a5 From d0c1f8ada2306801f2a6ce193e1f9f75471dbb3c Mon Sep 17 00:00:00 2001 From: Aleksei Latyshev Date: Sat, 2 May 2020 14:18:27 +0300 Subject: 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 04b4b423761..1c7b40fa908 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 f5fcabf63fd..e99c98ac79f 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 04dce8a0289..ba13172428e 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 6de138d7227..aa980d9965c 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 -- cgit 1.4.1-3-g733a5 From e7138e06291d13163e8ab2a57fe2465451fac193 Mon Sep 17 00:00:00 2001 From: CrazyRoka Date: Sat, 2 May 2020 14:25:45 +0300 Subject: 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 421571d2f2f..236362130e5 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 0bb39d77e46..30415e3b94d 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(); } -- cgit 1.4.1-3-g733a5 From de58c5644de0d9ffe46e7e2923d2301eaf4dd347 Mon Sep 17 00:00:00 2001 From: CrazyRoka Date: Sat, 2 May 2020 17:36:26 +0300 Subject: 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 236362130e5..ee69628e9f0 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 ca2c4ade155..79ca6845c6f 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"]; -- cgit 1.4.1-3-g733a5 From e5a1be8597c21c7b547a02231e5cf072dd3a0179 Mon Sep 17 00:00:00 2001 From: marmeladema Date: Sat, 2 May 2020 18:42:36 +0100 Subject: 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 ccce72fb0ac..e2eb39c3e1c 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 adbab3d4cb6..d95eb5f28fe 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); -- cgit 1.4.1-3-g733a5 From c9f1162a6ffc81adcb114a616899edad0f7d0750 Mon Sep 17 00:00:00 2001 From: Laurence Tratt Date: Mon, 4 May 2020 10:17:39 +0100 Subject: 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 39df803bbea..67698e5409f 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. -- cgit 1.4.1-3-g733a5 From 93f877ce870e9fd13ad7c6a05ccb4abd46a3d106 Mon Sep 17 00:00:00 2001 From: Laurence Tratt Date: Mon, 4 May 2020 11:01:31 +0100 Subject: 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 67698e5409f..2628f890332 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 -- cgit 1.4.1-3-g733a5 From 7744cf4e53c4e19e5753e2063be420b9d0c0d38a Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Mon, 4 May 2020 15:13:07 +0200 Subject: 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 d5cace0c647..d563eb886ae 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; -- cgit 1.4.1-3-g733a5 From 876001c8ac331a15661638fbb18b8b64facf2c96 Mon Sep 17 00:00:00 2001 From: Laurence Tratt Date: Mon, 4 May 2020 14:28:58 +0100 Subject: 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 2628f890332..996a9cdfc4d 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"`. /// -- cgit 1.4.1-3-g733a5 From 5cb2fa487bf6405a18c13041bc18544884f603a7 Mon Sep 17 00:00:00 2001 From: Dolpheyn Date: Mon, 4 May 2020 22:14:25 +0800 Subject: 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 63a5277100f..a87f3c1804c 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() } -- cgit 1.4.1-3-g733a5 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: Fix unused_parens false positive when using binary operations --- src/librustc_lint/unused.rs | 16 ++++++++++++---- src/test/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 ddd252cb290..4f7a1f9c310 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 00000000000..619be02566f --- /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() {} -- cgit 1.4.1-3-g733a5 From 73f07a47b892216c47a741e229924b90a86585e1 Mon Sep 17 00:00:00 2001 From: Dolpheyn Date: Tue, 5 May 2020 08:25:20 +0800 Subject: 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 a87f3c1804c..480fe4fd4be 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() } -- cgit 1.4.1-3-g733a5 From 2badd41d043c9ff549855ad832e7bcd2ad44970d Mon Sep 17 00:00:00 2001 From: Dolpheyn Date: Tue, 5 May 2020 09:50:59 +0800 Subject: 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 480fe4fd4be..4647ad01006 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> { -- cgit 1.4.1-3-g733a5 From 780a63a1ba84597eaf33e4d546bcf0edd6225836 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Tue, 5 May 2020 15:11:59 +0200 Subject: 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 b6a4adde848..bc785b075e0 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 -- cgit 1.4.1-3-g733a5 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: 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 619be02566f..f11d2d37737 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 -- cgit 1.4.1-3-g733a5 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: 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 4bb50f75791..bdda45fdcd4 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 } -- cgit 1.4.1-3-g733a5 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: Fix unused_parens nested binary op false positive --- src/librustc_lint/unused.rs | 16 ++++++++++++---- src/test/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 4f7a1f9c310..c24079a6e4b 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 f11d2d37737..24d77e36d94 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() {} -- cgit 1.4.1-3-g733a5 From a1ebb94775daa63cb105cc1c410022c20002667b Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Wed, 6 May 2020 19:28:48 +0200 Subject: Const prop aggregates even if partially or fully modified --- src/librustc_mir/transform/const_prop.rs | 100 ++++++++++++--------- src/test/mir-opt/const_prop/mutable_variable.rs | 8 ++ .../mutable_variable/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 ++++++++++++ .../mir-opt/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 7926bf535b3..4dd7c033053 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 00000000000..b3a2d80fa95 --- /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 00000000000..c6c5b0cf726 --- /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 00000000000..3c5fb4574b6 --- /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 00000000000..26f0250d94c --- /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 00000000000..fc13cbf2abd --- /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 00000000000..44203ac327a --- /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 00000000000..8c9cd005096 --- /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 00000000000..1e9cbe6024c --- /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 │ *... + } + -- cgit 1.4.1-3-g733a5 From 2b3adc9b9472e1d1e384422ceac783f9921f3b0b Mon Sep 17 00:00:00 2001 From: Mohsen Zohrevandi Date: Wed, 6 May 2020 23:41:38 -0700 Subject: Fix bind address in process-termination-blocking-io test --- src/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 df1a768ebbd..f306a61a538 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() {} }); -- cgit 1.4.1-3-g733a5 From d80ac14fe69676c34efdec0c1cc589d28cd03ab1 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 30 Apr 2020 15:37:00 +0200 Subject: Extend rustdoc-js tester to allow to test multiple queries in one file --- src/tools/rustdoc-js/tester.js | 98 ++++++++++++++++++++++++++++-------------- 1 file changed, 65 insertions(+), 33 deletions(-) diff --git a/src/tools/rustdoc-js/tester.js b/src/tools/rustdoc-js/tester.js index 03f06fc1c6c..72bc496c5b5 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 { + if (displaySuccess) { + console.log("OK"); + } + return 0; + } + 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; } - return errors; + 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; } -- cgit 1.4.1-3-g733a5 From 7590c393dee055e9ce97f8a5f993fa0cc7e56217 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 30 Apr 2020 20:53:40 +0200 Subject: 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 a023d5a2d95..411d2d44059 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() { -- cgit 1.4.1-3-g733a5 From cf41b1d3a5fc5e4c209ab101b159095178dea916 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 30 Apr 2020 20:54:06 +0200 Subject: 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 666e59b9a04..4ed367a5c80 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 5b090291227..17003334bc8 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); + } } } -- cgit 1.4.1-3-g733a5 From 3a0727e84e29318ee41eb63bac27bfc1a379bfc5 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 1 May 2020 00:27:24 +0200 Subject: 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 00000000000..e6310b625e5 --- /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 00000000000..8cd0a829974 --- /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 { + () => {} +} -- cgit 1.4.1-3-g733a5 From 9697c467aca28f40d8ef7c59b9f5bc670c1b85f8 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 1 May 2020 00:43:55 +0200 Subject: 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 f3c6713692b..0ce1b87b761 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 2b709c99119..0b1e983117f 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' }, ], }; -- cgit 1.4.1-3-g733a5 From f581cf754492f9f122193b8d8a7750ab38a87485 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 4 May 2020 14:51:06 +0200 Subject: 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 0922c8cdd12..ea65b390527 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 4ed367a5c80..9454baf7640 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 17003334bc8..53cf1abb16d 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 411d2d44059..94ae69fde57 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 0ce1b87b761..cb6ec4f8fed 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 0b1e983117f..2b709c99119 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 72bc496c5b5..90315d6f644 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() { -- cgit 1.4.1-3-g733a5 From 3b58d66b22fe9107a78b99c267c71322276aa15a Mon Sep 17 00:00:00 2001 From: Eduardo Broto Date: Thu, 7 May 2020 21:41:23 +0200 Subject: 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 facf363e371..8457d6ad05c 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 97785cba883..fb2e9932b8e 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 00000000000..ab8829abbf2 --- /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 79ca6845c6f..74040a96c78 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 a7685f67211..51d1cb2216a 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 6d09d71a630..d3a920de4b6 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 3b4968ef0a6..d1863701bfe 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 00000000000..84c02bba4dc --- /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 00000000000..bd5f9d1cf5f --- /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 00000000000..016fdf95977 --- /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 + -- cgit 1.4.1-3-g733a5 From 4ac348b30849ec472564a81797b7e9ae42985460 Mon Sep 17 00:00:00 2001 From: Eduardo Broto Date: Thu, 7 May 2020 22:03:38 +0200 Subject: 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 ab8829abbf2..b4be3ecfd16 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 -- cgit 1.4.1-3-g733a5 From 3e4bc026e2706b1cb21bad6d55726f8b5a1d4cf1 Mon Sep 17 00:00:00 2001 From: Eduardo Broto Date: Thu, 7 May 2020 22:40:28 +0200 Subject: 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 b4be3ecfd16..cb72a240582 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 74040a96c78..b3ad2ad9d99 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 84c02bba4dc..6bb1032a172 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 bd5f9d1cf5f..d50c919188b 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 016fdf95977..f278ee41aa3 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 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -- cgit 1.4.1-3-g733a5 From abbc7365a726269e13b7ee2864bb6086dfc41d69 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 8 May 2020 15:19:14 +0200 Subject: 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 666e59b9a04..82f91e232df 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) { -- cgit 1.4.1-3-g733a5 From 9d8310856b3a42aa99d6591244a6679284011dc9 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 8 May 2020 15:27:08 +0200 Subject: 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 7babfaf6060..11caa34d4b1 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' \ -- cgit 1.4.1-3-g733a5 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: 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 00000000000..c7855729a98 --- /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() {} -- cgit 1.4.1-3-g733a5 From 619c6055e71a5a202cba3f5cb979f17c3581faa3 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Fri, 8 May 2020 17:25:18 +0100 Subject: Fix debug assertion in error code --- .../traits/error_reporting/suggestions.rs | 9 +++++++++ .../imm-ref-trait-object-literal-bound-regions.rs | 18 ++++++++++++++++++ .../imm-ref-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 ce7b1390d46..3c8aa08bdca 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 00000000000..319789c4ec2 --- /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 00000000000..83de3c4cfe0 --- /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`. -- cgit 1.4.1-3-g733a5 From 54b7d45564e06a97ca30d9f8e64aa6cd007c2805 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Fri, 8 May 2020 17:34:39 -0400 Subject: 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 f29f9f3bf1c..d891ad1b668 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 -- cgit 1.4.1-3-g733a5 From 438877380a2bf591fc1294ab31bc7fb2598738ad Mon Sep 17 00:00:00 2001 From: Matthias Krüger Date: Sat, 9 May 2020 01:27:30 +0200 Subject: 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 63ce2cd8cad..6999b6bd740 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 } -- cgit 1.4.1-3-g733a5 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: 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 5ccfc1b276b..e44feee9660 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; -- cgit 1.4.1-3-g733a5 From 1fce20340a6422b5e1f9738b82a304c4c389171c Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 9 May 2020 14:04:32 +0200 Subject: 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 cad6a312521..201dfba91c9 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(); }) }); } -- cgit 1.4.1-3-g733a5 From 6a8cf4a17c2d2b3daca27e787f4154e233ab4545 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 22 Apr 2020 10:21:32 +0200 Subject: 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 ++- src/test/ui/const-generics/array-size-in-generic-struct-param.rs | 2 +- .../ui/const-generics/array-size-in-generic-struct-param.stderr | 3 ++- src/test/ui/const-generics/array-wrapper-struct-ctor.rs | 2 +- src/test/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 ++- src/test/ui/const-generics/cannot-infer-type-for-const-param.rs | 2 +- .../ui/const-generics/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 +- src/test/ui/const-generics/concrete-const-impl-method.stderr | 3 ++- src/test/ui/const-generics/condition-in-trait-const-arg.rs | 2 +- src/test/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 ++- src/test/ui/const-generics/const-arg-type-arg-misordered.rs | 2 +- src/test/ui/const-generics/const-arg-type-arg-misordered.stderr | 3 ++- src/test/ui/const-generics/const-expression-parameter.rs | 2 +- src/test/ui/const-generics/const-expression-parameter.stderr | 3 ++- src/test/ui/const-generics/const-fn-with-const-param.rs | 2 +- src/test/ui/const-generics/const-fn-with-const-param.stderr | 3 ++- src/test/ui/const-generics/const-generic-array-wrapper.rs | 2 +- src/test/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 +- src/test/ui/const-generics/const-param-elided-lifetime.stderr | 3 ++- src/test/ui/const-generics/const-param-from-outer-fn.rs | 2 +- src/test/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 ++- .../ui/const-generics/const-param-type-depends-on-type-param.rs | 2 +- .../const-generics/const-param-type-depends-on-type-param.stderr | 3 ++- src/test/ui/const-generics/const-parameter-uppercase-lint.rs | 2 +- src/test/ui/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 +- src/test/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 ++- src/test/ui/const-generics/fn-taking-const-generic-array.rs | 2 +- src/test/ui/const-generics/fn-taking-const-generic-array.stderr | 3 ++- src/test/ui/const-generics/forbid-non-structural_match-types.rs | 2 +- .../ui/const-generics/forbid-non-structural_match-types.stderr | 3 ++- src/test/ui/const-generics/foreign-item-const-parameter.rs | 2 +- src/test/ui/const-generics/foreign-item-const-parameter.stderr | 3 ++- src/test/ui/const-generics/impl-const-generic-struct.rs | 2 +- src/test/ui/const-generics/impl-const-generic-struct.stderr | 3 ++- src/test/ui/const-generics/incorrect-number-of-const-args.rs | 2 +- src/test/ui/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 ++- .../const-generics/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 +- src/test/ui/const-generics/issue-61522-array-len-succ.stderr | 3 ++- .../ui/const-generics/issue-66596-impl-trait-for-str-const-arg.rs | 2 +- .../const-generics/issue-66596-impl-trait-for-str-const-arg.stderr | 3 ++- .../ui/const-generics/issues/issue-60818-struct-constructors.rs | 2 +- .../const-generics/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 +- .../issues/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 +- src/test/ui/const-generics/issues/issue-62579-no-match.stderr | 3 ++- src/test/ui/const-generics/issues/issue-63322-forbid-dyn.rs | 2 +- src/test/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 +- src/test/ui/const-generics/issues/issue70273-assoc-fn.stderr | 3 ++- src/test/ui/const-generics/mut-ref-const-param-array.rs | 2 +- src/test/ui/const-generics/mut-ref-const-param-array.stderr | 3 ++- src/test/ui/const-generics/raw-ptr-const-param-deref.rs | 2 +- src/test/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 +- src/test/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 ++- src/test/ui/const-generics/struct-with-invalid-const-param.rs | 2 +- src/test/ui/const-generics/struct-with-invalid-const-param.stderr | 3 ++- src/test/ui/const-generics/transparent-maybeunit-array-wrapper.rs | 2 +- .../ui/const-generics/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 +- src/test/ui/const-generics/types-mismatch-const-args.stderr | 3 ++- src/test/ui/const-generics/uninferred-consts-during-codegen-1.rs | 2 +- .../ui/const-generics/uninferred-consts-during-codegen-1.stderr | 3 ++- src/test/ui/const-generics/uninferred-consts-during-codegen-2.rs | 2 +- .../ui/const-generics/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 ++- src/test/ui/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 ++- .../ui/inference/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 ++- src/test/ui/parser/impl-item-type-no-body-semantic-fail.stderr | 3 ++- src/test/ui/resolve/issue-65035-static-with-parent-generics.rs | 2 +- src/test/ui/resolve/issue-65035-static-with-parent-generics.stderr | 3 ++- src/test/ui/rfc-2497-if-let-chains/disallowed-positions.stderr | 7 +++++-- src/test/ui/rfc-2627-raw-dylib/link-ordinal-and-name.rs | 2 +- src/test/ui/rfc-2627-raw-dylib/link-ordinal-and-name.stderr | 3 ++- src/test/ui/rfc-2627-raw-dylib/link-ordinal-invalid-format.rs | 2 +- src/test/ui/rfc-2627-raw-dylib/link-ordinal-invalid-format.stderr | 3 ++- src/test/ui/rfc-2627-raw-dylib/link-ordinal-too-large.rs | 2 +- src/test/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 ++- src/test/ui/type-alias-impl-trait/type-alias-impl-trait-const.rs | 2 +- .../ui/type-alias-impl-trait/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 90e279bfc74..0eaeb910be6 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 b3c12fbb6e8..6b10c540494 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 7f3da75ddcb..45b2889f1ca 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 09f65f6acd0..c94d7d245a3 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 f8d230da365..8b396f23efd 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 9f219fb7c53..71f6e4ff8b6 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 7414c148452..3637f9558be 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 8c225a30638..11ff03db361 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 f6a80c3c7d3..316fac62325 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 7acc50819a6..f9c6e201b17 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 b6b83b78d3b..4389e4738ea 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 3446600d049..6110d16c070 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 7c55cb59a22..f77ae49cf10 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 d996bf56fcc..5c02e585dc8 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 05f30a1cc5e..14cf64eeb7a 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 2d1a405ebdd..49fc53b32bd 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 e28f65a3827..e6eb2a0a783 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 9a11bd3d031..f137be2d6a6 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 8b8e0fd1120..a5532bde1f5 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 d9a4411b4f9..c2f9b786f8f 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 cbb8159e9b5..e0bf039575b 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 e1061c6d1a3..2f6ad2654c1 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 fc426bf4f48..6696b025855 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 303bc8326fd..aac5d195f76 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 f273c4e9335..c5c48d7be46 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 54981b77a2b..18ebba49f6f 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 e83ccf9adb7..c8f3a8beaf8 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 226ea415180..c1ddf9a3314 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 c9145837ea4..5edb4f4f6cd 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 091fe904826..9d8aaed54bd 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 12a51d05f46..9ac33454128 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 3f86782838c..5ea2cf92fdc 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 74919ba0ae7..bb66849c7fe 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 f024eb6a957..9f989ee20a5 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 5795a492c22..ad38b632b75 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 22c6c351622..e0b66a7c14c 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 6784aeebf0f..e421c22be01 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 3d8b77bcf7b..bbc55815e9a 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 64b9c18a8f5..109b5002848 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 56a58c582f6..3e43387163b 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 1d05381b59b..47448bbd19d 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 469843d6aae..22f9bd2a0f0 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 641b868dcb2..f161739c9c8 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 5679dd35c30..5e6b6c4dabe 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 edc26d6348c..8c50fb73679 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 6534bcf5ce6..4b8e2db7233 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 a03ba080900..30bd1d72914 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 6e4f65fe6ca..68740725711 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 6afbce67e33..a2e367b25ad 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 7468020366c..654e36df37e 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 9f20b06813e..ed05264161e 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 164205dd75c..54a33e21812 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 826dc702c0d..b7febed7bdd 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 bc5188133d7..bde80f4a1ed 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 935baf1a63a..4628c900318 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 eee634c1564..c6d8b32f276 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 672586fd3fe..8fbe6d3e9a4 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 c52a5b8061d..78964eb3dee 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 9ea2aace89a..001d9852a69 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 cd4b19db353..afa577fa67f 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 872ec11ad1b..9c0f7e3ab9b 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 dc69fa9eea5..08f6e0db31c 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 7bfb0873a10..3e07393b9aa 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 d3d17cca4da..8e16221ed4b 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 5a2ef780e14..52fd0a8fec0 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 a30cdc3efdf..514e215ba1a 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 4f343146263..600be64b1e1 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 4673c8606c3..41113780de3 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 b8fd9854ff6..ee947943af1 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 87572e51e81..4c2aee59ffe 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 64dbc210d92..9d68df07ce6 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 7059e9d8348..cea64654e11 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 a2492e27e20..51064d7f90f 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 a4e3d3dee4a..7e8152dacc4 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 7a6da2582a8..f52e5e49a3b 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 70633bbb141..cede9ea045d 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 d698abd2bae..dfadfbb1663 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 30fbfda112c..952e05bac30 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 0924f8da25f..aadd10e5cca 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 3b627a5e530..7c8cdeece87 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 d52ae10ee07..a1fbd5f2025 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 b677dcc4af4..74f036e6d89 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 edaa59bbdc7..720420d9cd6 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 fb234eb0827..26d74ffb254 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 887d4547933..94a2b673a51 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 165d3e1c2e6..2135c868bbc 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 34920d8907f..b2c69d57c40 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 c5bf6b6ce94..52969056f00 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 27ee4f88870..5f3395223f9 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 7e84e62d8be..eb0f3097627 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 772a07cccf8..0eee37df3dd 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 4fa150ffef0..7e7ef6867ed 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 a66224b6d17..69bbaada691 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 832095ce542..0440468e9e6 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 cb2fa99f6d8..1d547b1b6c9 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 64674bb894e..9e0572d3568 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 3465db15208..2e405370dc0 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 4e5e4d045c8..2f3b5c5dc5b 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 70d0b61cc26..a9abb877c09 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 5d068eb7fc8..37947ad1b33 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 96a07110e73..0454fed6705 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 0ff7ddc41fe..7eaf5eea078 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 31f8d230935..9fb9b5b13d8 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 2bacd6c9a9c..2bcaa27b4d2 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 c3db6c65a8f..32054e43716 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 72cce9b4843..e9391096b04 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 94c010ba260..6552aea4ad1 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 461fe837dac..486c72d8a34 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 6730c97604c..8e8b552f90e 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 8b933c078ff..08a8309d431 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 b095d577fb7..8ad4b25ae5b 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 a3eca0dd7d9..fb7d4886a7c 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 6a30e5e783e..c1f9634810e 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 58fac8e0511..b53cec80071 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 2b56ed977ee..5d647e933c4 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 a192ddea9c6..c22e61d0ce3 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 afd2a50242f..931701b64b4 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 f930fb87963..9ca1f4552f5 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 336364e5aea..acbc2df1d74 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 745dde3c287..c498bfe2e97 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 736c9b49725..1ffc63ffdac 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 f0349f46962..d7d970e952b 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 a2496a6558d..6644c72236b 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 73c75ae6668..4f321b02b82 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 e497cc3220d..cc21f197e08 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 2629caa3921..9668f7ddabb 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 80fdf3296bc..524bd41a669 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 207b07bf695..0b00481d903 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 7472793f809..a968b26bc26 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 794048174f9..1aed9cfe927 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 0bf40839813..6077fe5b1ed 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 776084b77a5..588c7b9523a 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 5f848c3ec52..8afed0d3986 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 b25b7331017..bf517c11262 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 a76bbd177fb..2131738554f 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 7942631bb70..7473718351e 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 c1d115b4f1d..f41628d5d8e 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 0cf505906f6..8b95a010473 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 2738f37b21e..f1703bc3a2f 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 8025b3af8f1..d9292efc21b 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 6d3d1a612b8..be015a689ae 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 05234faf714..2c3ce7c9eab 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 2cc4070f76e..e14958ee566 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 66a6e1c817a..30745814b4a 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 b0d43225be6..f915f6edef5 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 50f3c1e0d5a..0215ff395df 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 94a1eca4953..4ca6d199835 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 11dba87d97b..b351b8b73a0 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 1a48fc12b8f..8b987471534 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 2e9b6cd5c78..c7fae45d5ca 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 2623d8e2d02..bf739d4722f 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 d4eef29ed32..d1f42be077d 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 14d33270ca5..6656968d79a 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 104a44d6566..fd79ba68fbd 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 7d64980074a..e983fdecdba 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 f5092044627..36b4ebca4df 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 fcc3cc51236..afc181a906a 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 7d75f254bfe..2e96022318b 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 39f5d3c6d8c..89a22f5e5d6 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 4fbed9b08f2..a687a9e3be1 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 25efbb10529..85db20b13fb 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 7678ee6c821..214467793bc 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 b6a08351609..f09ab3bf919 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 6076328b12f..7f8151db06f 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 4f11c306f50..4c3a00e5f35 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 5769366fb45..bf082932bd6 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 c7765a453c4..5d8545b5062 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 82fb1151c23..ea633c5bcce 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 4826c46e90c..8453a3966be 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 69596ad04ff..55cc329dc59 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 f8bfe5a62b8..35f9b53fdf7 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 7f3f86e4df0..d53f562e99f 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 77cd7f4b93a..e0c1b023861 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 0fd4d26ef60..bc2bf9eca93 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 5efb992a210..b0593d51a25 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 -- cgit 1.4.1-3-g733a5 From e22cc993fbf9918784ec38a25e04564e7b1973ee Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Sat, 9 May 2020 16:08:04 +0200 Subject: 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 2f3d89dc029..1f097f24942 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 b9eb58f800e..ba406c72df8 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 d334006d7b5..bfc872be653 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 a8e949ecb31..632408fde74 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!(), -- cgit 1.4.1-3-g733a5 From 0db2aec14a93fd9c5b084aa5f973d3609e625bf6 Mon Sep 17 00:00:00 2001 From: Bastian Kauschke Date: Sat, 9 May 2020 17:10:40 +0200 Subject: 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 +++--- src/test/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 2d2704fc2bd..8ec81fb3c57 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 09f65f6acd0..ed29443332f 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 d795840551c..bd26c08a8e5 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 c03377d74e9..76ccc48c32a 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 cbb8159e9b5..d48524f66dd 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 672586fd3fe..35ecc49cfb3 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 a3a864f770c..5d45e302888 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 -- cgit 1.4.1-3-g733a5 From 0c14ea8ed79ebf0b7368659282136e876f247cc9 Mon Sep 17 00:00:00 2001 From: Glenn Hope Date: Sun, 3 May 2020 10:56:25 -0700 Subject: 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 f3038861cee..70ad9a60a02 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 ed6cc00ef04..003f11009a0 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 c6d6efaece8..7bd57c7965a 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 050e4c6304f..858dc28797f 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 -- cgit 1.4.1-3-g733a5 From bdc75dbb7bbdc379b1f8cc346151fac4e63d7deb Mon Sep 17 00:00:00 2001 From: Glenn Hope Date: Sun, 3 May 2020 11:18:10 -0700 Subject: 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 70ad9a60a02..e7400642b07 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") } -- cgit 1.4.1-3-g733a5 From 56f4e1c3a8be54c1c80de366618e83d8d7a6e9eb Mon Sep 17 00:00:00 2001 From: Glenn Hope Date: Thu, 7 May 2020 08:06:30 -0700 Subject: 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 e7400642b07..a22d0e6775d 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 003f11009a0..1c5c01f65d1 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 7bd57c7965a..f783149ef93 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 858dc28797f..649d550a88d 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 -- cgit 1.4.1-3-g733a5 From ad92486d52fdede5c712dd27c868c942d8240704 Mon Sep 17 00:00:00 2001 From: Glenn Hope Date: Thu, 7 May 2020 14:41:54 -0700 Subject: 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 fb2e9932b8e..4b67c84e38e 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 4b81ff33495..57b9eafd14d 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 a22d0e6775d..43d0d1b9e96 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 18f5d994ba8..53970af4107 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 1c5c01f65d1..98bf6acfe55 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 f783149ef93..9275c5a0928 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 649d550a88d..bd000ce8161 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 -- cgit 1.4.1-3-g733a5 From a42a2bdac2a6c881f85ebdbce66e84d977c74cfa Mon Sep 17 00:00:00 2001 From: Glenn Hope Date: Thu, 7 May 2020 14:48:27 -0700 Subject: 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 43d0d1b9e96..843ddda0356 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); -- cgit 1.4.1-3-g733a5 From 152cdcb45be7a8f0f24dbcd4177e0858d94516b6 Mon Sep 17 00:00:00 2001 From: Glenn Hope Date: Fri, 8 May 2020 18:22:27 -0700 Subject: 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 843ddda0356..48405a00d55 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") } -- cgit 1.4.1-3-g733a5 From 4db6abcd50eb07a7fa8349a059f80792b7b19a2e Mon Sep 17 00:00:00 2001 From: Glenn Hope Date: Sat, 9 May 2020 08:04:07 -0700 Subject: 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 48405a00d55..e12a6659ab5 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 98bf6acfe55..b47c8f23e24 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 9275c5a0928..3ad1a29aeba 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 bd000ce8161..de07bd1d69b 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 -- cgit 1.4.1-3-g733a5 From a339766136a183327faaf13b987be30b2940872e Mon Sep 17 00:00:00 2001 From: Glenn Hope Date: Sat, 9 May 2020 08:33:35 -0700 Subject: 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 b47c8f23e24..67423e6ec1d 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; -- cgit 1.4.1-3-g733a5 From 0ba61c612ee873314d252ca1f747c14a2f0161ba Mon Sep 17 00:00:00 2001 From: Glenn Hope Date: Sat, 9 May 2020 10:14:29 -0700 Subject: 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 e12a6659ab5..2c4e24780e7 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 de07bd1d69b..fab43b738eb 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` -- cgit 1.4.1-3-g733a5 From b69200b8468434bc3f5b9ef8468733e5d40f4e01 Mon Sep 17 00:00:00 2001 From: Glenn Hope Date: Sat, 9 May 2020 10:16:47 -0700 Subject: 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 2c4e24780e7..32d9a45c37d 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); -- cgit 1.4.1-3-g733a5 From bb6a6e08325a38f735b4806f5146e0d6a3fa687f Mon Sep 17 00:00:00 2001 From: Bastian Kauschke Date: Sat, 9 May 2020 21:02:13 +0200 Subject: 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 00000000000..6427c547a8f --- /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 8bb9934789a..ae095184299 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 { -- cgit 1.4.1-3-g733a5 From b6e4581937dff28f4534e393907124182fb791d0 Mon Sep 17 00:00:00 2001 From: Marko Mijalkovic Date: Sat, 9 May 2020 15:41:49 -0400 Subject: 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 00000000000..d5765f01ba3 --- /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 00000000000..9dd38f5ce91 --- /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 51dce9e144c..dab1e51e3f8 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. -- cgit 1.4.1-3-g733a5 From 20a66913233589208934d155491c75157947e03e Mon Sep 17 00:00:00 2001 From: Marko Mijalkovic Date: Sat, 9 May 2020 16:03:40 -0400 Subject: Update stdarch --- src/stdarch | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/stdarch b/src/stdarch index d10eefc6228..ec6fccd34c3 160000 --- a/src/stdarch +++ b/src/stdarch @@ -1 +1 @@ -Subproject commit d10eefc62284c40c5a95a2eed19fc1f414a5364d +Subproject commit ec6fccd34c30003a7ebf4e7a9dfe4e31f5b76e1b -- cgit 1.4.1-3-g733a5 From 8961b083762d3660ca21110836b547e8b3f19022 Mon Sep 17 00:00:00 2001 From: Marko Mijalkovic Date: Sat, 9 May 2020 16:39:45 -0400 Subject: 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 d5765f01ba3..80c253b86bb 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() }, -- cgit 1.4.1-3-g733a5 From 0ceacd022c326dadfc65e5cffcde28449c3d735a Mon Sep 17 00:00:00 2001 From: Trevor Spiteri Date: Sun, 10 May 2020 11:24:06 +0200 Subject: 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 4483940c9a7..434569020d2 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 df45e588369..6476ddb4541 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; -- cgit 1.4.1-3-g733a5 From c82103cb21942b171c2fe135d0a32be620113e47 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 9 May 2020 13:59:21 +0200 Subject: 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 7e6dfbf00f5..2cf81af0416 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 9164734783c..7ee60176dbe 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 49692c73fad..b51c0a6e988 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 8db107ed68a..2a2169880a5 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 b17a77e0f6f..d0f627d8bc5 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 09f8588cee2..785c6c21d74 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 0e6a07e06d0..8e350d3ba26 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 dd7ba5cb6fc..58cdb87158a 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 c0011fddf4f..7261d631a6f 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)] -- cgit 1.4.1-3-g733a5 From c400f758e5cda9c2617f6d8dec87a6f24ddb291e Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 29 Apr 2020 10:00:22 +0200 Subject: 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 +++++++++++---------- src/test/ui/consts/miri_unleashed/mutable_const.rs | 25 -- .../ui/consts/miri_unleashed/mutable_const.stderr | 39 --- .../ui/consts/miri_unleashed/mutable_const2.rs | 16 -- .../ui/consts/miri_unleashed/mutable_const2.stderr | 29 --- .../ui/consts/miri_unleashed/mutable_references.rs | 3 +- .../miri_unleashed/mutable_references.stderr | 6 +- .../miri_unleashed/mutable_references_err.rs | 37 +++ .../miri_unleashed/mutable_references_err.stderr | 40 ++++ .../miri_unleashed/mutable_references_ice.rs | 29 --- .../miri_unleashed/mutable_references_ice.stderr | 25 -- .../ui/consts/miri_unleashed/raw_mutable_const.rs | 12 + .../consts/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 9bb7c879505..eba4dd336ad 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 1c44101595d..c9661c92d2e 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 f8aa6528273..00000000000 --- 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 4772baf9d9a..00000000000 --- 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 867091af7ba..00000000000 --- 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 98a1c8bdd89..00000000000 --- 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 ed2ca86ba2c..ca927ef4a51 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 83c4e0ceba0..7109ffd8b61 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 00000000000..5014a601390 --- /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 00000000000..45e7d5a2cc3 --- /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 7388aad2a9e..00000000000 --- 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 7ddf77af4d3..00000000000 --- 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 00000000000..3d200e23173 --- /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 00000000000..c6dbf086ec0 --- /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 00000000000..00fad046b55 --- /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 00000000000..974b1c3ff45 --- /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 + -- cgit 1.4.1-3-g733a5 From 8e48a304dc1aa87bfed8f8e8c137477efc64cfd0 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 29 Apr 2020 10:14:57 +0200 Subject: 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 c9661c92d2e..7b42d7ab6e8 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 + ); } } } -- cgit 1.4.1-3-g733a5 From ff39457364659e485991fdb0f145858ff2fb016f Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 29 Apr 2020 12:34:51 +0200 Subject: 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 ++- src/test/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 b6c635fb22a..0637ebf959e 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 e1146ef30d1..7f557e340bb 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 7b42d7ab6e8..4caf2caa8cc 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 4be95b69850..81de8dcece6 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 dbc50f1fbd4..3b7f1de5b9b 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 0e213555052..14a49810b9d 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 + | +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: `#[deny(const_err)]` on by default + = 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 c2d8e6d421a..ddd1fb1ba76 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 4d4c2876c45..a79ac62d5cd 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 -- cgit 1.4.1-3-g733a5 From d3b2e1fb9ed93575c9780e63f29a28d478b36c2b Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 29 Apr 2020 14:02:41 +0200 Subject: 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 4caf2caa8cc..8ce2cabed5d 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); } } -- cgit 1.4.1-3-g733a5 From a06740cbea6c821d0aab3bf9f4882ed3716d0a36 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 29 Apr 2020 14:04:40 +0200 Subject: 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 8ce2cabed5d..02a7f24a1e3 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>( -- cgit 1.4.1-3-g733a5 From e73ee41241240f740afc10a6fc16521215759ed7 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 4 May 2020 11:29:16 +0200 Subject: 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 5014a601390..06fb27bcff8 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 3d200e23173..cabd754e01a 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 c6dbf086ec0..b5b5a965295 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 _; | ^^^^^^^^^^^^^^^^^^^^ -- cgit 1.4.1-3-g733a5 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: 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 4647ad01006..4df9eaa4815 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 /// -- cgit 1.4.1-3-g733a5 From a26335b2a0972ccd92468f9ea811a5c9253c9f84 Mon Sep 17 00:00:00 2001 From: Sébastien Marie Date: Sun, 10 May 2020 10:23:13 +0000 Subject: 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 34d83e0d339..33fee44d793 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 f543f8051a4..81ad032967b 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" -- cgit 1.4.1-3-g733a5 From 0aaff14ae38aa24729fe2fc056ce9fc79b5dda57 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 10 May 2020 12:40:11 +0200 Subject: 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 c2a3a8d7588..eadae05aa30 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; }; -- cgit 1.4.1-3-g733a5 From 62116c31cd863c8aab35e5c7acfb8ded41ca28a1 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Sun, 10 May 2020 00:33:08 +0200 Subject: 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 48e36fdb3d4..15bd87d5ffd 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 f86972b7348..a97c5750f94 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 3ad405b2b50..f0e2ebfc37a 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 98283066361..a09f91c68ab 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 197e45219c3..53eafb05830 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 + -- cgit 1.4.1-3-g733a5 From 32a46e91155de70eeca062a1ece74cea56574649 Mon Sep 17 00:00:00 2001 From: csmoe Date: Wed, 6 May 2020 18:43:56 +0800 Subject: 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 00000000000..0c6c5311997 --- /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() {} -- cgit 1.4.1-3-g733a5 From 2e2aac4f57b6bd4ca8e17b9143d49c14371e071f Mon Sep 17 00:00:00 2001 From: csmoe Date: Wed, 6 May 2020 18:44:14 +0800 Subject: 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 996a01d413c..ed8c614b109 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 53f72804a84..2ffa77031f3 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 956e09ec52b..53891a4fd9f 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) { -- cgit 1.4.1-3-g733a5 From 114cd006f52272618bd64382213cd08eaa313136 Mon Sep 17 00:00:00 2001 From: csmoe Date: Sat, 9 May 2020 22:04:02 +0800 Subject: 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 53891a4fd9f..bd5049446e6 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); -- cgit 1.4.1-3-g733a5 From 627f473dd426497972cce58ba64e8b0ff2409078 Mon Sep 17 00:00:00 2001 From: csmoe Date: Sun, 10 May 2020 20:07:42 +0800 Subject: 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 ed8c614b109..ef748bcee6e 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 405c656bad5..272827cfef8 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 74dd47a91c2..d0b39d6016a 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 bd5049446e6..c142e88b7de 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, -- cgit 1.4.1-3-g733a5 From c7e64f54c86a05ddd09fc3da4e98a8d748658337 Mon Sep 17 00:00:00 2001 From: csmoe Date: Sun, 10 May 2020 22:34:01 +0800 Subject: 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 ef748bcee6e..996a01d413c 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 2ffa77031f3..a503e3534e3 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 272827cfef8..c7487030686 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 d0b39d6016a..b28f0001cd9 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, ); } -- cgit 1.4.1-3-g733a5 From 7e62240801cc5f7aa70300fb0f92f54370eabea6 Mon Sep 17 00:00:00 2001 From: Marko Mijalkovic Date: Sun, 10 May 2020 16:06:33 -0400 Subject: 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 7a0e1e2c638..ab59a1c5f48 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 80c253b86bb..eb38dee63b6 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 dab1e51e3f8..91dfa1550f6 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); -- cgit 1.4.1-3-g733a5 From dc7524be2720fd4ca8d30ecdd776c4c620b83846 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 9 May 2020 19:53:48 +0200 Subject: 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 e32beb1c611..5447434143c 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 028623aa7aa..b8960784ad2 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 390630ee51b..13f88c185ae 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 2a46c563d1f..d1e53db573e 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 bae90411496..c4bca4a0040 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 31bbd92cd62..15bf831a148 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 bcd79a49ece..446017f1fab 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 1760d655b3b..74b47d07728 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 0cf47d20ead..69d65ce9d2d 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 6de07d3e5cf..39baa6b8540 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, } -- cgit 1.4.1-3-g733a5 From a5ba75283e279205dd96d402dfde42041ac53fb4 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Sun, 10 May 2020 16:53:48 -0400 Subject: 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 3a8a5491255..93a414ff6b9 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); } } } -- cgit 1.4.1-3-g733a5 From 23d880b127c346be631d2a9dbcef3bd5dff7d305 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 10 May 2020 23:36:41 +0200 Subject: 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 913ccf8e680..f8afaecf218 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 2c699998ea9..1ce0300f239 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, ) } -- cgit 1.4.1-3-g733a5 From 7b649c7364f5128da33c34573a158477df030b70 Mon Sep 17 00:00:00 2001 From: Marko Mijalkovic Date: Sun, 10 May 2020 17:39:57 -0400 Subject: 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 ab59a1c5f48..dca9f12df09 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 eb38dee63b6..0c74454d0c5 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 91dfa1550f6..00088a0d040 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); -- cgit 1.4.1-3-g733a5 From 744449433004fbdc3d0d665551e59ca2880f0552 Mon Sep 17 00:00:00 2001 From: Marko Mijalkovic Date: Sun, 10 May 2020 17:53:04 -0400 Subject: 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 dca9f12df09..ca2d1b0488d 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 { -- cgit 1.4.1-3-g733a5 From 82e81191e44fc61c5b583608dd17d76fa8fdc06e Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 10 May 2020 23:55:41 +0200 Subject: update miri --- src/tools/miri | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/miri b/src/tools/miri index 7f3366288d1..4c784796103 160000 --- a/src/tools/miri +++ b/src/tools/miri @@ -1 +1 @@ -Subproject commit 7f3366288d126408815eeafa8d7cd6e9f3ea56b9 +Subproject commit 4c784796103173c503e44fcdb12cb79ef0aba820 -- cgit 1.4.1-3-g733a5 From 51e466de3cbfb94b7d0736066a765d8ea31394e4 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 11 May 2020 00:11:42 +0200 Subject: 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 f8afaecf218..6847b175e60 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) } -- cgit 1.4.1-3-g733a5 From 00dcb665e7ede908ba11638e8230340f396674f8 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Mon, 11 May 2020 00:16:16 +0300 Subject: 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 dbe281be7df..c638f88057a 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 4eabb55e6df..ed7b2b3d58a 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 00000000000..f71a9c3c582 --- /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"{{.*}} } +} -- cgit 1.4.1-3-g733a5 From a32463ade42d12de8da974796fb45a72e57721db Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Mon, 11 May 2020 02:10:25 +0200 Subject: 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 +++++++++++----------- src/librustc_mir/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 d3ab7df817b..a3ee49651ba 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 29636a06709..b820b79c47f 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 894a997ea7a..edd2dc3c2de 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 ee8a4358147..9282a0a06b4 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, -- cgit 1.4.1-3-g733a5 From a1104b4dea0e0d3b35fa73c7f7c186f76b23db78 Mon Sep 17 00:00:00 2001 From: csmoe Date: Sun, 10 May 2020 22:34:20 +0800 Subject: 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 a503e3534e3..53f72804a84 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 de0373c1384..a3f8cd1ee36 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 b28f0001cd9..5e3b383ff25 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 61f2570b2ff..96158fc0e04 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 0c6c5311997..04a9148ae24 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 00000000000..fb1eead04e6 --- /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`. -- cgit 1.4.1-3-g733a5 From 42f70d503b9a6c87ebb84e44842e421ef01a0421 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 11 May 2020 12:13:53 +0200 Subject: 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 ad3fd0d64a3..97565013265 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 4c784796103..10419b3f2fc 160000 --- a/src/tools/miri +++ b/src/tools/miri @@ -1 +1 @@ -Subproject commit 4c784796103173c503e44fcdb12cb79ef0aba820 +Subproject commit 10419b3f2fc625bb9d746c16d768e433a894484d -- cgit 1.4.1-3-g733a5 From 806f09cf21129ec92c975e99443850d376281e04 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 11 May 2020 13:22:56 +0200 Subject: 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 225e27f0cab..f554242a3d4 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. -- cgit 1.4.1-3-g733a5 From 5e354932fe2e2b6b4f55f404148e6b5fa0a3392a Mon Sep 17 00:00:00 2001 From: Igor Matuszewski Date: Tue, 5 May 2020 13:26:02 +0200 Subject: cargo update -p serde_derive --- Cargo.lock | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 033ebc884a3..012d3328f12 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]] -- cgit 1.4.1-3-g733a5 From 403a9d0867ca01a5aecbe88b535ed902a9d4a633 Mon Sep 17 00:00:00 2001 From: Igor Matuszewski Date: Tue, 5 May 2020 13:26:16 +0200 Subject: cargo update -p failure_derive --- Cargo.lock | 30 +++++++++--------------------- 1 file changed, 9 insertions(+), 21 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 012d3328f12..f05a1562d0d 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" -- cgit 1.4.1-3-g733a5 From 8c6e568141977702a43d70e0bf0258d32ef71f76 Mon Sep 17 00:00:00 2001 From: Igor Matuszewski Date: Tue, 5 May 2020 13:26:29 +0200 Subject: cargo update -p pest_generator --- Cargo.lock | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f05a1562d0d..51a166890bd 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]] -- cgit 1.4.1-3-g733a5 From 3bdacedfd9264549b6368cc060da16993701ec14 Mon Sep 17 00:00:00 2001 From: Igor Matuszewski Date: Tue, 5 May 2020 13:30:49 +0200 Subject: cargo update -p derive-new --- Cargo.lock | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 51a166890bd..43dcc6b9dae 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]] -- cgit 1.4.1-3-g733a5 From e26f35d343c1266012af31437a84e40eb33eaffb Mon Sep 17 00:00:00 2001 From: Igor Matuszewski Date: Tue, 5 May 2020 14:05:06 +0200 Subject: 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 43dcc6b9dae..cbdd43f7586 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 e6e758dccdf..ff41197faa1 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"] -- cgit 1.4.1-3-g733a5 From 7bea58eeac3a5a5280810623f06eadb3a8b891a3 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 3 May 2020 12:34:53 +0200 Subject: 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 4a5cc9aa591..a2bb651e2b7 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(); } -- cgit 1.4.1-3-g733a5 From 9a4e7183d4a6c31b32beca1a82095480ea32e359 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Mon, 11 May 2020 10:50:53 -0400 Subject: 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 366ea0ebbe5..291dbf60361 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 647da7c8a7e..1c120f81634 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: {} -- cgit 1.4.1-3-g733a5 From 8bfd84539e847b9ac9d7c811a370a9c3840d6c3b Mon Sep 17 00:00:00 2001 From: Matthias Krüger Date: Mon, 11 May 2020 13:01:37 +0200 Subject: 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 +- src/librustc_mir_build/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 +- src/librustc_query_system/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 a592bbc2bf9..af09779d072 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 78cbc1240b1..e94a0c6eb59 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 55bea57f3e2..b34685006e2 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 9e8f3a84e20..94cd4bcd4c6 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 f997df25e99..682b335c5d0 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 7ab66411b21..1e3676496ce 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 02fe7adcd07..571e50f5ae2 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 89bcb240d90..8f125098ee6 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 0f22288437c..65ff311d182 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 4cc6a27a6da..854f8eeaf34 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 75ac8e731b5..6e7d116ce1d 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 927e6a7e712..a6fa677cbc0 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 36343365ab6..d8875f8ac64 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 f85462eb78b..e8d02692f37 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 115e4a0e629..be0512dcac9 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 74dd47a91c2..4228c2342cc 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 0cec583bb56..a2aee9b6ef7 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 4dc15a6b2b6..14295810d55 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 a5a1e20396c..5dbcc5c9ec8 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 51ad1f04340..bf59b3f2573 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 4ad9651d563..8ec158ff938 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 4a9ad39e236..a00c9a0bcea 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 7a3cbbe4562..738f07250b5 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 aac454c023c..0cec8050c27 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, -- cgit 1.4.1-3-g733a5 From 10f3cd9bea7fed1382a8c2dd56841179b5703846 Mon Sep 17 00:00:00 2001 From: flip1995 Date: Mon, 11 May 2020 21:18:42 +0200 Subject: Update Cargo.lock --- Cargo.lock | 1 - 1 file changed, 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index 033ebc884a3..0ee46c84290 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", -- cgit 1.4.1-3-g733a5 From e7b02046a0b34ec6d114a7ba5549db8457684ec4 Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sun, 10 May 2020 21:09:56 +0100 Subject: Fix hang in lexical_region_resolve --- .../infer/lexical_region_resolve/mod.rs | 20 ++++++++++++++++---- .../ui/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 3ff0e26a4dc..33a80fb7471 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 00000000000..b7340b79d68 --- /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() {} -- cgit 1.4.1-3-g733a5 From a3cc435f5755f5550d4235779de58b53a22f0f1e Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 11 May 2020 11:46:13 +1000 Subject: 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 a8e19c9cbaa..ac5399acddb 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 -- cgit 1.4.1-3-g733a5 From 6de6d70ae0a21b779d63d885438c7214e17e7a6d Mon Sep 17 00:00:00 2001 From: Wesley Wiser Date: Mon, 11 May 2020 20:13:15 -0400 Subject: 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 | 352 ++++++++++++++++++--- .../32bit/rustc.main.SimplifyArmIdentity.diff | 31 +- .../64bit/rustc.main.SimplifyArmIdentity.diff | 31 +- src/test/mir-opt/simplify-arm.rs | 32 ++ .../simplify-arm/rustc.id.SimplifyArmIdentity.diff | 45 +++ .../simplify-arm/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 ++++++ .../rustc.try_identity.SimplifyArmIdentity.diff | 53 +++- ...rustc.try_identity.SimplifyBranchSame.after.mir | 22 +- .../rustc.try_identity.SimplifyLocals.after.mir | 19 +- src/test/mir-opt/simplify_try_if_let.rs | 40 +++ .../rustc.{{impl}}-append.SimplifyArmIdentity.diff | 127 ++++++++ 16 files changed, 1032 insertions(+), 73 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 220691c1570..7ad5baac205 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 d22c2d90600..41ffa659441 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, - }; + 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; + } - // 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; - } + // 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(); + } - // 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())); + 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(); + } + } } - _ => unreachable!(), + + // 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 bf24bfb2c57..6199e2c5662 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 ff7183e57d2..bf875c6a555 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 00000000000..0e3f86501bb --- /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 00000000000..8d08267d75b --- /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 00000000000..23fa9817f80 --- /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 00000000000..e2a12ca5be2 --- /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 00000000000..9d1ff22dc51 --- /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 00000000000..ba6e1ac24cb --- /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 00000000000..4061c5e74ac --- /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 009153cfd49..58c5313909f 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 e5661a47201..be61e5e2a9f 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 989931ed0ea..b12036f6a03 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 00000000000..6ccec937b9b --- /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 + } + } + -- cgit 1.4.1-3-g733a5 From f420726566587862ef4da9153fbc2800ed444033 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 11 May 2020 12:26:59 +1000 Subject: 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 2f50234b6d5..540649c61b3 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 ac5399acddb..921ef447be0 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)? -- cgit 1.4.1-3-g733a5 From 68b75033ad78d88872450a81745cacfc11e58178 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 11 May 2020 13:17:28 +1000 Subject: 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 921ef447be0..d46bf81f996 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`. /// -- cgit 1.4.1-3-g733a5 From 41f6b958d502b3e3d4de1b787a3981c9d752dd78 Mon Sep 17 00:00:00 2001 From: Jack Huey Date: Tue, 12 May 2020 01:56:29 -0400 Subject: Remove ty::UnnormalizedProjection --- src/librustc_codegen_ssa/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 +- src/librustc_mir/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 - src/librustc_trait_selection/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 - .../ui-fulldeps/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 6c0e4128e30..1d8730db546 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 a0b5dd45a0e..5551b56ab79 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 d8133c58df7..0141ba82737 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 47346c3a856..c9ed687eaf2 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 1d97b286024..703c2a7a443 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 67f4b15f919..e030125b5b1 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 86b740b8503..7feb080d4b8 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 f3b6a53dfeb..cf63a659e6c 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 2a937d6581d..16d8e379407 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 a88f3628109..042ffc4d1e5 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 7c4e4d095bc..1339281667e 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 02fe7adcd07..5ed3c3dab93 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 4fd4d0d1f06..afd670b8577 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 6bdc65eb056..69b36980bd7 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 757a8bd23f6..41a6cd5466f 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 2684492a406..06ad90a147a 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 9c198dd556a..d68bc7221f9 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 c8406a024ec..680b7187921 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 a6cf3b7e2ee..2ad673b2c19 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 a89927ecfb7..f9c10488ffb 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 b6cadd00996..0093c60d768 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 b81a454cac4..71cca725982 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 4f90f83b735..748cb8d9d1a 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 917e2f54830..b474b23ac4f 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 01e9356b42f..3038b0c6bd7 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 53df140e0b5..3b439e09a9d 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 f9ff772900b..85c2f9246af 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 405c656bad5..1620bdfa66e 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 64cc5fadeab..856a2111fc8 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 b595f77e4d6..f0ff30232b9 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 1d4afeaae42..ba7ec96775c 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 4dc15a6b2b6..6ba8e63886b 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 76ff58d61a2..08475d6a09d 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 6add099e75b..1aa11a761c8 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 981e6d2c47e..46d6706cbf4 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 01d077d47f0..3a680f55c8c 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 8cd9ab41aa4..6c001bc5484 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 66b594a1b09..27fe432e96d 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 ee9f1ff10f8..0486c90a5a0 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(..) => (), - | ^^^^^^ help: try using ty:: directly: `ty` - -error: usage of `ty::TyKind::` - --> $DIR/ty_tykind_usage.rs:36:9 - | LL | TyKind::Opaque(..) => (), | ^^^^^^ help: try using ty:: directly: `ty` error: usage of `ty::TyKind::` - --> $DIR/ty_tykind_usage.rs:37:9 + --> $DIR/ty_tykind_usage.rs:36:9 | LL | TyKind::Param(..) => (), | ^^^^^^ help: try using ty:: directly: `ty` error: usage of `ty::TyKind::` - --> $DIR/ty_tykind_usage.rs:38:9 + --> $DIR/ty_tykind_usage.rs:37:9 | LL | TyKind::Bound(..) => (), | ^^^^^^ help: try using ty:: directly: `ty` error: usage of `ty::TyKind::` - --> $DIR/ty_tykind_usage.rs:39:9 + --> $DIR/ty_tykind_usage.rs:38:9 | LL | TyKind::Placeholder(..) => (), | ^^^^^^ help: try using ty:: directly: `ty` error: usage of `ty::TyKind::` - --> $DIR/ty_tykind_usage.rs:40:9 + --> $DIR/ty_tykind_usage.rs:39:9 | LL | TyKind::Infer(..) => (), | ^^^^^^ help: try using ty:: directly: `ty` error: usage of `ty::TyKind::` - --> $DIR/ty_tykind_usage.rs:41:9 + --> $DIR/ty_tykind_usage.rs:40: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 -- cgit 1.4.1-3-g733a5 From 6f9810c981f43cab6f4598d2d3b3e6e9b82d56ee Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 12 May 2020 09:46:41 +0200 Subject: 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 4f90f83b735..7eb05ba2d2c 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 29ac32fcf22..f69f6a1109f 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 063ea81036b..47d29ffc9b3 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. -- cgit 1.4.1-3-g733a5 From 98d625441501aa23284a1897c4a6511a46a86ce5 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 12 May 2020 15:56:02 +1000 Subject: 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 ++--- src/librustc_incremental/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 6210559251d..46e17d66d61 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 dd715c6c81d..7fd4b3c2554 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 99c799950c0..966faa9639d 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 6a03a01430b..7bc3b47e15a 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 4db6297712c..c43d4ad4049 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 a15ee6d81db..19d64bda56d 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 5f14a09b24d..04a45090b72 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)] -- cgit 1.4.1-3-g733a5 From c849a0d087546d9ef5a47593287b2bc1ec5bfcaf Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Tue, 12 May 2020 12:55:55 +0200 Subject: 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 00000000000..4f43ec8c947 --- /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 00000000000..b88bb9b4915 --- /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 + } + } + -- cgit 1.4.1-3-g733a5 From de434d8e44b40451eff0020832bb9a9303b32067 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Tue, 12 May 2020 13:14:47 +0200 Subject: 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 e898f22ec23..d66c909fe6c 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 b88bb9b4915..3cf05f13578 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: () -- cgit 1.4.1-3-g733a5 From 0a785cdf34e2eba2200677aa2a397bc3ddeed270 Mon Sep 17 00:00:00 2001 From: Oliver Scherer Date: Tue, 12 May 2020 13:23:01 +0200 Subject: Add some more sanity tests and add a debug log message for it --- src/librustc_mir/transform/const_prop.rs | 5 ++ .../const_prop/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 d66c909fe6c..88dfa90ac21 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 00000000000..40f801b1b5e --- /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 00000000000..738343c655e --- /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 + } + } + -- cgit 1.4.1-3-g733a5 From 3fccdb3ded1aea60b699cc3d11dcd886f70fbb0e Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 1 May 2020 12:10:06 +0200 Subject: Pointer printing: do not print 0 offset --- src/librustc_middle/mir/interpret/pointer.rs | 28 ++++++++++++++-------- ...ustc.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 +++++----- .../const-pointer-values-in-various-types.stderr | 14 +++++------ .../ui/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 0b060056499..70cc546199b 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 b8ecaf787fe..88cb09ac15a 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 d202531c7ab..509947071b0 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 d517207390d..8eb8d4c667b 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 b49c1aaa866..d9c6b4f0029 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 09c08cf449f..781aa3c5500 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 a20dd7bf0fc..30a383fd162 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 ff89ac9ad93..5fa54ae5a58 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 e392eaa6aed..d386d247829 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 81dc0372b5d..d7acd0f0f43 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 a29327eb973..39c60ad987a 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 865c7c93432..96024f1c82c 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 1e9cbe6024c..b7f1242d8d1 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 bbe0d106011..103444f796e 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 649105812b0..d24491e1bc5 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 df6fc66620b..cb0ba5d9929 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 8f0ce58eaf5..d8dafac3e70 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 95a83d11acd..a219679f182 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. -- cgit 1.4.1-3-g733a5 From 61fbe57f4afd8f5b1a348b644d00c912d4b2e9fb Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 12 May 2020 13:36:57 +0200 Subject: 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 947ec255a9d..89f6e3269ec 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() { -- cgit 1.4.1-3-g733a5 From 5063297c798c98f785047d4e18a3b9fd1a5331d8 Mon Sep 17 00:00:00 2001 From: Wesley Wiser Date: Tue, 12 May 2020 08:11:58 -0400 Subject: 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 632607e3356..c889dbc0a44 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, -- cgit 1.4.1-3-g733a5 From 34b2072599c2d14a36ed8cb7adeb0db44b8f76b3 Mon Sep 17 00:00:00 2001 From: Joshua Cotton Date: Wed, 6 May 2020 20:24:40 -0400 Subject: 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 9a91f37c5de..b7d0fac5be3 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 = { -- cgit 1.4.1-3-g733a5 From 2d39f5abcd3953eb1578f718c75c39c457bcb009 Mon Sep 17 00:00:00 2001 From: Kornel Date: Tue, 12 May 2020 16:38:02 +0100 Subject: 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 738f07250b5..3134a596756 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 -- cgit 1.4.1-3-g733a5 From 003ed802c4a289d959d4212ad80f33df7f3e2bc3 Mon Sep 17 00:00:00 2001 From: Laurence Tratt Date: Tue, 12 May 2020 16:54:29 +0100 Subject: 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 996a9cdfc4d..79b6304958d 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 -- cgit 1.4.1-3-g733a5 From 6c415450fd2e33ec7056805b97475d7ea73eb04c Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Tue, 12 May 2020 13:00:10 -0400 Subject: 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 e32beb1c611..f76ccac8953 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 b0e06731330..731382e4f75 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 390630ee51b..ef822dd3e5f 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) { -- cgit 1.4.1-3-g733a5 From 545320a22ff61c30e932200c07466ba3f2be76aa Mon Sep 17 00:00:00 2001 From: Esteban Küber Date: Wed, 22 Apr 2020 16:03:39 -0700 Subject: Suggest adding super trait constraints --- .../traits/error_reporting/suggestions.rs | 45 ++++++++++++++++++++-- .../defaults-unsound-62211-1.stderr | 16 ++++++-- .../defaults-unsound-62211-2.stderr | 16 ++++++-- src/test/ui/associated-types/issue-63593.stderr | 4 +- .../trait-with-supertraits-needing-sized-self.rs | 11 ++++++ ...rait-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 e0b99333fd1..5abae7ed68b 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 856d513d60b..c804bc3d833 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 1060c82fec2..aee5e4b28ca 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 c27800f5a3f..42529fd2b22 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 00000000000..0474bf0a339 --- /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 00000000000..707bcf5e2fe --- /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`. -- cgit 1.4.1-3-g733a5 From 45738e8cd1b026836f6cf161843971459bc1334e Mon Sep 17 00:00:00 2001 From: Esteban Küber Date: Wed, 22 Apr 2020 16:31:58 -0700 Subject: 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 ++++--- ...ssociated-types-no-suitable-supertrait-2.stderr | 10 ++++--- .../associated-types-no-suitable-supertrait.stderr | 10 ++++--- ...unrelated-trait-in-method-without-default.fixed | 2 +- ...nrelated-trait-in-method-without-default.stderr | 10 ++++--- .../associated-types-unsized.fixed | 2 +- .../associated-types-unsized.stderr | 6 ++-- .../associated-types/defaults-suitability.stderr | 16 ++++++---- .../defaults-unsound-62211-1.stderr | 34 ++++++++++++++-------- .../defaults-unsound-62211-2.stderr | 34 ++++++++++++++-------- src/test/ui/associated-types/issue-63593.stderr | 8 +++-- ...rait-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 +++---- .../missing-assoc-type-bound-restriction.stderr | 24 +++++++++------ .../type/type-params-in-different-spaces-2.stderr | 14 ++++++--- .../typeck-default-trait-impl-assoc-type.fixed | 2 +- .../typeck-default-trait-impl-assoc-type.stderr | 6 ++-- .../ui/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 ++++-- .../ui/wf/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 ++++-- src/test/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 5abae7ed68b..c9eb2ee6c5a 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 f65ae32c01c..cbacc3610dc 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 cc47f31d004..68ee38d16b3 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 c420c86a275..ab8909d1092 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 aa23326506f..80bbef17469 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 83d5390417e..6d7289bd071 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 6aa0403088d..dfe62aa5d6b 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 8c242be9796..f0f2451a1ec 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 f357045a456..9bc308465eb 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 cb01488fa34..4528f03c54a 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 f780d171fee..9837796e308 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 2352ac4ad38..6daba54ac69 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 3f6702da2a4..8676c1fa223 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 c804bc3d833..69c310766c1 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 aee5e4b28ca..84f0ba7529e 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 42529fd2b22..82e76ff0b7c 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 707bcf5e2fe..a37573dffff 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 283a5e04a8b..038490bbd7c 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 fbc72d063f3..3eb9d3c6203 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 915bfffd6d5..0d4797a7a06 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 6fc629b33a2..fb0914a8743 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 ef484e94729..a8ea2147961 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 7ce249a60b8..e0039f2a316 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 7a108d880be..dd1195b99f6 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 e64acfc54ff..f97d41637ba 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 70cf88f262f..e2892e3d248 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 ed563af5928..23d886e25ff 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 57cf1e9e6da..02140640172 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 534bf4d3448..3664c8b25aa 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 494619a2f29..b5f5f70ce81 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 6a3381d9a22..5e7d8cbfea6 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 2d6cf838f08..2d9ba56c585 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 -- cgit 1.4.1-3-g733a5 From 4556130e7d9fdf03bedfa177a658808dbec16b8a Mon Sep 17 00:00:00 2001 From: Esteban Küber Date: Thu, 7 May 2020 12:54:05 -0700 Subject: 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 f53489a99f3..775f9702401 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 | -- cgit 1.4.1-3-g733a5 From 722b3df454f427db019de2e3c54739b61e6f713b Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Tue, 12 May 2020 11:27:03 -0700 Subject: 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 e37c0e84e2e..6247be15a7f 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 8204c1d1234..49270740c7a 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 40beccdf1bb..366c50a03be 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 4d2d2759977..d1517d4e3f2 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 ed22e6fbfcb..892b928b565 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 ffc99581689..ab072b14393 160000 --- a/src/doc/rust-by-example +++ b/src/doc/rust-by-example @@ -1 +1 @@ -Subproject commit ffc99581689fe2455908aaef5f5cf50dd03bb8f5 +Subproject commit ab072b14393cbd9e8a1d1d75879bf51e27217bbb -- cgit 1.4.1-3-g733a5 From 58797b01f1b0925095986e4f42b839cdb2a99ac8 Mon Sep 17 00:00:00 2001 From: Esteban Küber Date: Tue, 12 May 2020 11:56:11 -0700 Subject: 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 c9eb2ee6c5a..5c4ba40bf38 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, -- cgit 1.4.1-3-g733a5 From 5320bd986b054d72522b29539278bfc5d576eabb Mon Sep 17 00:00:00 2001 From: Jade McGough Date: Mon, 11 May 2020 17:28:24 -0700 Subject: 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 + ...-lifetime-default-dyn-binding-nonstatic1.stderr | 1 + ...-lifetime-default-dyn-binding-nonstatic2.stderr | 1 + ...-lifetime-default-dyn-binding-nonstatic3.stderr | 1 + .../suggestions/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 e01412bc21c..2399e99a309 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 00000000000..3443a5ae863 --- /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 0c3dbffeea6..bd50a27fd5e 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 9dbf7a78ed7..f06a9da1dee 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 d069f52ce47..51d8450af76 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 9c7b6b98f2e..f721bf39419 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 f5ff54cc916..2630cf1affa 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 fe242e6a909..2c595833cd1 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`. -- cgit 1.4.1-3-g733a5 From 9111d8b66e013a881bae4e09646514be86ca4c87 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 4 May 2020 17:17:07 +1000 Subject: 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 0f0bd617f43..b42a2e711ac 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; } } -- cgit 1.4.1-3-g733a5 From 40d4868b3949c60de42e400baabe281a00a8c615 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 4 May 2020 19:25:09 +1000 Subject: 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 b42a2e711ac..bbe80c26dcb 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()); -- cgit 1.4.1-3-g733a5 From 5a0ac0552e05c079f252482cfcdaab3c4b39d614 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 13 May 2020 15:47:19 +1000 Subject: 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 f74c6862006..3386f83ec81 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)* -- cgit 1.4.1-3-g733a5 From 3b108588d159b4f4600ec226679f5ce64341b82e Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 13 May 2020 15:48:08 +1000 Subject: 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 34ca79154b6..447db405c02 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); } -- cgit 1.4.1-3-g733a5 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: 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 c51bf735fa7..dcb4cc91796 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 } -- cgit 1.4.1-3-g733a5 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: 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 f676a34a1d1..1d67d6de4da 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) { -- cgit 1.4.1-3-g733a5 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: 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 1b17f343a6d..4428d09902b 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 dcb4cc91796..2a9e1b7cbc3 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 e7b1ff6479d..f2b751a78f2 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 5ad43ad55a3..26bf463bd29 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 -- cgit 1.4.1-3-g733a5 From bb2ff593a63dc5500b0dd8d83cfa9bdca5768b79 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 13 May 2020 13:40:55 +0200 Subject: 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 c0cf44852c4..e50cc60ea33 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: -- cgit 1.4.1-3-g733a5 From 5f93bc774b1c0b9c415c4989cb81e6b650711e7d Mon Sep 17 00:00:00 2001 From: Bastian Kauschke Date: Wed, 13 May 2020 14:46:15 +0200 Subject: 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 efd5adeba8c..52ebcd63e7c 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 88cc63a7285..1ce079821a2 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 7c4e4d095bc..e1e47852dec 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 9282a0a06b4..059c241f9fe 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 4648100e3b7..a8094990594 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 847f59b95e9..d025468d28b 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 bfc872be653..1f1f74beb4b 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 2d7d3a0ccae..af7c88b178d 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 854f8eeaf34..d3129751586 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 47df82690e0..0779882b6dd 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, -- cgit 1.4.1-3-g733a5 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: 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 4df9eaa4815..542115763c2 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 /// -- cgit 1.4.1-3-g733a5 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: 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 542115763c2..515040dd4cc 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 { -- cgit 1.4.1-3-g733a5 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: 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 515040dd4cc..3e64177a467 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. -- cgit 1.4.1-3-g733a5 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: 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 3e64177a467..848560bd795 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 => (), -- cgit 1.4.1-3-g733a5 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: 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 848560bd795..340637a55f7 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 -- cgit 1.4.1-3-g733a5 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: 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 340637a55f7..a6a8d4bd7e1 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 /// -- cgit 1.4.1-3-g733a5 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: 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 a6a8d4bd7e1..ebaa4894862 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> { -- cgit 1.4.1-3-g733a5 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: 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 ebaa4894862..e8483875c97 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> { -- cgit 1.4.1-3-g733a5 From 2b42a2b541e04164428e83a4adfc4c120a482f82 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Wed, 13 May 2020 11:32:43 -0400 Subject: 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 fb380af0a47..646b9e05d99 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")), -- cgit 1.4.1-3-g733a5 From 617c7cd9fa9751375abbf1a43cfe29ffc19ee92b Mon Sep 17 00:00:00 2001 From: Tymoteusz Jankowski Date: Wed, 13 May 2020 16:54:16 +0200 Subject: Make intra links work inside trait impl block --- src/librustdoc/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 fbdb538cd87..a3ef350a048 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 00000000000..fab8406d525 --- /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(); +} -- cgit 1.4.1-3-g733a5 From cef616b1dc1b3e0aa846fd8325ab8dde94de12d5 Mon Sep 17 00:00:00 2001 From: CAD97 Date: Wed, 13 May 2020 14:49:45 -0400 Subject: 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 1b096893902..9e54e69bc55 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`; -- cgit 1.4.1-3-g733a5 From 9001a6429969be2732f0f0b650f193faeade89e7 Mon Sep 17 00:00:00 2001 From: Bastian Kauschke Date: Wed, 13 May 2020 21:38:58 +0200 Subject: 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 059c241f9fe..bad176c603f 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 1f1f74beb4b..14faa5be02f 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 8ae5ee4c3f9..bff1e727fe3 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) -- cgit 1.4.1-3-g733a5 From e44f87fca30186b6dd34932a8532d4e52b9b88fe Mon Sep 17 00:00:00 2001 From: Tshepang Lekhonkhobe Date: Wed, 13 May 2020 23:02:56 +0200 Subject: 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 710a41bc8fd..19b983018c9 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 -- cgit 1.4.1-3-g733a5 From 90b196129b85b5b2ae795e9bd621b95d7bec17b4 Mon Sep 17 00:00:00 2001 From: CAD97 Date: Wed, 13 May 2020 17:57:06 -0400 Subject: 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 9e54e69bc55..7a08d6d1ff3 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 } }; } -- cgit 1.4.1-3-g733a5 From dab3a5813e2590b2161d84a410e4d5bdc072152d Mon Sep 17 00:00:00 2001 From: Tomasz Miąsko Date: Thu, 14 May 2020 00:00:00 +0000 Subject: 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 19d289c87fd..dbee9d27d8a 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] -- cgit 1.4.1-3-g733a5 From 883c177abb216fcef5b2d2369970394b0967f302 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 4 May 2020 15:26:17 +0200 Subject: 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 0a682857b18..cd767802714 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 9454baf7640..abca8ab778c 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 53cf1abb16d..b8d97c2ac50 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 94ae69fde57..22e312e13c0 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, }; } -- cgit 1.4.1-3-g733a5 From c4d9318be6a493da4c6aa307dd4de7e24a15120a Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 7 May 2020 21:42:41 +0200 Subject: 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 22e312e13c0..7592331dd65 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 cb6ec4f8fed..798fa29efbd 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 e6310b625e5..896808d4157 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 8cd0a829974..84c638a1995 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 90315d6f644..1fa46ce99f5 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() { -- cgit 1.4.1-3-g733a5 From e17ac668997410a1a9d2da8725329afb8b5f2901 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 13 May 2020 17:03:37 +0200 Subject: * 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 b8d97c2ac50..57d385de320 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 7592331dd65..9b498d66249 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); } -- cgit 1.4.1-3-g733a5 From 31fbf33679a9b018576058d37b4f6cf9beec1b14 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 14 May 2020 11:51:39 +0200 Subject: 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 5e15a875b0b..8a4f8d21725 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 { -- cgit 1.4.1-3-g733a5 From 425723f5b384ba75af4b9a6b4e0186f8bf2e99a3 Mon Sep 17 00:00:00 2001 From: Marko Mijalkovic Date: Thu, 14 May 2020 06:19:36 -0400 Subject: Rewrite link script from scratch This absolves previous licensing issues. --- .../spec/mipsel_sony_psp_linker_script.ld | 297 ++------------------- 1 file changed, 21 insertions(+), 276 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 9dd38f5ce91..1bd436d6f94 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) } - - /* 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)) - } - + /* PRX format requires text to begin at 0 */ + .text 0 : { *(.text .text.*) } + + /* Sort stubs for convenient ordering */ + .sceStub.text : { *(.sceStub.text) *(SORT(.sceStub.text.*)) } + + /* 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.*)) } } -- cgit 1.4.1-3-g733a5 From bbb63d4554b03feee481bc799a04f183abaff1d4 Mon Sep 17 00:00:00 2001 From: Tomasz Miąsko Date: Wed, 13 May 2020 00:00:00 +0000 Subject: 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 +-- .../ui/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 dd9ada0b95d..a08235b304d 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 89bd96c1fe2..f5ae9824df8 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 0d466c2cd74..713cb2324f7 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 6210559251d..a88fef5aaac 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 b39b15dc244..cb5bd37442a 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 84bde9a52f7..b17fa57c5c1 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 00000000000..458f99143b6 --- /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); +} -- cgit 1.4.1-3-g733a5 From f6aa161936887bf4a0aaebbd5cfc743132a1ab0b Mon Sep 17 00:00:00 2001 From: Nathan Corbyn Date: Thu, 14 May 2020 11:37:58 +0100 Subject: 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 405c656bad5..784fc36e67e 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 00000000000..01d1cff42e4 --- /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 00000000000..57cf2468945 --- /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`. -- cgit 1.4.1-3-g733a5 From 0dc74dc0c6beb0bf2fd4fcc32cf3461a07f44521 Mon Sep 17 00:00:00 2001 From: sergey-melnychuk Date: Thu, 14 May 2020 20:02:40 +0200 Subject: 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 2cb6267e0f6..2932475430b 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 f676a34a1d1..aa048d682c2 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() -- cgit 1.4.1-3-g733a5 From 15c22922989774cb2102fc5c52f078f0f899cc62 Mon Sep 17 00:00:00 2001 From: Tyler Mandry Date: Thu, 14 May 2020 11:46:36 -0700 Subject: 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 7a0e1e2c638..dc712e509c2 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/", _ => "", -- cgit 1.4.1-3-g733a5 From c919a6ea09108d3c45bcfb9e95c6289a04606f53 Mon Sep 17 00:00:00 2001 From: JOE1994 Date: Thu, 14 May 2020 16:39:36 -0400 Subject: 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 3cf562b927e..34db59b1b45 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 c3eeea7662b..f02d8fe8ad6 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; -- cgit 1.4.1-3-g733a5 From d53068e3ea607ba757eeb496376fc955c5a85055 Mon Sep 17 00:00:00 2001 From: CAD97 Date: Thu, 14 May 2020 16:57:02 -0400 Subject: 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 7a08d6d1ff3..bae673408c6 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) - } } )+ }; -- cgit 1.4.1-3-g733a5 From 89543793126b142b8c40b4cc83e284a91cccb499 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 14 May 2020 23:29:50 +0200 Subject: make sure even unleashed miri does not do pointer stuff --- src/test/ui/consts/miri_unleashed/ptr_arith.rs | 29 ++++++++++++++++ src/test/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 00000000000..81985f9f625 --- /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 00000000000..5bd534a16b8 --- /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`. -- cgit 1.4.1-3-g733a5 From 00d42bbd2aa6222dc62177ebcecefd76ca977b9b Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Thu, 14 May 2020 13:03:33 -0300 Subject: Add prioritize_on attribute to triagebot --- triagebot.toml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/triagebot.toml b/triagebot.toml index 56d29994a8d..2210a8ff8e6 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 -- cgit 1.4.1-3-g733a5 From e84b379351577cae8cc3e89bf66c71bcabf547d7 Mon Sep 17 00:00:00 2001 From: Wesley Wiser Date: Thu, 23 Apr 2020 17:09:21 -0400 Subject: [const-prop] Don't replace Rvalues that are already constants --- src/librustc_mir/transform/const_prop.rs | 7 +++++++ .../mir-opt/const_prop/mutable_variable/rustc.main.ConstProp.diff | 3 +-- .../mutable_variable_aggregate/rustc.main.ConstProp.diff | 3 +-- .../copy_propagation_arg/rustc.arg_src.CopyPropagation.diff | 2 +- .../mir-opt/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 e898f22ec23..bdf2193c6af 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 c6c5b0cf726..187c1745435 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 26f0250d94c..cf432b2acc1 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 b976449ca6d..1e0271a560f 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 26f8068f674..b875bbea67b 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 -- cgit 1.4.1-3-g733a5 From 257e3772cb1b434a3c3fc8ac61ef808929036558 Mon Sep 17 00:00:00 2001 From: Lzu Tao Date: Fri, 15 May 2020 04:49:23 +0000 Subject: 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 a259e293b0c..9039e71b828 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 -- cgit 1.4.1-3-g733a5 From 10d7da4e0b07f469c9d2b8215b563528adfc7e99 Mon Sep 17 00:00:00 2001 From: csmoe Date: Thu, 14 May 2020 23:07:46 +0800 Subject: 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 +++++++-- src/test/ui/async-await/try-on-option-in-async.rs | 3 +- .../ui/async-await/try-on-option-in-async.stderr | 6 ++-- src/tools/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 a3f8cd1ee36..b823516d64f 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 2ceba519494..13cf9a934b7 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 239691dbd17..4acf766f033 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 5e3b383ff25..d5b2b765e93 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 778430fc2ca..9592f93ce2e 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 04a9148ae24..13b45df64ea 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 fb1eead04e6..e71f4e7136d 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 51ac522017c..c520a07abc1 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 46f8f41076b..700296d6747 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 2fd080e9ef0..84a324f76c5 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. -- cgit 1.4.1-3-g733a5 From 00268be9da13215398d779b2e344ffa3e300693c Mon Sep 17 00:00:00 2001 From: Nathan Corbyn Date: Thu, 14 May 2020 22:06:44 +0100 Subject: Remove lang_items\(\).*\.unwrap\(\) --- src/librustc_mir/monomorphize/mod.rs | 4 +++- src/librustc_mir_build/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 98a3d9584f5..28edd87a3ad 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 d3129751586..28ec2ca13d5 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 8007290f35d..eb63505b69b 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 035e5880dc5..87a6f119acb 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 64de94ea58c..9694ce9450c 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 956e09ec52b..f06303ecff9 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 c01c4d90c8e..efa3cd9955b 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()); -- cgit 1.4.1-3-g733a5 From 084cdde976e2485104bc14b8079238b37ab8aac1 Mon Sep 17 00:00:00 2001 From: SOFe Date: Fri, 15 May 2020 22:41:36 +0800 Subject: 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 173d6d1cfa7..8516e80f3b8 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), -- cgit 1.4.1-3-g733a5 From 45ee3360072a4bed1a2625dc03bdae1bd5aee5c4 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Thu, 14 May 2020 22:36:17 -0700 Subject: 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 ++++++++--- .../lint/redundant-semicolon/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 d2222d12623..a8f6a90ef76 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 a0e7d90f497..bf0d8fcee5b 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 31bc61263ab..f34a39996fe 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 afc6dc36eb4..b9693c2c862 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 a79fba9bf3f..bc0c5330324 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 | -- cgit 1.4.1-3-g733a5 From 4c4b4c4ab407f0ccdfc71caf443735e5ba62539c Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Fri, 15 May 2020 09:01:26 -0700 Subject: Add test of proc_macro::TokenStream's Debug --- .../proc-macro/debug/auxiliary/macro-dump-debug.rs | 15 ++ src/test/ui/proc-macro/debug/dump-debug.rs | 40 +++++ src/test/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 00000000000..56ad0612f74 --- /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 00000000000..0ed36b690f4 --- /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 00000000000..0aedefd4e60 --- /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), + }, +] -- cgit 1.4.1-3-g733a5 From d5ea92526549e40ff43b34f25fe6bee4418a3186 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Fri, 15 May 2020 09:12:41 -0700 Subject: 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 31bc61263ab..b6544341fa9 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}; -- cgit 1.4.1-3-g733a5 From bea2c59ea56cb3daa7e3bacabd7c95f002f9aca0 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Fri, 15 May 2020 09:35:46 -0700 Subject: 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 a8f6a90ef76..283aa25b0ea 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 -- cgit 1.4.1-3-g733a5 From 7433c4ddf3c226fc6beeed7a79f7d48777a3e807 Mon Sep 17 00:00:00 2001 From: Diggory Blake Date: Mon, 27 Apr 2020 22:50:55 +0100 Subject: 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 9e5c2b10d0d..17863dd38af 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 84f28488c74..115194a65a0 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 /// -- cgit 1.4.1-3-g733a5 From 004f4f389e5cf5cbb1f9604c5f7691cd16b1966e Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Fri, 15 May 2020 20:51:12 -0700 Subject: 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 437d0ffa119..93c7faf22a7 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 b6557163d45..e5f5a7d8968 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 2f2464d3629..ba479828538 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 = () -- cgit 1.4.1-3-g733a5 From 78eb64f35acf2c998c2ea6d9007f18d247d4ce88 Mon Sep 17 00:00:00 2001 From: Rustin-Liu Date: Sat, 16 May 2020 14:40:45 +0800 Subject: 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 52707b93acc..0d29d56ea1a 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`: -- cgit 1.4.1-3-g733a5 From 2e1c2a6d0a0d3785802c73d13039a0f0eea36b7c Mon Sep 17 00:00:00 2001 From: csmoe Date: Sat, 16 May 2020 18:29:46 +0800 Subject: 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 d27aae0d6ed..51f55417663 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 -- cgit 1.4.1-3-g733a5 From de24ddac0a80a6e16de1bfbfade772648cf66e18 Mon Sep 17 00:00:00 2001 From: Charles Lew Date: Sat, 16 May 2020 14:09:01 +0800 Subject: 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 + .../ui/rfc-2457/mod_file_nonascii_forbidden.rs | 6 ++++ .../ui/rfc-2457/mod_file_nonascii_forbidden.stderr | 20 +++++++++++ .../mod_file_nonascii_with_path_allowed.rs | 7 ++++ .../ui/rfc-2457/mod_inline_nonascii_allowed.rs | 8 +++++ .../ui/rfc-2457/no_mangle_nonascii_forbidden.rs | 6 ++++ .../rfc-2457/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 46c415413e9..8eb125e4440 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 2399e99a309..d6863c615f6 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 00000000000..abdc01ed21a --- /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 00000000000..e373b64384f --- /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 00000000000..efd2932f152 --- /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 00000000000..be729836f4f --- /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 00000000000..e9f3fba2fb0 --- /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 00000000000..dd27da432ba --- /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 00000000000..a408c975716 --- /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 00000000000..4ca83e41032 --- /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`. -- cgit 1.4.1-3-g733a5 From 993c4480ac0ad6233068b02f1f4c1d4096111cbe Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 16 May 2020 11:14:00 +0200 Subject: 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 17863dd38af..18767c482c7 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 -- cgit 1.4.1-3-g733a5 From 47034db8510ec4ea2a82ce3b8779b3b4816b1134 Mon Sep 17 00:00:00 2001 From: Esteban Küber Date: Sat, 16 May 2020 12:56:21 -0700 Subject: 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 6bd4455e1e3..0d53df3bf4b 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 cf8459609b6..828e8bc9f4a 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 -- cgit 1.4.1-3-g733a5 From 9271f998d176c7e5adf35a39fd2d6642bc399858 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Sat, 16 May 2020 22:10:28 +0200 Subject: Fix issue number typo in note --- src/librustc_trait_selection/traits/error_reporting/suggestions.rs | 2 +- .../feature-gates/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 503daf56b49..c098e44fa06 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 632afb24aa5..67721780682 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 -- cgit 1.4.1-3-g733a5 From 27c818bc56afd28b60dd9f71af11773d177745c8 Mon Sep 17 00:00:00 2001 From: Wesley Wiser Date: Sat, 16 May 2020 22:12:01 -0400 Subject: 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 3cf05f13578..6834bb6bdd4 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 -- cgit 1.4.1-3-g733a5 From 5980d972d1911225e38e98fe81974973349793a0 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 17 May 2020 11:06:59 +0200 Subject: 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 2f9505ec79f..0b2622b6ce3 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 dbee9d27d8a..12232520ef4 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 0f2665eba6f..fad3095f8a3 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 962bcbe6198..43512f7a236 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 94ea9b78828..16739b4a1af 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 8d8276b4159..b1e87a7cac2 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 05028ff0b2c..db6c30adb04 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 343b2ee1273..bf381896a22 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 fd9d61e99c2..d1a46c51757 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 79123903e92..603764922c5 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(); } -- cgit 1.4.1-3-g733a5 From 4caddaeeeaf0d6018325085b436256800c05b56c Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 17 May 2020 11:40:58 +0200 Subject: 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 6653c505bf5..390b7e96b9a 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, ); -- cgit 1.4.1-3-g733a5