mirror of https://github.com/rust-lang/rust.git
Auto merge of #110585 - JohnTitor:rollup-gfffoiv, r=JohnTitor
Rollup of 7 pull requests Successful merges: - #102341 (Implement `Neg` for signed non-zero integers.) - #110424 (Spelling misc) - #110448 (cmp doc examples improvements) - #110516 (bootstrap: Update linux-raw-sys to 0.3.2) - #110548 (Make `impl Debug for Span` not panic on not having session globals.) - #110554 (`deny(unsafe_op_in_unsafe_fn)` in `rustc_data_structures`) - #110575 (fix lint regression in `non_upper_case_globals`) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
13fc33e3f2
|
@ -12,7 +12,7 @@ Tracking issues are for tracking a feature from implementation to stabilization.
|
|||
Make sure to include the relevant RFC for the feature if it has one.
|
||||
|
||||
If the new feature is small, it may be fine to skip the RFC process. In that
|
||||
case, you can use use `issue = "none"` in your initial implementation PR. The
|
||||
case, you can use `issue = "none"` in your initial implementation PR. The
|
||||
reviewer will ask you to open a tracking issue if they agree your feature can be
|
||||
added without an RFC.
|
||||
-->
|
||||
|
@ -65,7 +65,7 @@ the rfcbot will ask all the team members to verify they agree with
|
|||
stabilization. Once enough members agree and there are no concerns, the final
|
||||
comment period begins: this issue will be marked as such and will be listed
|
||||
in the next This Week in Rust newsletter. If no blocking concerns are raised in
|
||||
that period of 10 days, a stabilzation PR can be opened by anyone.
|
||||
that period of 10 days, a stabilization PR can be opened by anyone.
|
||||
-->
|
||||
|
||||
### Unresolved Questions
|
||||
|
|
10
RELEASES.md
10
RELEASES.md
|
@ -963,7 +963,7 @@ Compatibility Notes
|
|||
- [rustdoc: doctests are now run on unexported `macro_rules!` macros, matching other private items][96630]
|
||||
- [rustdoc: Remove .woff font files][96279]
|
||||
- [Enforce Copy bounds for repeat elements while considering lifetimes][95819]
|
||||
- [Windows: Fix potentinal unsoundness by aborting if `File` reads or writes cannot
|
||||
- [Windows: Fix potential unsoundness by aborting if `File` reads or writes cannot
|
||||
complete synchronously][95469].
|
||||
|
||||
Internal Changes
|
||||
|
@ -1794,10 +1794,10 @@ Libraries
|
|||
- [impl Default, Copy, Clone for std::io::Sink and std::io::Empty][rust#86744]
|
||||
- [`impl From<[(K, V); N]>` for all collections.][rust#84111]
|
||||
- [Remove `P: Unpin` bound on impl Future for Pin.][rust#81363]
|
||||
- [Treat invalid environment variable names as non-existent.][rust#86183]
|
||||
- [Treat invalid environment variable names as nonexistent.][rust#86183]
|
||||
Previously, the environment functions would panic if given a variable name
|
||||
with an internal null character or equal sign (`=`). Now, these functions will
|
||||
just treat such names as non-existent variables, since the OS cannot represent
|
||||
just treat such names as nonexistent variables, since the OS cannot represent
|
||||
the existence of a variable with such a name.
|
||||
|
||||
Stabilised APIs
|
||||
|
@ -1990,7 +1990,7 @@ Compatibility Notes
|
|||
kinds of errors could be categorised [into newer more specific `ErrorKind`
|
||||
variants][79965], and that they do not represent a user error.
|
||||
- [Using environment variable names with `process::Command` on Windows now
|
||||
behaves as expected.][85270] Previously using envionment variables with
|
||||
behaves as expected.][85270] Previously using environment variables with
|
||||
`Command` would cause them to be ASCII-uppercased.
|
||||
- [Rustdoc will now warn on using rustdoc lints that aren't prefixed
|
||||
with `rustdoc::`][86849]
|
||||
|
@ -6367,7 +6367,7 @@ eg. `static MINUTE: Duration = Duration::from_secs(60);`
|
|||
|
||||
Cargo
|
||||
-----
|
||||
- [`cargo new` no longer removes `rust` or `rs` prefixs/suffixs.][cargo/5013]
|
||||
- [`cargo new` no longer removes `rust` or `rs` prefixes/suffixes.][cargo/5013]
|
||||
- [`cargo new` now defaults to creating a binary crate, instead of a
|
||||
library crate.][cargo/5029]
|
||||
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
#![allow(rustc::potential_query_instability)]
|
||||
#![deny(rustc::untranslatable_diagnostic)]
|
||||
#![deny(rustc::diagnostic_outside_of_impl)]
|
||||
#![deny(unsafe_op_in_unsafe_fn)]
|
||||
|
||||
#[macro_use]
|
||||
extern crate tracing;
|
||||
|
|
|
@ -13,7 +13,8 @@ pub struct Mmap(Vec<u8>);
|
|||
impl Mmap {
|
||||
#[inline]
|
||||
pub unsafe fn map(file: File) -> io::Result<Self> {
|
||||
memmap2::Mmap::map(&file).map(Mmap)
|
||||
// Safety: this is in fact not safe.
|
||||
unsafe { memmap2::Mmap::map(&file).map(Mmap) }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -96,28 +96,30 @@ macro_rules! compress {
|
|||
unsafe fn copy_nonoverlapping_small(src: *const u8, dst: *mut u8, count: usize) {
|
||||
debug_assert!(count <= 8);
|
||||
|
||||
if count == 8 {
|
||||
ptr::copy_nonoverlapping(src, dst, 8);
|
||||
return;
|
||||
}
|
||||
unsafe {
|
||||
if count == 8 {
|
||||
ptr::copy_nonoverlapping(src, dst, 8);
|
||||
return;
|
||||
}
|
||||
|
||||
let mut i = 0;
|
||||
if i + 3 < count {
|
||||
ptr::copy_nonoverlapping(src.add(i), dst.add(i), 4);
|
||||
i += 4;
|
||||
}
|
||||
let mut i = 0;
|
||||
if i + 3 < count {
|
||||
ptr::copy_nonoverlapping(src.add(i), dst.add(i), 4);
|
||||
i += 4;
|
||||
}
|
||||
|
||||
if i + 1 < count {
|
||||
ptr::copy_nonoverlapping(src.add(i), dst.add(i), 2);
|
||||
i += 2
|
||||
}
|
||||
if i + 1 < count {
|
||||
ptr::copy_nonoverlapping(src.add(i), dst.add(i), 2);
|
||||
i += 2
|
||||
}
|
||||
|
||||
if i < count {
|
||||
*dst.add(i) = *src.add(i);
|
||||
i += 1;
|
||||
}
|
||||
if i < count {
|
||||
*dst.add(i) = *src.add(i);
|
||||
i += 1;
|
||||
}
|
||||
|
||||
debug_assert_eq!(i, count);
|
||||
debug_assert_eq!(i, count);
|
||||
}
|
||||
}
|
||||
|
||||
// # Implementation
|
||||
|
@ -232,38 +234,40 @@ impl SipHasher128 {
|
|||
// overflow) if it wasn't already.
|
||||
#[inline(never)]
|
||||
unsafe fn short_write_process_buffer<const LEN: usize>(&mut self, bytes: [u8; LEN]) {
|
||||
let nbuf = self.nbuf;
|
||||
debug_assert!(LEN <= 8);
|
||||
debug_assert!(nbuf < BUFFER_SIZE);
|
||||
debug_assert!(nbuf + LEN >= BUFFER_SIZE);
|
||||
debug_assert!(nbuf + LEN < BUFFER_WITH_SPILL_SIZE);
|
||||
unsafe {
|
||||
let nbuf = self.nbuf;
|
||||
debug_assert!(LEN <= 8);
|
||||
debug_assert!(nbuf < BUFFER_SIZE);
|
||||
debug_assert!(nbuf + LEN >= BUFFER_SIZE);
|
||||
debug_assert!(nbuf + LEN < BUFFER_WITH_SPILL_SIZE);
|
||||
|
||||
// Copy first part of input into end of buffer, possibly into spill
|
||||
// element. The memcpy call is optimized away because the size is known.
|
||||
let dst = (self.buf.as_mut_ptr() as *mut u8).add(nbuf);
|
||||
ptr::copy_nonoverlapping(bytes.as_ptr(), dst, LEN);
|
||||
// Copy first part of input into end of buffer, possibly into spill
|
||||
// element. The memcpy call is optimized away because the size is known.
|
||||
let dst = (self.buf.as_mut_ptr() as *mut u8).add(nbuf);
|
||||
ptr::copy_nonoverlapping(bytes.as_ptr(), dst, LEN);
|
||||
|
||||
// Process buffer.
|
||||
for i in 0..BUFFER_CAPACITY {
|
||||
let elem = self.buf.get_unchecked(i).assume_init().to_le();
|
||||
self.state.v3 ^= elem;
|
||||
Sip13Rounds::c_rounds(&mut self.state);
|
||||
self.state.v0 ^= elem;
|
||||
// Process buffer.
|
||||
for i in 0..BUFFER_CAPACITY {
|
||||
let elem = self.buf.get_unchecked(i).assume_init().to_le();
|
||||
self.state.v3 ^= elem;
|
||||
Sip13Rounds::c_rounds(&mut self.state);
|
||||
self.state.v0 ^= elem;
|
||||
}
|
||||
|
||||
// Copy remaining input into start of buffer by copying LEN - 1
|
||||
// elements from spill (at most LEN - 1 bytes could have overflowed
|
||||
// into the spill). The memcpy call is optimized away because the size
|
||||
// is known. And the whole copy is optimized away for LEN == 1.
|
||||
let dst = self.buf.as_mut_ptr() as *mut u8;
|
||||
let src = self.buf.get_unchecked(BUFFER_SPILL_INDEX) as *const _ as *const u8;
|
||||
ptr::copy_nonoverlapping(src, dst, LEN - 1);
|
||||
|
||||
// This function should only be called when the write fills the buffer.
|
||||
// Therefore, when LEN == 1, the new `self.nbuf` must be zero.
|
||||
// LEN is statically known, so the branch is optimized away.
|
||||
self.nbuf = if LEN == 1 { 0 } else { nbuf + LEN - BUFFER_SIZE };
|
||||
self.processed += BUFFER_SIZE;
|
||||
}
|
||||
|
||||
// Copy remaining input into start of buffer by copying LEN - 1
|
||||
// elements from spill (at most LEN - 1 bytes could have overflowed
|
||||
// into the spill). The memcpy call is optimized away because the size
|
||||
// is known. And the whole copy is optimized away for LEN == 1.
|
||||
let dst = self.buf.as_mut_ptr() as *mut u8;
|
||||
let src = self.buf.get_unchecked(BUFFER_SPILL_INDEX) as *const _ as *const u8;
|
||||
ptr::copy_nonoverlapping(src, dst, LEN - 1);
|
||||
|
||||
// This function should only be called when the write fills the buffer.
|
||||
// Therefore, when LEN == 1, the new `self.nbuf` must be zero.
|
||||
// LEN is statically known, so the branch is optimized away.
|
||||
self.nbuf = if LEN == 1 { 0 } else { nbuf + LEN - BUFFER_SIZE };
|
||||
self.processed += BUFFER_SIZE;
|
||||
}
|
||||
|
||||
// A write function for byte slices.
|
||||
|
@ -301,57 +305,59 @@ impl SipHasher128 {
|
|||
// containing the byte offset `self.nbuf`.
|
||||
#[inline(never)]
|
||||
unsafe fn slice_write_process_buffer(&mut self, msg: &[u8]) {
|
||||
let length = msg.len();
|
||||
let nbuf = self.nbuf;
|
||||
debug_assert!(nbuf < BUFFER_SIZE);
|
||||
debug_assert!(nbuf + length >= BUFFER_SIZE);
|
||||
unsafe {
|
||||
let length = msg.len();
|
||||
let nbuf = self.nbuf;
|
||||
debug_assert!(nbuf < BUFFER_SIZE);
|
||||
debug_assert!(nbuf + length >= BUFFER_SIZE);
|
||||
|
||||
// Always copy first part of input into current element of buffer.
|
||||
// This function should only be called when the write fills the buffer,
|
||||
// so we know that there is enough input to fill the current element.
|
||||
let valid_in_elem = nbuf % ELEM_SIZE;
|
||||
let needed_in_elem = ELEM_SIZE - valid_in_elem;
|
||||
// Always copy first part of input into current element of buffer.
|
||||
// This function should only be called when the write fills the buffer,
|
||||
// so we know that there is enough input to fill the current element.
|
||||
let valid_in_elem = nbuf % ELEM_SIZE;
|
||||
let needed_in_elem = ELEM_SIZE - valid_in_elem;
|
||||
|
||||
let src = msg.as_ptr();
|
||||
let dst = (self.buf.as_mut_ptr() as *mut u8).add(nbuf);
|
||||
copy_nonoverlapping_small(src, dst, needed_in_elem);
|
||||
let src = msg.as_ptr();
|
||||
let dst = (self.buf.as_mut_ptr() as *mut u8).add(nbuf);
|
||||
copy_nonoverlapping_small(src, dst, needed_in_elem);
|
||||
|
||||
// Process buffer.
|
||||
// Process buffer.
|
||||
|
||||
// Using `nbuf / ELEM_SIZE + 1` rather than `(nbuf + needed_in_elem) /
|
||||
// ELEM_SIZE` to show the compiler that this loop's upper bound is > 0.
|
||||
// We know that is true, because last step ensured we have a full
|
||||
// element in the buffer.
|
||||
let last = nbuf / ELEM_SIZE + 1;
|
||||
// Using `nbuf / ELEM_SIZE + 1` rather than `(nbuf + needed_in_elem) /
|
||||
// ELEM_SIZE` to show the compiler that this loop's upper bound is > 0.
|
||||
// We know that is true, because last step ensured we have a full
|
||||
// element in the buffer.
|
||||
let last = nbuf / ELEM_SIZE + 1;
|
||||
|
||||
for i in 0..last {
|
||||
let elem = self.buf.get_unchecked(i).assume_init().to_le();
|
||||
self.state.v3 ^= elem;
|
||||
Sip13Rounds::c_rounds(&mut self.state);
|
||||
self.state.v0 ^= elem;
|
||||
for i in 0..last {
|
||||
let elem = self.buf.get_unchecked(i).assume_init().to_le();
|
||||
self.state.v3 ^= elem;
|
||||
Sip13Rounds::c_rounds(&mut self.state);
|
||||
self.state.v0 ^= elem;
|
||||
}
|
||||
|
||||
// Process the remaining element-sized chunks of input.
|
||||
let mut processed = needed_in_elem;
|
||||
let input_left = length - processed;
|
||||
let elems_left = input_left / ELEM_SIZE;
|
||||
let extra_bytes_left = input_left % ELEM_SIZE;
|
||||
|
||||
for _ in 0..elems_left {
|
||||
let elem = (msg.as_ptr().add(processed) as *const u64).read_unaligned().to_le();
|
||||
self.state.v3 ^= elem;
|
||||
Sip13Rounds::c_rounds(&mut self.state);
|
||||
self.state.v0 ^= elem;
|
||||
processed += ELEM_SIZE;
|
||||
}
|
||||
|
||||
// Copy remaining input into start of buffer.
|
||||
let src = msg.as_ptr().add(processed);
|
||||
let dst = self.buf.as_mut_ptr() as *mut u8;
|
||||
copy_nonoverlapping_small(src, dst, extra_bytes_left);
|
||||
|
||||
self.nbuf = extra_bytes_left;
|
||||
self.processed += nbuf + processed;
|
||||
}
|
||||
|
||||
// Process the remaining element-sized chunks of input.
|
||||
let mut processed = needed_in_elem;
|
||||
let input_left = length - processed;
|
||||
let elems_left = input_left / ELEM_SIZE;
|
||||
let extra_bytes_left = input_left % ELEM_SIZE;
|
||||
|
||||
for _ in 0..elems_left {
|
||||
let elem = (msg.as_ptr().add(processed) as *const u64).read_unaligned().to_le();
|
||||
self.state.v3 ^= elem;
|
||||
Sip13Rounds::c_rounds(&mut self.state);
|
||||
self.state.v0 ^= elem;
|
||||
processed += ELEM_SIZE;
|
||||
}
|
||||
|
||||
// Copy remaining input into start of buffer.
|
||||
let src = msg.as_ptr().add(processed);
|
||||
let dst = self.buf.as_mut_ptr() as *mut u8;
|
||||
copy_nonoverlapping_small(src, dst, extra_bytes_left);
|
||||
|
||||
self.nbuf = extra_bytes_left;
|
||||
self.processed += nbuf + processed;
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
|
|
@ -153,7 +153,7 @@ unsafe impl<T: ?Sized + Aligned> Pointer for Box<T> {
|
|||
#[inline]
|
||||
unsafe fn from_ptr(ptr: NonNull<T>) -> Self {
|
||||
// Safety: `ptr` comes from `into_ptr` which calls `Box::into_raw`
|
||||
Box::from_raw(ptr.as_ptr())
|
||||
unsafe { Box::from_raw(ptr.as_ptr()) }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -169,7 +169,7 @@ unsafe impl<T: ?Sized + Aligned> Pointer for Rc<T> {
|
|||
#[inline]
|
||||
unsafe fn from_ptr(ptr: NonNull<T>) -> Self {
|
||||
// Safety: `ptr` comes from `into_ptr` which calls `Rc::into_raw`
|
||||
Rc::from_raw(ptr.as_ptr())
|
||||
unsafe { Rc::from_raw(ptr.as_ptr()) }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -185,7 +185,7 @@ unsafe impl<T: ?Sized + Aligned> Pointer for Arc<T> {
|
|||
#[inline]
|
||||
unsafe fn from_ptr(ptr: NonNull<T>) -> Self {
|
||||
// Safety: `ptr` comes from `into_ptr` which calls `Arc::into_raw`
|
||||
Arc::from_raw(ptr.as_ptr())
|
||||
unsafe { Arc::from_raw(ptr.as_ptr()) }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -201,7 +201,7 @@ unsafe impl<'a, T: 'a + ?Sized + Aligned> Pointer for &'a T {
|
|||
unsafe fn from_ptr(ptr: NonNull<T>) -> Self {
|
||||
// Safety:
|
||||
// `ptr` comes from `into_ptr` which gets the pointer from a reference
|
||||
ptr.as_ref()
|
||||
unsafe { ptr.as_ref() }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -217,7 +217,7 @@ unsafe impl<'a, T: 'a + ?Sized + Aligned> Pointer for &'a mut T {
|
|||
unsafe fn from_ptr(mut ptr: NonNull<T>) -> Self {
|
||||
// Safety:
|
||||
// `ptr` comes from `into_ptr` which gets the pointer from a reference
|
||||
ptr.as_mut()
|
||||
unsafe { ptr.as_mut() }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -33,6 +33,11 @@ pub fn method_context(cx: &LateContext<'_>, id: LocalDefId) -> MethodLateContext
|
|||
}
|
||||
}
|
||||
|
||||
fn assoc_item_in_trait_impl(cx: &LateContext<'_>, ii: &hir::ImplItem<'_>) -> bool {
|
||||
let item = cx.tcx.associated_item(ii.owner_id);
|
||||
item.trait_item_def_id.is_some()
|
||||
}
|
||||
|
||||
declare_lint! {
|
||||
/// The `non_camel_case_types` lint detects types, variants, traits and
|
||||
/// type parameters that don't have camel case names.
|
||||
|
@ -177,6 +182,7 @@ impl EarlyLintPass for NonCamelCaseTypes {
|
|||
// trait impls where we should have warned for the trait definition already.
|
||||
ast::ItemKind::Impl(box ast::Impl { of_trait: None, items, .. }) => {
|
||||
for it in items {
|
||||
// FIXME: this doesn't respect `#[allow(..)]` on the item itself.
|
||||
if let ast::AssocItemKind::Type(..) = it.kind {
|
||||
self.check_case(cx, "associated type", &it.ident);
|
||||
}
|
||||
|
@ -494,15 +500,6 @@ impl<'tcx> LateLintPass<'tcx> for NonUpperCaseGlobals {
|
|||
hir::ItemKind::Const(..) => {
|
||||
NonUpperCaseGlobals::check_upper_case(cx, "constant", &it.ident);
|
||||
}
|
||||
// we only want to check inherent associated consts, trait consts
|
||||
// are linted at def-site.
|
||||
hir::ItemKind::Impl(hir::Impl { of_trait: None, items, .. }) => {
|
||||
for it in *items {
|
||||
if let hir::AssocItemKind::Const = it.kind {
|
||||
NonUpperCaseGlobals::check_upper_case(cx, "associated constant", &it.ident);
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
@ -513,6 +510,12 @@ impl<'tcx> LateLintPass<'tcx> for NonUpperCaseGlobals {
|
|||
}
|
||||
}
|
||||
|
||||
fn check_impl_item(&mut self, cx: &LateContext<'_>, ii: &hir::ImplItem<'_>) {
|
||||
if let hir::ImplItemKind::Const(..) = ii.kind && !assoc_item_in_trait_impl(cx, ii) {
|
||||
NonUpperCaseGlobals::check_upper_case(cx, "associated constant", &ii.ident);
|
||||
}
|
||||
}
|
||||
|
||||
fn check_pat(&mut self, cx: &LateContext<'_>, p: &hir::Pat<'_>) {
|
||||
// Lint for constants that look like binding identifiers (#7526)
|
||||
if let PatKind::Path(hir::QPath::Resolved(None, ref path)) = p.kind {
|
||||
|
|
|
@ -1044,17 +1044,26 @@ impl fmt::Debug for Span {
|
|||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
// Use the global `SourceMap` to print the span. If that's not
|
||||
// available, fall back to printing the raw values.
|
||||
with_session_globals(|session_globals| {
|
||||
if let Some(source_map) = &*session_globals.source_map.borrow() {
|
||||
write!(f, "{} ({:?})", source_map.span_to_diagnostic_string(*self), self.ctxt())
|
||||
} else {
|
||||
f.debug_struct("Span")
|
||||
.field("lo", &self.lo())
|
||||
.field("hi", &self.hi())
|
||||
.field("ctxt", &self.ctxt())
|
||||
.finish()
|
||||
}
|
||||
})
|
||||
|
||||
fn fallback(span: Span, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("Span")
|
||||
.field("lo", &span.lo())
|
||||
.field("hi", &span.hi())
|
||||
.field("ctxt", &span.ctxt())
|
||||
.finish()
|
||||
}
|
||||
|
||||
if SESSION_GLOBALS.is_set() {
|
||||
with_session_globals(|session_globals| {
|
||||
if let Some(source_map) = &*session_globals.source_map.borrow() {
|
||||
write!(f, "{} ({:?})", source_map.span_to_diagnostic_string(*self), self.ctxt())
|
||||
} else {
|
||||
fallback(*self, f)
|
||||
}
|
||||
})
|
||||
} else {
|
||||
fallback(*self, f)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -321,14 +321,11 @@ pub struct AssertParamIsEq<T: Eq + ?Sized> {
|
|||
/// ```
|
||||
/// use std::cmp::Ordering;
|
||||
///
|
||||
/// let result = 1.cmp(&2);
|
||||
/// assert_eq!(Ordering::Less, result);
|
||||
/// assert_eq!(1.cmp(&2), Ordering::Less);
|
||||
///
|
||||
/// let result = 1.cmp(&1);
|
||||
/// assert_eq!(Ordering::Equal, result);
|
||||
/// assert_eq!(1.cmp(&1), Ordering::Equal);
|
||||
///
|
||||
/// let result = 2.cmp(&1);
|
||||
/// assert_eq!(Ordering::Greater, result);
|
||||
/// assert_eq!(2.cmp(&1), Ordering::Greater);
|
||||
/// ```
|
||||
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
|
@ -784,8 +781,8 @@ pub trait Ord: Eq + PartialOrd<Self> {
|
|||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// assert_eq!(2, 1.max(2));
|
||||
/// assert_eq!(2, 2.max(2));
|
||||
/// assert_eq!(1.max(2), 2);
|
||||
/// assert_eq!(2.max(2), 2);
|
||||
/// ```
|
||||
#[stable(feature = "ord_max_min", since = "1.21.0")]
|
||||
#[inline]
|
||||
|
@ -804,8 +801,8 @@ pub trait Ord: Eq + PartialOrd<Self> {
|
|||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// assert_eq!(1, 1.min(2));
|
||||
/// assert_eq!(2, 2.min(2));
|
||||
/// assert_eq!(1.min(2), 1);
|
||||
/// assert_eq!(2.min(2), 2);
|
||||
/// ```
|
||||
#[stable(feature = "ord_max_min", since = "1.21.0")]
|
||||
#[inline]
|
||||
|
@ -829,9 +826,9 @@ pub trait Ord: Eq + PartialOrd<Self> {
|
|||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// assert!((-3).clamp(-2, 1) == -2);
|
||||
/// assert!(0.clamp(-2, 1) == 0);
|
||||
/// assert!(2.clamp(-2, 1) == 1);
|
||||
/// assert_eq!((-3).clamp(-2, 1), -2);
|
||||
/// assert_eq!(0.clamp(-2, 1), 0);
|
||||
/// assert_eq!(2.clamp(-2, 1), 1);
|
||||
/// ```
|
||||
#[must_use]
|
||||
#[stable(feature = "clamp", since = "1.50.0")]
|
||||
|
@ -1060,11 +1057,9 @@ pub trait PartialOrd<Rhs: ?Sized = Self>: PartialEq<Rhs> {
|
|||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// let result = 1.0 < 2.0;
|
||||
/// assert_eq!(result, true);
|
||||
///
|
||||
/// let result = 2.0 < 1.0;
|
||||
/// assert_eq!(result, false);
|
||||
/// assert_eq!(1.0 < 1.0, false);
|
||||
/// assert_eq!(1.0 < 2.0, true);
|
||||
/// assert_eq!(2.0 < 1.0, false);
|
||||
/// ```
|
||||
#[inline]
|
||||
#[must_use]
|
||||
|
@ -1079,11 +1074,9 @@ pub trait PartialOrd<Rhs: ?Sized = Self>: PartialEq<Rhs> {
|
|||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// let result = 1.0 <= 2.0;
|
||||
/// assert_eq!(result, true);
|
||||
///
|
||||
/// let result = 2.0 <= 2.0;
|
||||
/// assert_eq!(result, true);
|
||||
/// assert_eq!(1.0 <= 1.0, true);
|
||||
/// assert_eq!(1.0 <= 2.0, true);
|
||||
/// assert_eq!(2.0 <= 1.0, false);
|
||||
/// ```
|
||||
#[inline]
|
||||
#[must_use]
|
||||
|
@ -1097,11 +1090,9 @@ pub trait PartialOrd<Rhs: ?Sized = Self>: PartialEq<Rhs> {
|
|||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// let result = 1.0 > 2.0;
|
||||
/// assert_eq!(result, false);
|
||||
///
|
||||
/// let result = 2.0 > 2.0;
|
||||
/// assert_eq!(result, false);
|
||||
/// assert_eq!(1.0 > 1.0, false);
|
||||
/// assert_eq!(1.0 > 2.0, false);
|
||||
/// assert_eq!(2.0 > 1.0, true);
|
||||
/// ```
|
||||
#[inline]
|
||||
#[must_use]
|
||||
|
@ -1116,11 +1107,9 @@ pub trait PartialOrd<Rhs: ?Sized = Self>: PartialEq<Rhs> {
|
|||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// let result = 2.0 >= 1.0;
|
||||
/// assert_eq!(result, true);
|
||||
///
|
||||
/// let result = 2.0 >= 2.0;
|
||||
/// assert_eq!(result, true);
|
||||
/// assert_eq!(1.0 >= 1.0, true);
|
||||
/// assert_eq!(1.0 >= 2.0, false);
|
||||
/// assert_eq!(2.0 >= 1.0, true);
|
||||
/// ```
|
||||
#[inline]
|
||||
#[must_use]
|
||||
|
@ -1150,8 +1139,8 @@ pub macro PartialOrd($item:item) {
|
|||
/// ```
|
||||
/// use std::cmp;
|
||||
///
|
||||
/// assert_eq!(1, cmp::min(1, 2));
|
||||
/// assert_eq!(2, cmp::min(2, 2));
|
||||
/// assert_eq!(cmp::min(1, 2), 1);
|
||||
/// assert_eq!(cmp::min(2, 2), 2);
|
||||
/// ```
|
||||
#[inline]
|
||||
#[must_use]
|
||||
|
@ -1170,8 +1159,11 @@ pub fn min<T: Ord>(v1: T, v2: T) -> T {
|
|||
/// ```
|
||||
/// use std::cmp;
|
||||
///
|
||||
/// assert_eq!(cmp::min_by(-2, 1, |x: &i32, y: &i32| x.abs().cmp(&y.abs())), 1);
|
||||
/// assert_eq!(cmp::min_by(-2, 2, |x: &i32, y: &i32| x.abs().cmp(&y.abs())), -2);
|
||||
/// let result = cmp::min_by(-2, 1, |x: &i32, y: &i32| x.abs().cmp(&y.abs()));
|
||||
/// assert_eq!(result, 1);
|
||||
///
|
||||
/// let result = cmp::min_by(-2, 3, |x: &i32, y: &i32| x.abs().cmp(&y.abs()));
|
||||
/// assert_eq!(result, -2);
|
||||
/// ```
|
||||
#[inline]
|
||||
#[must_use]
|
||||
|
@ -1192,8 +1184,11 @@ pub fn min_by<T, F: FnOnce(&T, &T) -> Ordering>(v1: T, v2: T, compare: F) -> T {
|
|||
/// ```
|
||||
/// use std::cmp;
|
||||
///
|
||||
/// assert_eq!(cmp::min_by_key(-2, 1, |x: &i32| x.abs()), 1);
|
||||
/// assert_eq!(cmp::min_by_key(-2, 2, |x: &i32| x.abs()), -2);
|
||||
/// let result = cmp::min_by_key(-2, 1, |x: &i32| x.abs());
|
||||
/// assert_eq!(result, 1);
|
||||
///
|
||||
/// let result = cmp::min_by_key(-2, 2, |x: &i32| x.abs());
|
||||
/// assert_eq!(result, -2);
|
||||
/// ```
|
||||
#[inline]
|
||||
#[must_use]
|
||||
|
@ -1213,8 +1208,8 @@ pub fn min_by_key<T, F: FnMut(&T) -> K, K: Ord>(v1: T, v2: T, mut f: F) -> T {
|
|||
/// ```
|
||||
/// use std::cmp;
|
||||
///
|
||||
/// assert_eq!(2, cmp::max(1, 2));
|
||||
/// assert_eq!(2, cmp::max(2, 2));
|
||||
/// assert_eq!(cmp::max(1, 2), 2);
|
||||
/// assert_eq!(cmp::max(2, 2), 2);
|
||||
/// ```
|
||||
#[inline]
|
||||
#[must_use]
|
||||
|
@ -1233,8 +1228,11 @@ pub fn max<T: Ord>(v1: T, v2: T) -> T {
|
|||
/// ```
|
||||
/// use std::cmp;
|
||||
///
|
||||
/// assert_eq!(cmp::max_by(-2, 1, |x: &i32, y: &i32| x.abs().cmp(&y.abs())), -2);
|
||||
/// assert_eq!(cmp::max_by(-2, 2, |x: &i32, y: &i32| x.abs().cmp(&y.abs())), 2);
|
||||
/// let result = cmp::max_by(-2, 1, |x: &i32, y: &i32| x.abs().cmp(&y.abs()));
|
||||
/// assert_eq!(result, -2);
|
||||
///
|
||||
/// let result = cmp::max_by(-2, 2, |x: &i32, y: &i32| x.abs().cmp(&y.abs())) ;
|
||||
/// assert_eq!(result, 2);
|
||||
/// ```
|
||||
#[inline]
|
||||
#[must_use]
|
||||
|
@ -1255,8 +1253,11 @@ pub fn max_by<T, F: FnOnce(&T, &T) -> Ordering>(v1: T, v2: T, compare: F) -> T {
|
|||
/// ```
|
||||
/// use std::cmp;
|
||||
///
|
||||
/// assert_eq!(cmp::max_by_key(-2, 1, |x: &i32| x.abs()), -2);
|
||||
/// assert_eq!(cmp::max_by_key(-2, 2, |x: &i32| x.abs()), 2);
|
||||
/// let result = cmp::max_by_key(-2, 1, |x: &i32| x.abs());
|
||||
/// assert_eq!(result, -2);
|
||||
///
|
||||
/// let result = cmp::max_by_key(-2, 2, |x: &i32| x.abs());
|
||||
/// assert_eq!(result, 2);
|
||||
/// ```
|
||||
#[inline]
|
||||
#[must_use]
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
//! Definitions of integer that is known not to equal zero.
|
||||
|
||||
use crate::fmt;
|
||||
use crate::ops::{BitOr, BitOrAssign, Div, Rem};
|
||||
use crate::ops::{BitOr, BitOrAssign, Div, Neg, Rem};
|
||||
use crate::str::FromStr;
|
||||
|
||||
use super::from_str_radix;
|
||||
|
@ -664,8 +664,7 @@ macro_rules! nonzero_signed_operations {
|
|||
/// assert_eq!(pos, pos.wrapping_abs());
|
||||
/// assert_eq!(pos, neg.wrapping_abs());
|
||||
/// assert_eq!(min, min.wrapping_abs());
|
||||
/// # // FIXME: add once Neg is implemented?
|
||||
/// # // assert_eq!(max, (-max).wrapping_abs());
|
||||
/// assert_eq!(max, (-max).wrapping_abs());
|
||||
/// # Some(())
|
||||
/// # }
|
||||
/// ```
|
||||
|
@ -868,6 +867,20 @@ macro_rules! nonzero_signed_operations {
|
|||
unsafe { $Ty::new_unchecked(result) }
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "signed_nonzero_neg", since = "CURRENT_RUSTC_VERSION")]
|
||||
impl Neg for $Ty {
|
||||
type Output = $Ty;
|
||||
|
||||
#[inline]
|
||||
fn neg(self) -> $Ty {
|
||||
// SAFETY: negation of nonzero cannot yield zero values.
|
||||
unsafe { $Ty::new_unchecked(self.get().neg()) }
|
||||
}
|
||||
}
|
||||
|
||||
forward_ref_unop! { impl Neg, neg for $Ty,
|
||||
#[stable(feature = "signed_nonzero_neg", since = "CURRENT_RUSTC_VERSION")] }
|
||||
)+
|
||||
}
|
||||
}
|
||||
|
|
|
@ -336,3 +336,21 @@ fn test_nonzero_uint_rem() {
|
|||
let x: u32 = 42u32 % nz;
|
||||
assert_eq!(x, 2u32);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_signed_nonzero_neg() {
|
||||
assert_eq!((-NonZeroI8::new(1).unwrap()).get(), -1);
|
||||
assert_eq!((-NonZeroI8::new(-1).unwrap()).get(), 1);
|
||||
|
||||
assert_eq!((-NonZeroI16::new(1).unwrap()).get(), -1);
|
||||
assert_eq!((-NonZeroI16::new(-1).unwrap()).get(), 1);
|
||||
|
||||
assert_eq!((-NonZeroI32::new(1).unwrap()).get(), -1);
|
||||
assert_eq!((-NonZeroI32::new(-1).unwrap()).get(), 1);
|
||||
|
||||
assert_eq!((-NonZeroI64::new(1).unwrap()).get(), -1);
|
||||
assert_eq!((-NonZeroI64::new(-1).unwrap()).get(), 1);
|
||||
|
||||
assert_eq!((-NonZeroI128::new(1).unwrap()).get(), -1);
|
||||
assert_eq!((-NonZeroI128::new(-1).unwrap()).get(), 1);
|
||||
}
|
||||
|
|
|
@ -374,9 +374,9 @@ checksum = "99227334921fae1a979cf0bfdfcc6b3e5ce376ef57e16fb6fb3ea2ed6095f80c"
|
|||
|
||||
[[package]]
|
||||
name = "linux-raw-sys"
|
||||
version = "0.3.1"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d59d8c75012853d2e872fb56bc8a2e53718e2cafe1a4c823143141c6d90c322f"
|
||||
checksum = "3f508063cc7bb32987c71511216bd5a32be15bccb6a80b52df8b9d7f01fc3aa2"
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
// check-pass
|
||||
|
||||
#![deny(warnings)]
|
||||
|
||||
pub struct Struct;
|
||||
|
||||
impl Struct {
|
||||
#[allow(non_upper_case_globals)]
|
||||
pub const Const: () = ();
|
||||
}
|
||||
|
||||
fn main() {}
|
|
@ -0,0 +1,12 @@
|
|||
// run-fail
|
||||
// error-pattern:thread 'main' panicked at 'attempt to negate with overflow'
|
||||
// ignore-emscripten no processes
|
||||
// compile-flags: -C debug-assertions
|
||||
|
||||
#![allow(arithmetic_overflow)]
|
||||
|
||||
use std::num::NonZeroI8;
|
||||
|
||||
fn main() {
|
||||
let _x = -NonZeroI8::new(i8::MIN).unwrap();
|
||||
}
|
Loading…
Reference in New Issue