From 18df8d6e559174700e302369c2fe0d9c7c143e66 Mon Sep 17 00:00:00 2001 From: Kevin Reid Date: Mon, 30 Aug 2021 20:20:14 -0700 Subject: [PATCH 01/15] Expand documentation for `FpCategory`. I intend these changes to be helpful to readers who are not yet familiar with the quirks of floating-point numbers. Additionally, I felt it was misleading to describe `Nan` as being the result of division by zero, since most divisions by zero (except for 0/0) produce `Infinite` floats, so I moved that remark to the `Infinite` variant with adjustment. The first sentence of the `Nan` documentation is copied from `f32`; I followed the example of the `f64` documentation by referring to `f32` for general concepts, rather than duplicating the text. --- library/core/src/num/mod.rs | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/library/core/src/num/mod.rs b/library/core/src/num/mod.rs index 09b7418bec0d9..360ca9b700b7a 100644 --- a/library/core/src/num/mod.rs +++ b/library/core/src/num/mod.rs @@ -778,23 +778,41 @@ impl usize { #[derive(Copy, Clone, PartialEq, Eq, Debug)] #[stable(feature = "rust1", since = "1.0.0")] pub enum FpCategory { - /// "Not a Number", often obtained by dividing by zero. + /// NaN (not a number): this value results from calculations like `(-1.0).sqrt()`. + /// + /// See [the documentation for `f32`](f32) for more information on the unusual properties + /// of NaN. #[stable(feature = "rust1", since = "1.0.0")] Nan, - /// Positive or negative infinity. + /// Positive or negative infinity, which often results from dividing a nonzero number + /// by zero. #[stable(feature = "rust1", since = "1.0.0")] Infinite, /// Positive or negative zero. + /// + /// See [the documentation for `f32`](f32) for more information on the signedness of zeroes. #[stable(feature = "rust1", since = "1.0.0")] Zero, - /// De-normalized floating point representation (less precise than `Normal`). + /// “Subnormal” or “denormal” floating point representation (less precise, relative to + /// their magnitude, than [`Normal`]). + /// + /// Subnormal numbers are larger in magnitude than [`Zero`] but smaller in magnitude than all + /// [`Normal`] numbers. + /// + /// [`Normal`]: Self::Normal + /// [`Zero`]: Self::Zero #[stable(feature = "rust1", since = "1.0.0")] Subnormal, - /// A regular floating point number. + /// A regular floating point number, not any of the exceptional categories. + /// + /// The smallest positive normal numbers are [`f32::MIN_POSITIVE`] and [`f64::MIN_POSITIVE`], + /// and the largest positive normal numbers are [`f32::MAX`] and [`f64::MAX`]. (Unlike signed + /// integers, floating point numbers are symmetric in their range, so negating any of these + /// constants will produce their negative counterpart.) #[stable(feature = "rust1", since = "1.0.0")] Normal, } From 25b6f9b68b6ff4bdcce01feaa5259ff2786c4851 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= Date: Tue, 28 Sep 2021 00:00:00 +0000 Subject: [PATCH 02/15] print-type-sizes: skip field printing for primitives --- compiler/rustc_middle/src/ty/layout.rs | 7 +++++-- src/test/ui/print_type_sizes/uninhabited.rs | 2 +- src/test/ui/print_type_sizes/uninhabited.stdout | 1 + 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index cfbbec374a172..2c3c21e7a393b 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -1805,8 +1805,11 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { match layout.variants { Variants::Single { index } => { - debug!("print-type-size `{:#?}` variant {}", layout, adt_def.variants[index].ident); - if !adt_def.variants.is_empty() { + if !adt_def.variants.is_empty() && layout.fields != FieldsShape::Primitive { + debug!( + "print-type-size `{:#?}` variant {}", + layout, adt_def.variants[index].ident + ); let variant_def = &adt_def.variants[index]; let fields: Vec<_> = variant_def.fields.iter().map(|f| f.ident.name).collect(); record( diff --git a/src/test/ui/print_type_sizes/uninhabited.rs b/src/test/ui/print_type_sizes/uninhabited.rs index c234547bd14b1..06a62db4ebb0f 100644 --- a/src/test/ui/print_type_sizes/uninhabited.rs +++ b/src/test/ui/print_type_sizes/uninhabited.rs @@ -11,5 +11,5 @@ fn start(_: isize, _: *const *const u8) -> isize { let _x: Option = None; let _y: Result = Ok(42); - 0 + let _z: Result = loop {}; } diff --git a/src/test/ui/print_type_sizes/uninhabited.stdout b/src/test/ui/print_type_sizes/uninhabited.stdout index 2a8706f7ac551..5eb5384bce340 100644 --- a/src/test/ui/print_type_sizes/uninhabited.stdout +++ b/src/test/ui/print_type_sizes/uninhabited.stdout @@ -3,3 +3,4 @@ print-type-size variant `Ok`: 4 bytes print-type-size field `.0`: 4 bytes print-type-size type: `std::option::Option`: 0 bytes, alignment: 1 bytes print-type-size variant `None`: 0 bytes +print-type-size type: `std::result::Result`: 0 bytes, alignment: 1 bytes From fe11483afa90628106971993049b4fd2f0dae6fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20du=20Garreau?= Date: Thu, 29 Jul 2021 19:39:56 +0200 Subject: [PATCH 03/15] Add functions to add unsigned and signed integers --- library/core/src/lib.rs | 1 + library/core/src/num/mod.rs | 16 ++--- library/core/src/num/uint_macros.rs | 102 +++++++++++++++++++++++++++- library/std/src/io/cursor.rs | 7 +- library/std/src/lib.rs | 1 + 5 files changed, 112 insertions(+), 15 deletions(-) diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 4408b5a3d2088..2e419625d14f6 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -159,6 +159,7 @@ #![feature(trait_alias)] #![feature(transparent_unions)] #![feature(try_blocks)] +#![feature(uint_add_signed)] #![feature(unboxed_closures)] #![feature(unsized_fn_params)] // diff --git a/library/core/src/num/mod.rs b/library/core/src/num/mod.rs index 59b68cbe9c0ce..8966a9c11d2b4 100644 --- a/library/core/src/num/mod.rs +++ b/library/core/src/num/mod.rs @@ -245,7 +245,7 @@ const ASCII_CASE_MASK: u8 = 0b0010_0000; #[lang = "u8"] impl u8 { widening_impl! { u8, u16, 8 } - uint_impl! { u8, u8, 8, 255, 2, "0x82", "0xa", "0x12", "0x12", "0x48", "[0x12]", + uint_impl! { u8, u8, i8, 8, 255, 2, "0x82", "0xa", "0x12", "0x12", "0x48", "[0x12]", "[0x12]", "", "" } /// Checks if the value is within the ASCII range. @@ -779,21 +779,21 @@ impl u8 { #[lang = "u16"] impl u16 { widening_impl! { u16, u32, 16 } - uint_impl! { u16, u16, 16, 65535, 4, "0xa003", "0x3a", "0x1234", "0x3412", "0x2c48", + uint_impl! { u16, u16, i16, 16, 65535, 4, "0xa003", "0x3a", "0x1234", "0x3412", "0x2c48", "[0x34, 0x12]", "[0x12, 0x34]", "", "" } } #[lang = "u32"] impl u32 { widening_impl! { u32, u64, 32 } - uint_impl! { u32, u32, 32, 4294967295, 8, "0x10000b3", "0xb301", "0x12345678", + uint_impl! { u32, u32, i32, 32, 4294967295, 8, "0x10000b3", "0xb301", "0x12345678", "0x78563412", "0x1e6a2c48", "[0x78, 0x56, 0x34, 0x12]", "[0x12, 0x34, 0x56, 0x78]", "", "" } } #[lang = "u64"] impl u64 { widening_impl! { u64, u128, 64 } - uint_impl! { u64, u64, 64, 18446744073709551615, 12, "0xaa00000000006e1", "0x6e10aa", + uint_impl! { u64, u64, i64, 64, 18446744073709551615, 12, "0xaa00000000006e1", "0x6e10aa", "0x1234567890123456", "0x5634129078563412", "0x6a2c48091e6a2c48", "[0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]", "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]", @@ -802,7 +802,7 @@ impl u64 { #[lang = "u128"] impl u128 { - uint_impl! { u128, u128, 128, 340282366920938463463374607431768211455, 16, + uint_impl! { u128, u128, i128, 128, 340282366920938463463374607431768211455, 16, "0x13f40000000000000000000000004f76", "0x4f7613f4", "0x12345678901234567890123456789012", "0x12907856341290785634129078563412", "0x48091e6a2c48091e6a2c48091e6a2c48", "[0x12, 0x90, 0x78, 0x56, 0x34, 0x12, 0x90, 0x78, \ @@ -816,7 +816,7 @@ impl u128 { #[lang = "usize"] impl usize { widening_impl! { usize, u32, 16 } - uint_impl! { usize, u16, 16, 65535, 4, "0xa003", "0x3a", "0x1234", "0x3412", "0x2c48", + uint_impl! { usize, u16, isize, 16, 65535, 4, "0xa003", "0x3a", "0x1234", "0x3412", "0x2c48", "[0x34, 0x12]", "[0x12, 0x34]", usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!() } } @@ -824,7 +824,7 @@ impl usize { #[lang = "usize"] impl usize { widening_impl! { usize, u64, 32 } - uint_impl! { usize, u32, 32, 4294967295, 8, "0x10000b3", "0xb301", "0x12345678", + uint_impl! { usize, u32, isize, 32, 4294967295, 8, "0x10000b3", "0xb301", "0x12345678", "0x78563412", "0x1e6a2c48", "[0x78, 0x56, 0x34, 0x12]", "[0x12, 0x34, 0x56, 0x78]", usize_isize_to_xe_bytes_doc!(), usize_isize_from_xe_bytes_doc!() } } @@ -833,7 +833,7 @@ impl usize { #[lang = "usize"] impl usize { widening_impl! { usize, u128, 64 } - uint_impl! { usize, u64, 64, 18446744073709551615, 12, "0xaa00000000006e1", "0x6e10aa", + uint_impl! { usize, u64, isize, 64, 18446744073709551615, 12, "0xaa00000000006e1", "0x6e10aa", "0x1234567890123456", "0x5634129078563412", "0x6a2c48091e6a2c48", "[0x56, 0x34, 0x12, 0x90, 0x78, 0x56, 0x34, 0x12]", "[0x12, 0x34, 0x56, 0x78, 0x90, 0x12, 0x34, 0x56]", diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs index 8ce8266263091..67d72a171350b 100644 --- a/library/core/src/num/uint_macros.rs +++ b/library/core/src/num/uint_macros.rs @@ -1,5 +1,5 @@ macro_rules! uint_impl { - ($SelfT:ty, $ActualT:ident, $BITS:expr, $MaxV:expr, + ($SelfT:ty, $ActualT:ident, $SignedT:ident, $BITS:expr, $MaxV:expr, $rot:expr, $rot_op:expr, $rot_result:expr, $swap_op:expr, $swapped:expr, $reversed:expr, $le_bytes:expr, $be_bytes:expr, $to_xe_bytes_doc:expr, $from_xe_bytes_doc:expr) => { @@ -442,6 +442,29 @@ macro_rules! uint_impl { unsafe { intrinsics::unchecked_add(self, rhs) } } + /// Checked addition with a signed integer. Computes `self + rhs`, + /// returning `None` if overflow occurred. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// # #![feature(uint_add_signed)] + #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".checked_add_signed(2), Some(3));")] + #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".checked_add_signed(-2), None);")] + #[doc = concat!("assert_eq!((", stringify!($SelfT), "::MAX - 2).checked_add(3), None);")] + /// ``` + #[unstable(feature = "uint_add_signed", issue = "none")] + #[rustc_const_unstable(feature = "uint_add_signed", issue = "none")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn checked_add_signed(self, rhs: $SignedT) -> Option { + let (a, b) = self.overflowing_add_signed(rhs); + if unlikely!(b) {None} else {Some(a)} + } + /// Checked integer subtraction. Computes `self - rhs`, returning /// `None` if overflow occurred. /// @@ -995,6 +1018,32 @@ macro_rules! uint_impl { intrinsics::saturating_add(self, rhs) } + /// Saturating addition with a signed integer. Computes `self + rhs`, + /// saturating at the numeric bounds instead of overflowing. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// # #![feature(uint_add_signed)] + #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".saturating_add_signed(2), 3);")] + #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".saturating_add_signed(-2), 0);")] + #[doc = concat!("assert_eq!((", stringify!($SelfT), "::MAX - 2).saturating_add_signed(4), ", stringify!($SelfT), "::MAX);")] + /// ``` + #[unstable(feature = "uint_add_signed", issue = "none")] + #[rustc_const_unstable(feature = "uint_add_signed", issue = "none")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn saturating_add_signed(self, rhs: $SignedT) -> Self { + if rhs >= 0 { + self.saturating_add(rhs as Self) + } else { + self.saturating_sub(rhs.unsigned_abs()) + } + } + /// Saturating integer subtraction. Computes `self - rhs`, saturating /// at the numeric bounds instead of overflowing. /// @@ -1111,6 +1160,28 @@ macro_rules! uint_impl { intrinsics::wrapping_add(self, rhs) } + /// Wrapping (modular) addition with a signed integer. Computes + /// `self + rhs`, wrapping around at the boundary of the type. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// # #![feature(uint_add_signed)] + #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".wrapping_add_signed(2), 3);")] + #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".wrapping_add_signed(-2), ", stringify!($SelfT), "::MAX);")] + #[doc = concat!("assert_eq!((", stringify!($SelfT), "::MAX - 2).wrapping_add_signed(4), 1);")] + /// ``` + #[unstable(feature = "uint_add_signed", issue = "none")] + #[rustc_const_unstable(feature = "uint_add_signed", issue = "none")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn wrapping_add_signed(self, rhs: $SignedT) -> Self { + self.wrapping_add(rhs as Self) + } + /// Wrapping (modular) subtraction. Computes `self - rhs`, /// wrapping around at the boundary of the type. /// @@ -1435,6 +1506,35 @@ macro_rules! uint_impl { (c, b | d) } + /// Calculates `self` + `rhs` with a signed `rhs` + /// + /// Returns a tuple of the addition along with a boolean indicating + /// whether an arithmetic overflow would occur. If an overflow would + /// have occurred then the wrapped value is returned. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// # #![feature(uint_add_signed)] + #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".overflowing_add_signed(2), (3, false));")] + #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".overflowing_add_signed(-2), (", stringify!($SelfT), "::MAX, true));")] + #[doc = concat!("assert_eq!((", stringify!($SelfT), "::MAX - 2).overflowing_add_signed(4), (1, true));")] + /// ``` + #[unstable(feature = "uint_add_signed", issue = "none")] + #[rustc_const_unstable(feature = "uint_add_signed", issue = "none")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn overflowing_add_signed(self, rhs: $SignedT) -> (Self, bool) { + if rhs >= 0 { + self.overflowing_add(rhs as Self) + } else { + self.overflowing_sub(rhs.unsigned_abs()) + } + } + /// Calculates `self` - `rhs` /// /// Returns a tuple of the subtraction along with a boolean indicating diff --git a/library/std/src/io/cursor.rs b/library/std/src/io/cursor.rs index 25cc5e67ad14e..980b2531192e8 100644 --- a/library/std/src/io/cursor.rs +++ b/library/std/src/io/cursor.rs @@ -292,12 +292,7 @@ where SeekFrom::End(n) => (self.inner.as_ref().len() as u64, n), SeekFrom::Current(n) => (self.pos, n), }; - let new_pos = if offset >= 0 { - base_pos.checked_add(offset as u64) - } else { - base_pos.checked_sub((offset.wrapping_neg()) as u64) - }; - match new_pos { + match base_pos.checked_add_signed(offset) { Some(n) => { self.pos = n; Ok(self.pos) diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index b33a3c5d22fe1..e9a1aa41a63db 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -333,6 +333,7 @@ #![feature(try_blocks)] #![feature(try_reserve)] #![feature(try_reserve_kind)] +#![feature(uint_add_signed)] #![feature(unboxed_closures)] #![feature(unwrap_infallible)] #![feature(vec_into_raw_parts)] From ab9f8a0b593a832f98188cd755bd467eeb9416d4 Mon Sep 17 00:00:00 2001 From: Alphyr <47725341+a1phyr@users.noreply.github.com> Date: Fri, 30 Jul 2021 12:11:18 +0200 Subject: [PATCH 04/15] Apply suggestion for `overflowing_add_signed` Co-authored-by: kennytm --- library/core/src/num/uint_macros.rs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs index 67d72a171350b..2c4097a30a1e1 100644 --- a/library/core/src/num/uint_macros.rs +++ b/library/core/src/num/uint_macros.rs @@ -1528,11 +1528,8 @@ macro_rules! uint_impl { without modifying the original"] #[inline] pub const fn overflowing_add_signed(self, rhs: $SignedT) -> (Self, bool) { - if rhs >= 0 { - self.overflowing_add(rhs as Self) - } else { - self.overflowing_sub(rhs.unsigned_abs()) - } + let (res, overflowed) = self.overflowing_add(rhs as Self); + (res, overflowed ^ (rhs < 0)) } /// Calculates `self` - `rhs` From b5dd5227ee7785174f006a5281622c52533c6075 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20du=20Garreau?= Date: Sat, 7 Aug 2021 11:26:34 +0200 Subject: [PATCH 05/15] Fix doc test --- library/core/src/num/uint_macros.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs index 2c4097a30a1e1..e6c675edabcc3 100644 --- a/library/core/src/num/uint_macros.rs +++ b/library/core/src/num/uint_macros.rs @@ -453,7 +453,7 @@ macro_rules! uint_impl { /// # #![feature(uint_add_signed)] #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".checked_add_signed(2), Some(3));")] #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".checked_add_signed(-2), None);")] - #[doc = concat!("assert_eq!((", stringify!($SelfT), "::MAX - 2).checked_add(3), None);")] + #[doc = concat!("assert_eq!((", stringify!($SelfT), "::MAX - 2).checked_add_signed(3), None);")] /// ``` #[unstable(feature = "uint_add_signed", issue = "none")] #[rustc_const_unstable(feature = "uint_add_signed", issue = "none")] From 9faf6213558c0f0158eff5f2a911dbd6ab804605 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20du=20Garreau?= Date: Sat, 7 Aug 2021 12:11:59 +0200 Subject: [PATCH 06/15] Add methods to add/sub `uX` to/from `iX` --- library/core/src/lib.rs | 2 +- library/core/src/num/int_macros.rs | 190 ++++++++++++++++++++++++++++ library/core/src/num/uint_macros.rs | 24 ++-- library/std/src/lib.rs | 2 +- 4 files changed, 204 insertions(+), 14 deletions(-) diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 2e419625d14f6..f41eeae9cc1fa 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -142,6 +142,7 @@ #![feature(link_llvm_intrinsics)] #![feature(llvm_asm)] #![feature(min_specialization)] +#![feature(mixed_integer_ops)] #![cfg_attr(not(bootstrap), feature(must_not_suspend))] #![feature(negative_impls)] #![feature(never_type)] @@ -159,7 +160,6 @@ #![feature(trait_alias)] #![feature(transparent_unions)] #![feature(try_blocks)] -#![feature(uint_add_signed)] #![feature(unboxed_closures)] #![feature(unsized_fn_params)] // diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs index daef5c98967cc..5f299687780ef 100644 --- a/library/core/src/num/int_macros.rs +++ b/library/core/src/num/int_macros.rs @@ -433,6 +433,28 @@ macro_rules! int_impl { unsafe { intrinsics::unchecked_add(self, rhs) } } + /// Checked addition with an unsigned integer. Computes `self + rhs`, + /// returning `None` if overflow occurred. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// # #![feature(mixed_integer_ops)] + #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".checked_add_unsigned(2), Some(3));")] + #[doc = concat!("assert_eq!((", stringify!($SelfT), "::MAX - 2).checked_add_unsigned(3), None);")] + /// ``` + #[unstable(feature = "mixed_integer_ops", issue = "87840")] + #[rustc_const_unstable(feature = "mixed_integer_ops", issue = "87840")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn checked_add_unsigned(self, rhs: $UnsignedT) -> Option { + let (a, b) = self.overflowing_add_unsigned(rhs); + if unlikely!(b) {None} else {Some(a)} + } + /// Checked integer subtraction. Computes `self - rhs`, returning `None` if /// overflow occurred. /// @@ -479,6 +501,28 @@ macro_rules! int_impl { unsafe { intrinsics::unchecked_sub(self, rhs) } } + /// Checked addition with an unsigned integer. Computes `self + rhs`, + /// returning `None` if overflow occurred. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// # #![feature(mixed_integer_ops)] + #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".checked_sub_unsigned(2), Some(-1));")] + #[doc = concat!("assert_eq!((", stringify!($SelfT), "::MIN + 2).checked_sub_unsigned(3), None);")] + /// ``` + #[unstable(feature = "mixed_integer_ops", issue = "87840")] + #[rustc_const_unstable(feature = "mixed_integer_ops", issue = "87840")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn checked_sub_unsigned(self, rhs: $UnsignedT) -> Option { + let (a, b) = self.overflowing_sub_unsigned(rhs); + if unlikely!(b) {None} else {Some(a)} + } + /// Checked integer multiplication. Computes `self * rhs`, returning `None` if /// overflow occurred. /// @@ -822,6 +866,31 @@ macro_rules! int_impl { intrinsics::saturating_add(self, rhs) } + /// Saturating addition with an unsigned integer. Computes `self + rhs`, + /// saturating at the numeric bounds instead of overflowing. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// # #![feature(mixed_integer_ops)] + #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".saturating_add_unsigned(2), 3);")] + #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.saturating_add_unsigned(100), ", stringify!($SelfT), "::MAX);")] + /// ``` + #[unstable(feature = "mixed_integer_ops", issue = "87840")] + #[rustc_const_unstable(feature = "mixed_integer_ops", issue = "87840")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn saturating_add_unsigned(self, rhs: $UnsignedT) -> Self { + // Overflow can only happen at the upper bound + match self.checked_add_unsigned(rhs) { + Some(x) => x, + None => Self::MAX, + } + } + /// Saturating integer subtraction. Computes `self - rhs`, saturating at the /// numeric bounds instead of overflowing. /// @@ -843,6 +912,31 @@ macro_rules! int_impl { intrinsics::saturating_sub(self, rhs) } + /// Saturating substraction with an unsigned integer. Computes `self - rhs`, + /// saturating at the numeric bounds instead of overflowing. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// # #![feature(mixed_integer_ops)] + #[doc = concat!("assert_eq!(100", stringify!($SelfT), ".saturating_sub_unsigned(127), -27);")] + #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN.saturating_sub_unsigned(100), ", stringify!($SelfT), "::MIN);")] + /// ``` + #[unstable(feature = "mixed_integer_ops", issue = "87840")] + #[rustc_const_unstable(feature = "mixed_integer_ops", issue = "87840")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn saturating_sub_unsigned(self, rhs: $UnsignedT) -> Self { + // Overflow can only happen at the lower bound + match self.checked_sub_unsigned(rhs) { + Some(x) => x, + None => Self::MIN, + } + } + /// Saturating integer negation. Computes `-self`, returning `MAX` if `self == MIN` /// instead of overflowing. /// @@ -998,6 +1092,27 @@ macro_rules! int_impl { intrinsics::wrapping_add(self, rhs) } + /// Wrapping (modular) addition with an unsigned integer. Computes + /// `self + rhs`, wrapping around at the boundary of the type. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// # #![feature(mixed_integer_ops)] + #[doc = concat!("assert_eq!(100", stringify!($SelfT), ".wrapping_add_unsigned(27), 127);")] + #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.wrapping_add_unsigned(2), ", stringify!($SelfT), "::MIN + 1);")] + /// ``` + #[unstable(feature = "mixed_integer_ops", issue = "87840")] + #[rustc_const_unstable(feature = "mixed_integer_ops", issue = "87840")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline(always)] + pub const fn wrapping_add_unsigned(self, rhs: $UnsignedT) -> Self { + self.wrapping_add(rhs as Self) + } + /// Wrapping (modular) subtraction. Computes `self - rhs`, wrapping around at the /// boundary of the type. /// @@ -1018,6 +1133,27 @@ macro_rules! int_impl { intrinsics::wrapping_sub(self, rhs) } + /// Wrapping (modular) substraction with an unsigned integer. Computes + /// `self - rhs`, wrapping around at the boundary of the type. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// # #![feature(mixed_integer_ops)] + #[doc = concat!("assert_eq!(0", stringify!($SelfT), ".wrapping_sub_unsigned(127), -127);")] + #[doc = concat!("assert_eq!((-2", stringify!($SelfT), ").wrapping_sub_unsigned(", stringify!($UnsignedT), "::MAX), -1);")] + /// ``` + #[unstable(feature = "mixed_integer_ops", issue = "87840")] + #[rustc_const_unstable(feature = "mixed_integer_ops", issue = "87840")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline(always)] + pub const fn wrapping_sub_unsigned(self, rhs: $UnsignedT) -> Self { + self.wrapping_sub(rhs as Self) + } + /// Wrapping (modular) multiplication. Computes `self * rhs`, wrapping around at /// the boundary of the type. /// @@ -1368,6 +1504,33 @@ macro_rules! int_impl { (sum as $SelfT, carry) } + /// Calculates `self` + `rhs` with an unsigned `rhs` + /// + /// Returns a tuple of the addition along with a boolean indicating + /// whether an arithmetic overflow would occur. If an overflow would + /// have occurred then the wrapped value is returned. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// # #![feature(mixed_integer_ops)] + #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".overflowing_add_unsigned(2), (3, false));")] + #[doc = concat!("assert_eq!((", stringify!($SelfT), "::MIN).overflowing_add_unsigned(", stringify!($UnsignedT), "::MAX), (", stringify!($SelfT), "::MAX, false));")] + #[doc = concat!("assert_eq!((", stringify!($SelfT), "::MAX - 2).overflowing_add_unsigned(3), (", stringify!($SelfT), "::MIN, true));")] + /// ``` + #[unstable(feature = "mixed_integer_ops", issue = "87840")] + #[rustc_const_unstable(feature = "mixed_integer_ops", issue = "87840")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn overflowing_add_unsigned(self, rhs: $UnsignedT) -> (Self, bool) { + let rhs = rhs as Self; + let (res, overflowed) = self.overflowing_add(rhs); + (res, overflowed ^ (rhs < 0)) + } + /// Calculates `self` - `rhs` /// /// Returns a tuple of the subtraction along with a boolean indicating whether an arithmetic overflow @@ -1419,6 +1582,33 @@ macro_rules! int_impl { (sum as $SelfT, borrow) } + /// Calculates `self` - `rhs` with an unsigned `rhs` + /// + /// Returns a tuple of the substraction along with a boolean indicating + /// whether an arithmetic overflow would occur. If an overflow would + /// have occurred then the wrapped value is returned. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// # #![feature(mixed_integer_ops)] + #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".overflowing_sub_unsigned(2), (-1, false));")] + #[doc = concat!("assert_eq!((", stringify!($SelfT), "::MAX).overflowing_sub_unsigned(", stringify!($UnsignedT), "::MAX), (", stringify!($SelfT), "::MIN, false));")] + #[doc = concat!("assert_eq!((", stringify!($SelfT), "::MIN + 2).overflowing_sub_unsigned(3), (", stringify!($SelfT), "::MAX, true));")] + /// ``` + #[unstable(feature = "mixed_integer_ops", issue = "87840")] + #[rustc_const_unstable(feature = "mixed_integer_ops", issue = "87840")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn overflowing_sub_unsigned(self, rhs: $UnsignedT) -> (Self, bool) { + let rhs = rhs as Self; + let (res, overflowed) = self.overflowing_sub(rhs); + (res, overflowed ^ (rhs < 0)) + } + /// Calculates the multiplication of `self` and `rhs`. /// /// Returns a tuple of the multiplication along with a boolean indicating whether an arithmetic overflow diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs index e6c675edabcc3..5a65f77a87993 100644 --- a/library/core/src/num/uint_macros.rs +++ b/library/core/src/num/uint_macros.rs @@ -450,13 +450,13 @@ macro_rules! uint_impl { /// Basic usage: /// /// ``` - /// # #![feature(uint_add_signed)] + /// # #![feature(mixed_integer_ops)] #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".checked_add_signed(2), Some(3));")] #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".checked_add_signed(-2), None);")] #[doc = concat!("assert_eq!((", stringify!($SelfT), "::MAX - 2).checked_add_signed(3), None);")] /// ``` - #[unstable(feature = "uint_add_signed", issue = "none")] - #[rustc_const_unstable(feature = "uint_add_signed", issue = "none")] + #[unstable(feature = "mixed_integer_ops", issue = "87840")] + #[rustc_const_unstable(feature = "mixed_integer_ops", issue = "87840")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -1026,13 +1026,13 @@ macro_rules! uint_impl { /// Basic usage: /// /// ``` - /// # #![feature(uint_add_signed)] + /// # #![feature(mixed_integer_ops)] #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".saturating_add_signed(2), 3);")] #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".saturating_add_signed(-2), 0);")] #[doc = concat!("assert_eq!((", stringify!($SelfT), "::MAX - 2).saturating_add_signed(4), ", stringify!($SelfT), "::MAX);")] /// ``` - #[unstable(feature = "uint_add_signed", issue = "none")] - #[rustc_const_unstable(feature = "uint_add_signed", issue = "none")] + #[unstable(feature = "mixed_integer_ops", issue = "87840")] + #[rustc_const_unstable(feature = "mixed_integer_ops", issue = "87840")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -1168,13 +1168,13 @@ macro_rules! uint_impl { /// Basic usage: /// /// ``` - /// # #![feature(uint_add_signed)] + /// # #![feature(mixed_integer_ops)] #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".wrapping_add_signed(2), 3);")] #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".wrapping_add_signed(-2), ", stringify!($SelfT), "::MAX);")] #[doc = concat!("assert_eq!((", stringify!($SelfT), "::MAX - 2).wrapping_add_signed(4), 1);")] /// ``` - #[unstable(feature = "uint_add_signed", issue = "none")] - #[rustc_const_unstable(feature = "uint_add_signed", issue = "none")] + #[unstable(feature = "mixed_integer_ops", issue = "87840")] + #[rustc_const_unstable(feature = "mixed_integer_ops", issue = "87840")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] @@ -1517,13 +1517,13 @@ macro_rules! uint_impl { /// Basic usage: /// /// ``` - /// # #![feature(uint_add_signed)] + /// # #![feature(mixed_integer_ops)] #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".overflowing_add_signed(2), (3, false));")] #[doc = concat!("assert_eq!(1", stringify!($SelfT), ".overflowing_add_signed(-2), (", stringify!($SelfT), "::MAX, true));")] #[doc = concat!("assert_eq!((", stringify!($SelfT), "::MAX - 2).overflowing_add_signed(4), (1, true));")] /// ``` - #[unstable(feature = "uint_add_signed", issue = "none")] - #[rustc_const_unstable(feature = "uint_add_signed", issue = "none")] + #[unstable(feature = "mixed_integer_ops", issue = "87840")] + #[rustc_const_unstable(feature = "mixed_integer_ops", issue = "87840")] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index e9a1aa41a63db..1781a3cb7c402 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -297,6 +297,7 @@ #![feature(maybe_uninit_slice)] #![feature(maybe_uninit_uninit_array)] #![feature(min_specialization)] +#![feature(mixed_integer_ops)] #![cfg_attr(not(bootstrap), feature(must_not_suspend))] #![feature(needs_panic_runtime)] #![feature(negative_impls)] @@ -333,7 +334,6 @@ #![feature(try_blocks)] #![feature(try_reserve)] #![feature(try_reserve_kind)] -#![feature(uint_add_signed)] #![feature(unboxed_closures)] #![feature(unwrap_infallible)] #![feature(vec_into_raw_parts)] From 70e55a8938bb84542f73a127edd5c91f2c8bd0aa Mon Sep 17 00:00:00 2001 From: Alphyr <47725341+a1phyr@users.noreply.github.com> Date: Sun, 3 Oct 2021 22:44:07 +0200 Subject: [PATCH 07/15] Apply suggestions Co-authored-by: kennytm --- library/core/src/num/int_macros.rs | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs index 5f299687780ef..540b7d36625af 100644 --- a/library/core/src/num/int_macros.rs +++ b/library/core/src/num/int_macros.rs @@ -501,7 +501,7 @@ macro_rules! int_impl { unsafe { intrinsics::unchecked_sub(self, rhs) } } - /// Checked addition with an unsigned integer. Computes `self + rhs`, + /// Checked subtraction with an unsigned integer. Computes `self - rhs`, /// returning `None` if overflow occurred. /// /// # Examples @@ -885,10 +885,7 @@ macro_rules! int_impl { #[inline] pub const fn saturating_add_unsigned(self, rhs: $UnsignedT) -> Self { // Overflow can only happen at the upper bound - match self.checked_add_unsigned(rhs) { - Some(x) => x, - None => Self::MAX, - } + self.checked_add_unsigned(rhs).unwrap_or(Self::MAX) } /// Saturating integer subtraction. Computes `self - rhs`, saturating at the @@ -912,7 +909,7 @@ macro_rules! int_impl { intrinsics::saturating_sub(self, rhs) } - /// Saturating substraction with an unsigned integer. Computes `self - rhs`, + /// Saturating subtraction with an unsigned integer. Computes `self - rhs`, /// saturating at the numeric bounds instead of overflowing. /// /// # Examples @@ -931,10 +928,7 @@ macro_rules! int_impl { #[inline] pub const fn saturating_sub_unsigned(self, rhs: $UnsignedT) -> Self { // Overflow can only happen at the lower bound - match self.checked_sub_unsigned(rhs) { - Some(x) => x, - None => Self::MIN, - } + self.checked_sub_unsigned(rhs).unwrap_or(Self::MIN) } /// Saturating integer negation. Computes `-self`, returning `MAX` if `self == MIN` @@ -1133,7 +1127,7 @@ macro_rules! int_impl { intrinsics::wrapping_sub(self, rhs) } - /// Wrapping (modular) substraction with an unsigned integer. Computes + /// Wrapping (modular) subtraction with an unsigned integer. Computes /// `self - rhs`, wrapping around at the boundary of the type. /// /// # Examples @@ -1584,7 +1578,7 @@ macro_rules! int_impl { /// Calculates `self` - `rhs` with an unsigned `rhs` /// - /// Returns a tuple of the substraction along with a boolean indicating + /// Returns a tuple of the subtraction along with a boolean indicating /// whether an arithmetic overflow would occur. If an overflow would /// have occurred then the wrapped value is returned. /// From 4846fd92c0cc82545c5fd33c9ab3007f03f0f9f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20du=20Garreau?= Date: Sun, 3 Oct 2021 22:56:34 +0200 Subject: [PATCH 08/15] Revert suggested use of `unwrap_or` --- library/core/src/num/int_macros.rs | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs index 540b7d36625af..5bdb6ed91761f 100644 --- a/library/core/src/num/int_macros.rs +++ b/library/core/src/num/int_macros.rs @@ -885,7 +885,11 @@ macro_rules! int_impl { #[inline] pub const fn saturating_add_unsigned(self, rhs: $UnsignedT) -> Self { // Overflow can only happen at the upper bound - self.checked_add_unsigned(rhs).unwrap_or(Self::MAX) + // We cannot use `unwrap_or` here because it is not `const` + match self.checked_add_unsigned(rhs) { + Some(x) => x, + None => Self::MAX, + } } /// Saturating integer subtraction. Computes `self - rhs`, saturating at the @@ -928,7 +932,11 @@ macro_rules! int_impl { #[inline] pub const fn saturating_sub_unsigned(self, rhs: $UnsignedT) -> Self { // Overflow can only happen at the lower bound - self.checked_sub_unsigned(rhs).unwrap_or(Self::MIN) + // We cannot use `unwrap_or` here because it is not `const` + match self.checked_sub_unsigned(rhs) { + Some(x) => x, + None => Self::MIN, + } } /// Saturating integer negation. Computes `-self`, returning `MAX` if `self == MIN` From 47edde1086412b36e9efd6098b191ec15a2a760a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20du=20Garreau?= Date: Mon, 4 Oct 2021 18:52:17 +0200 Subject: [PATCH 09/15] Optimize `saturating_add_signed` --- library/core/src/num/uint_macros.rs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs index 5a65f77a87993..96375b82582ed 100644 --- a/library/core/src/num/uint_macros.rs +++ b/library/core/src/num/uint_macros.rs @@ -1037,10 +1037,13 @@ macro_rules! uint_impl { without modifying the original"] #[inline] pub const fn saturating_add_signed(self, rhs: $SignedT) -> Self { - if rhs >= 0 { - self.saturating_add(rhs as Self) + let (res, overflow) = self.overflowing_add(rhs as Self); + if overflow == (rhs < 0) { + res + } else if overflow { + Self::MAX } else { - self.saturating_sub(rhs.unsigned_abs()) + 0 } } From 388bcc1cb086c567f17a4933bfb1d3f14eb19fb7 Mon Sep 17 00:00:00 2001 From: Fabian Wolff Date: Mon, 4 Oct 2021 21:15:02 +0200 Subject: [PATCH 10/15] Fix suggestion to borrow when casting from pointer to reference --- compiler/rustc_typeck/src/check/cast.rs | 44 +++++++++++++++---- src/test/ui/cast/issue-89497.fixed | 10 +++++ src/test/ui/cast/issue-89497.rs | 10 +++++ src/test/ui/cast/issue-89497.stderr | 15 +++++++ src/test/ui/error-codes/E0605.stderr | 5 ++- src/test/ui/issues/issue-2995.stderr | 5 ++- .../ui/mismatched_types/cast-rfc0401.stderr | 5 ++- 7 files changed, 80 insertions(+), 14 deletions(-) create mode 100644 src/test/ui/cast/issue-89497.fixed create mode 100644 src/test/ui/cast/issue-89497.rs create mode 100644 src/test/ui/cast/issue-89497.stderr diff --git a/compiler/rustc_typeck/src/check/cast.rs b/compiler/rustc_typeck/src/check/cast.rs index 4ea7a8694c075..fe0de61ab89e2 100644 --- a/compiler/rustc_typeck/src/check/cast.rs +++ b/compiler/rustc_typeck/src/check/cast.rs @@ -351,7 +351,7 @@ impl<'a, 'tcx> CastCheck<'tcx> { ); let mut sugg = None; let mut sugg_mutref = false; - if let ty::Ref(reg, _, mutbl) = *self.cast_ty.kind() { + if let ty::Ref(reg, cast_ty, mutbl) = *self.cast_ty.kind() { if let ty::RawPtr(TypeAndMut { ty: expr_ty, .. }) = *self.expr_ty.kind() { if fcx .try_coerce( @@ -366,7 +366,7 @@ impl<'a, 'tcx> CastCheck<'tcx> { ) .is_ok() { - sugg = Some(format!("&{}*", mutbl.prefix_str())); + sugg = Some((format!("&{}*", mutbl.prefix_str()), cast_ty == expr_ty)); } } else if let ty::Ref(expr_reg, expr_ty, expr_mutbl) = *self.expr_ty.kind() { if expr_mutbl == Mutability::Not @@ -400,7 +400,7 @@ impl<'a, 'tcx> CastCheck<'tcx> { ) .is_ok() { - sugg = Some(format!("&{}", mutbl.prefix_str())); + sugg = Some((format!("&{}", mutbl.prefix_str()), false)); } } else if let ty::RawPtr(TypeAndMut { mutbl, .. }) = *self.cast_ty.kind() { if fcx @@ -416,19 +416,47 @@ impl<'a, 'tcx> CastCheck<'tcx> { ) .is_ok() { - sugg = Some(format!("&{}", mutbl.prefix_str())); + sugg = Some((format!("&{}", mutbl.prefix_str()), false)); } } if sugg_mutref { err.span_label(self.span, "invalid cast"); err.span_note(self.expr.span, "this reference is immutable"); err.span_note(self.cast_span, "trying to cast to a mutable reference type"); - } else if let Some(sugg) = sugg { + } else if let Some((sugg, remove_cast)) = sugg { err.span_label(self.span, "invalid cast"); - err.span_suggestion_verbose( - self.expr.span.shrink_to_lo(), + + let has_parens = fcx + .tcx + .sess + .source_map() + .span_to_snippet(self.expr.span) + .map_or(false, |snip| snip.starts_with("(")); + + // Very crude check to see whether the expression must be wrapped + // in parentheses for the suggestion to work (issue #89497). + // Can/should be extended in the future. + let needs_parens = !has_parens + && match self.expr.kind { + hir::ExprKind::Cast(..) => true, + _ => false, + }; + + let mut suggestion = vec![(self.expr.span.shrink_to_lo(), sugg)]; + if needs_parens { + suggestion[0].1 += "("; + suggestion.push((self.expr.span.shrink_to_hi(), ")".to_string())); + } + if remove_cast { + suggestion.push(( + self.expr.span.shrink_to_hi().to(self.cast_span), + String::new(), + )); + } + + err.multipart_suggestion_verbose( "consider borrowing the value", - sugg, + suggestion, Applicability::MachineApplicable, ); } else if !matches!( diff --git a/src/test/ui/cast/issue-89497.fixed b/src/test/ui/cast/issue-89497.fixed new file mode 100644 index 0000000000000..04c10a5f79ed4 --- /dev/null +++ b/src/test/ui/cast/issue-89497.fixed @@ -0,0 +1,10 @@ +// Regression test for issue #89497. + +// run-rustfix + +fn main() { + let pointer: usize = &1_i32 as *const i32 as usize; + let _reference: &'static i32 = unsafe { &*(pointer as *const i32) }; + //~^ ERROR: non-primitive cast + //~| HELP: consider borrowing the value +} diff --git a/src/test/ui/cast/issue-89497.rs b/src/test/ui/cast/issue-89497.rs new file mode 100644 index 0000000000000..76301b704c81c --- /dev/null +++ b/src/test/ui/cast/issue-89497.rs @@ -0,0 +1,10 @@ +// Regression test for issue #89497. + +// run-rustfix + +fn main() { + let pointer: usize = &1_i32 as *const i32 as usize; + let _reference: &'static i32 = unsafe { pointer as *const i32 as &'static i32 }; + //~^ ERROR: non-primitive cast + //~| HELP: consider borrowing the value +} diff --git a/src/test/ui/cast/issue-89497.stderr b/src/test/ui/cast/issue-89497.stderr new file mode 100644 index 0000000000000..3726f8a41015e --- /dev/null +++ b/src/test/ui/cast/issue-89497.stderr @@ -0,0 +1,15 @@ +error[E0605]: non-primitive cast: `*const i32` as `&'static i32` + --> $DIR/issue-89497.rs:7:45 + | +LL | let _reference: &'static i32 = unsafe { pointer as *const i32 as &'static i32 }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid cast + | +help: consider borrowing the value + | +LL - let _reference: &'static i32 = unsafe { pointer as *const i32 as &'static i32 }; +LL + let _reference: &'static i32 = unsafe { &*(pointer as *const i32) }; + | + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0605`. diff --git a/src/test/ui/error-codes/E0605.stderr b/src/test/ui/error-codes/E0605.stderr index e5647ee6d0968..d082b6c10cc2a 100644 --- a/src/test/ui/error-codes/E0605.stderr +++ b/src/test/ui/error-codes/E0605.stderr @@ -12,8 +12,9 @@ LL | v as &u8; | help: consider borrowing the value | -LL | &*v as &u8; - | ++ +LL - v as &u8; +LL + &*v; + | error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-2995.stderr b/src/test/ui/issues/issue-2995.stderr index 455d32e233ab9..7616f987d7312 100644 --- a/src/test/ui/issues/issue-2995.stderr +++ b/src/test/ui/issues/issue-2995.stderr @@ -6,8 +6,9 @@ LL | let _q: &isize = p as &isize; | help: consider borrowing the value | -LL | let _q: &isize = &*p as &isize; - | ++ +LL - let _q: &isize = p as &isize; +LL + let _q: &isize = &*p; + | error: aborting due to previous error diff --git a/src/test/ui/mismatched_types/cast-rfc0401.stderr b/src/test/ui/mismatched_types/cast-rfc0401.stderr index a47eb87cff06c..7f91d5ed42ce4 100644 --- a/src/test/ui/mismatched_types/cast-rfc0401.stderr +++ b/src/test/ui/mismatched_types/cast-rfc0401.stderr @@ -28,8 +28,9 @@ LL | let _ = v as &u8; | help: consider borrowing the value | -LL | let _ = &*v as &u8; - | ++ +LL - let _ = v as &u8; +LL + let _ = &*v; + | error[E0605]: non-primitive cast: `*const u8` as `E` --> $DIR/cast-rfc0401.rs:30:13 From c79447e708541abda1e5075385c9ef8810ebc715 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Mon, 4 Oct 2021 22:11:53 +0100 Subject: [PATCH 11/15] library std, libc dependency update to solve #87528 build. --- Cargo.lock | 4 ++-- library/std/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a4e1ab6c1e4a8..b596e09828afa 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1892,9 +1892,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "libc" -version = "0.2.99" +version = "0.2.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7f823d141fe0a24df1e23b4af4e3c7ba9e5966ec514ea068c93024aa7deb765" +checksum = "dd8f7255a17a627354f321ef0055d63b898c6fb27eff628af4d1b66b7331edf6" dependencies = [ "rustc-std-workspace-core", ] diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml index 2b77dc54ab35c..6bc445c6f2b07 100644 --- a/library/std/Cargo.toml +++ b/library/std/Cargo.toml @@ -15,7 +15,7 @@ cfg-if = { version = "0.1.8", features = ['rustc-dep-of-std'] } panic_unwind = { path = "../panic_unwind", optional = true } panic_abort = { path = "../panic_abort" } core = { path = "../core" } -libc = { version = "0.2.99", default-features = false, features = ['rustc-dep-of-std'] } +libc = { version = "0.2.103", default-features = false, features = ['rustc-dep-of-std'] } compiler_builtins = { version = "0.1.44" } profiler_builtins = { path = "../profiler_builtins", optional = true } unwind = { path = "../unwind" } From b2e4e59fbe201ff23fd2911f2650827ad46902b9 Mon Sep 17 00:00:00 2001 From: DeveloperC286 Date: Fri, 17 Sep 2021 18:25:21 +0100 Subject: [PATCH 12/15] refactor: VecDeques Drain fields to private --- .../alloc/src/collections/vec_deque/drain.rs | 19 +++++++++++---- .../alloc/src/collections/vec_deque/mod.rs | 24 +++++++++---------- 2 files changed, 26 insertions(+), 17 deletions(-) diff --git a/library/alloc/src/collections/vec_deque/drain.rs b/library/alloc/src/collections/vec_deque/drain.rs index dfa0227dea3b8..05f94da6de70d 100644 --- a/library/alloc/src/collections/vec_deque/drain.rs +++ b/library/alloc/src/collections/vec_deque/drain.rs @@ -18,10 +18,21 @@ pub struct Drain< T: 'a, #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, > { - pub(crate) after_tail: usize, - pub(crate) after_head: usize, - pub(crate) iter: Iter<'a, T>, - pub(crate) deque: NonNull>, + after_tail: usize, + after_head: usize, + iter: Iter<'a, T>, + deque: NonNull>, +} + +impl<'a, T, A: Allocator> Drain<'a, T, A> { + pub(super) unsafe fn new( + after_tail: usize, + after_head: usize, + iter: Iter<'a, T>, + deque: NonNull>, + ) -> Self { + Drain { after_tail, after_head, iter, deque } + } } #[stable(feature = "collection_debug", since = "1.17.0")] diff --git a/library/alloc/src/collections/vec_deque/mod.rs b/library/alloc/src/collections/vec_deque/mod.rs index f4de2b2ebe5dc..ea3136cae42b5 100644 --- a/library/alloc/src/collections/vec_deque/mod.rs +++ b/library/alloc/src/collections/vec_deque/mod.rs @@ -1269,19 +1269,17 @@ impl VecDeque { // the drain is complete and the Drain destructor is run. self.head = drain_tail; - Drain { - deque: NonNull::from(&mut *self), - after_tail: drain_head, - after_head: head, - iter: Iter { - tail: drain_tail, - head: drain_head, - // Crucially, we only create shared references from `self` here and read from - // it. We do not write to `self` nor reborrow to a mutable reference. - // Hence the raw pointer we created above, for `deque`, remains valid. - ring: unsafe { self.buffer_as_slice() }, - }, - } + let deque = NonNull::from(&mut *self); + let iter = Iter { + tail: drain_tail, + head: drain_head, + // Crucially, we only create shared references from `self` here and read from + // it. We do not write to `self` nor reborrow to a mutable reference. + // Hence the raw pointer we created above, for `deque`, remains valid. + ring: unsafe { self.buffer_as_slice() }, + }; + + unsafe { Drain::new(drain_head, head, iter, deque) } } /// Clears the `VecDeque`, removing all values. From 5af61cb114e4af46e5c1c6c97b4556d5f007536f Mon Sep 17 00:00:00 2001 From: DeveloperC Date: Sat, 25 Sep 2021 13:55:45 +0100 Subject: [PATCH 13/15] refactor: VecDeques IterMut fields to private Made the fields of VecDeque's IterMut private by creating a IterMut::new(...) function to create a new instance of IterMut and migrating usage to use IterMut::new(...). --- .../src/collections/vec_deque/iter_mut.rs | 19 +++++++++++++++---- .../alloc/src/collections/vec_deque/mod.rs | 18 ++++++------------ 2 files changed, 21 insertions(+), 16 deletions(-) diff --git a/library/alloc/src/collections/vec_deque/iter_mut.rs b/library/alloc/src/collections/vec_deque/iter_mut.rs index 7700b31cf5b46..31e6e3b06af5f 100644 --- a/library/alloc/src/collections/vec_deque/iter_mut.rs +++ b/library/alloc/src/collections/vec_deque/iter_mut.rs @@ -13,10 +13,21 @@ use super::{count, wrap_index, RingSlices}; #[stable(feature = "rust1", since = "1.0.0")] pub struct IterMut<'a, T: 'a> { // Internal safety invariant: the entire slice is dereferencable. - pub(crate) ring: *mut [T], - pub(crate) tail: usize, - pub(crate) head: usize, - pub(crate) phantom: PhantomData<&'a mut [T]>, + ring: *mut [T], + tail: usize, + head: usize, + phantom: PhantomData<&'a mut [T]>, +} + +impl<'a, T> IterMut<'a, T> { + pub(super) unsafe fn new( + ring: *mut [T], + tail: usize, + head: usize, + phantom: PhantomData<&'a mut [T]>, + ) -> Self { + IterMut { ring, tail, head, phantom } + } } // SAFETY: we do nothing thread-local and there is no interior mutability, diff --git a/library/alloc/src/collections/vec_deque/mod.rs b/library/alloc/src/collections/vec_deque/mod.rs index f4de2b2ebe5dc..54fcb358ede1b 100644 --- a/library/alloc/src/collections/vec_deque/mod.rs +++ b/library/alloc/src/collections/vec_deque/mod.rs @@ -1000,12 +1000,9 @@ impl VecDeque { pub fn iter_mut(&mut self) -> IterMut<'_, T> { // SAFETY: The internal `IterMut` safety invariant is established because the // `ring` we create is a dereferencable slice for lifetime '_. - IterMut { - tail: self.tail, - head: self.head, - ring: ptr::slice_from_raw_parts_mut(self.ptr(), self.cap()), - phantom: PhantomData, - } + let ring = ptr::slice_from_raw_parts_mut(self.ptr(), self.cap()); + + unsafe { IterMut::new(ring, self.tail, self.head, PhantomData) } } /// Returns a pair of slices which contain, in order, the contents of the @@ -1192,12 +1189,9 @@ impl VecDeque { // SAFETY: The internal `IterMut` safety invariant is established because the // `ring` we create is a dereferencable slice for lifetime '_. - IterMut { - tail, - head, - ring: ptr::slice_from_raw_parts_mut(self.ptr(), self.cap()), - phantom: PhantomData, - } + let ring = ptr::slice_from_raw_parts_mut(self.ptr(), self.cap()); + + unsafe { IterMut::new(ring, tail, head, PhantomData) } } /// Creates a draining iterator that removes the specified range in the From 3c974adb4c4c6de497a36dec362af6c0928c7367 Mon Sep 17 00:00:00 2001 From: Aaron Hill Date: Sun, 3 Oct 2021 15:25:26 -0500 Subject: [PATCH 14/15] Note specific regions involved in 'borrowed data escapes' error Fixes #67007 Currently, a 'borrowed data escapes' error does not mention the specific lifetime involved (except indirectly through a suggestion about adding a lifetime bound). We now explain the specific lifetime relationship that failed to hold, which improves otherwise vague error messages. --- .../src/diagnostics/region_errors.rs | 21 +++++++++++ .../async-await/issues/issue-62097.nll.stderr | 10 ++++-- .../dyn-trait.nll.stderr | 9 +++-- src/test/ui/issues/issue-16683.nll.stderr | 13 +++++-- src/test/ui/issues/issue-17758.nll.stderr | 13 +++++-- ...etime-bound-will-change-warning.nll.stderr | 18 +++++++--- ...oximated-shorter-to-static-no-bound.stderr | 9 +++-- ...mated-shorter-to-static-wrong-bound.stderr | 9 +++-- src/test/ui/nll/issue-67007-escaping-data.rs | 26 ++++++++++++++ .../ui/nll/issue-67007-escaping-data.stderr | 21 +++++++++++ .../ui/nll/outlives-suggestion-simple.stderr | 9 ++++- .../user-annotations/closure-substs.stderr | 9 +++-- .../object-lifetime-default-mybox.nll.stderr | 9 +++-- src/test/ui/regions/issue-78262.nll.stderr | 7 ++-- .../ui/regions/issue-78262.polonius.stderr | 7 ++-- ...nvariant-static-error-reporting.nll.stderr | 9 +++-- ...hod-type-parameters-trait-bound.nll.stderr | 13 ++++--- ...rait-with-implicit-static-bound.nll.stderr | 36 ++++++++++++++----- 18 files changed, 209 insertions(+), 39 deletions(-) create mode 100644 src/test/ui/nll/issue-67007-escaping-data.rs create mode 100644 src/test/ui/nll/issue-67007-escaping-data.stderr diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs index d05cfebc5f02e..11cdbe84accb7 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs @@ -498,6 +498,27 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { diag.span_label(*span, format!("`{}` escapes the {} body here", fr_name, escapes_from)); } + // Only show an extra note if we can find an 'error region' for both of the region + // variables. This avoids showing a noisy note that just mentions 'synthetic' regions + // that don't help the user understand the error. + if self.to_error_region(errci.fr).is_some() + && self.to_error_region(errci.outlived_fr).is_some() + { + let fr_region_name = self.give_region_a_name(errci.fr).unwrap(); + fr_region_name.highlight_region_name(&mut diag); + let outlived_fr_region_name = self.give_region_a_name(errci.outlived_fr).unwrap(); + outlived_fr_region_name.highlight_region_name(&mut diag); + + diag.span_label( + *span, + format!( + "{}requires that `{}` must outlive `{}`", + category.description(), + fr_region_name, + outlived_fr_region_name, + ), + ); + } diag } diff --git a/src/test/ui/async-await/issues/issue-62097.nll.stderr b/src/test/ui/async-await/issues/issue-62097.nll.stderr index e71bcf5822808..786f621326049 100644 --- a/src/test/ui/async-await/issues/issue-62097.nll.stderr +++ b/src/test/ui/async-await/issues/issue-62097.nll.stderr @@ -20,9 +20,15 @@ error[E0521]: borrowed data escapes outside of associated function --> $DIR/issue-62097.rs:13:9 | LL | pub async fn run_dummy_fn(&self) { - | ----- `self` is a reference that is only valid in the associated function body + | ----- + | | + | `self` is a reference that is only valid in the associated function body + | let's call the lifetime of this reference `'1` LL | foo(|| self.bar()).await; - | ^^^^^^^^^^^^^^^^^^ `self` escapes the associated function body here + | ^^^^^^^^^^^^^^^^^^ + | | + | `self` escapes the associated function body here + | argument requires that `'1` must outlive `'static` error: aborting due to 2 previous errors diff --git a/src/test/ui/impl-header-lifetime-elision/dyn-trait.nll.stderr b/src/test/ui/impl-header-lifetime-elision/dyn-trait.nll.stderr index e49bd9da754d6..88c260b18cbb0 100644 --- a/src/test/ui/impl-header-lifetime-elision/dyn-trait.nll.stderr +++ b/src/test/ui/impl-header-lifetime-elision/dyn-trait.nll.stderr @@ -2,9 +2,14 @@ error[E0521]: borrowed data escapes outside of function --> $DIR/dyn-trait.rs:20:5 | LL | fn with_dyn_debug_static<'a>(x: Box) { - | - `x` is a reference that is only valid in the function body + | -- - `x` is a reference that is only valid in the function body + | | + | lifetime `'a` defined here LL | static_val(x); - | ^^^^^^^^^^^^^ `x` escapes the function body here + | ^^^^^^^^^^^^^ + | | + | `x` escapes the function body here + | argument requires that `'a` must outlive `'static` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-16683.nll.stderr b/src/test/ui/issues/issue-16683.nll.stderr index 51d86eaf9e60c..0e8f520353fba 100644 --- a/src/test/ui/issues/issue-16683.nll.stderr +++ b/src/test/ui/issues/issue-16683.nll.stderr @@ -1,10 +1,19 @@ error[E0521]: borrowed data escapes outside of associated function --> $DIR/issue-16683.rs:4:9 | +LL | trait T<'a> { + | -- lifetime `'a` defined here +LL | fn a(&'a self) -> &'a bool; LL | fn b(&self) { - | ----- `self` is a reference that is only valid in the associated function body + | ----- + | | + | `self` is a reference that is only valid in the associated function body + | let's call the lifetime of this reference `'1` LL | self.a(); - | ^^^^^^^^ `self` escapes the associated function body here + | ^^^^^^^^ + | | + | `self` escapes the associated function body here + | argument requires that `'1` must outlive `'a` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-17758.nll.stderr b/src/test/ui/issues/issue-17758.nll.stderr index 075c141ed7af6..b929fdbf3687a 100644 --- a/src/test/ui/issues/issue-17758.nll.stderr +++ b/src/test/ui/issues/issue-17758.nll.stderr @@ -1,10 +1,19 @@ error[E0521]: borrowed data escapes outside of associated function --> $DIR/issue-17758.rs:7:9 | +LL | trait Foo<'a> { + | -- lifetime `'a` defined here +LL | fn foo(&'a self); LL | fn bar(&self) { - | ----- `self` is a reference that is only valid in the associated function body + | ----- + | | + | `self` is a reference that is only valid in the associated function body + | let's call the lifetime of this reference `'1` LL | self.foo(); - | ^^^^^^^^^^ `self` escapes the associated function body here + | ^^^^^^^^^^ + | | + | `self` escapes the associated function body here + | argument requires that `'1` must outlive `'a` error: aborting due to previous error diff --git a/src/test/ui/lifetimes/lifetime-bound-will-change-warning.nll.stderr b/src/test/ui/lifetimes/lifetime-bound-will-change-warning.nll.stderr index 050d5fcf05ef4..6f3f84096e400 100644 --- a/src/test/ui/lifetimes/lifetime-bound-will-change-warning.nll.stderr +++ b/src/test/ui/lifetimes/lifetime-bound-will-change-warning.nll.stderr @@ -2,19 +2,29 @@ error[E0521]: borrowed data escapes outside of function --> $DIR/lifetime-bound-will-change-warning.rs:34:5 | LL | fn test2<'a>(x: &'a Box) { - | - `x` is a reference that is only valid in the function body + | -- - `x` is a reference that is only valid in the function body + | | + | lifetime `'a` defined here LL | // but ref_obj will not, so warn. LL | ref_obj(x) - | ^^^^^^^^^^ `x` escapes the function body here + | ^^^^^^^^^^ + | | + | `x` escapes the function body here + | argument requires that `'a` must outlive `'static` error[E0521]: borrowed data escapes outside of function --> $DIR/lifetime-bound-will-change-warning.rs:39:5 | LL | fn test2cc<'a>(x: &'a Box) { - | - `x` is a reference that is only valid in the function body + | -- - `x` is a reference that is only valid in the function body + | | + | lifetime `'a` defined here LL | // same as test2, but cross crate LL | lib::ref_obj(x) - | ^^^^^^^^^^^^^^^ `x` escapes the function body here + | ^^^^^^^^^^^^^^^ + | | + | `x` escapes the function body here + | argument requires that `'a` must outlive `'static` error: aborting due to 2 previous errors diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr index d17a40a95c1b8..d77793291c5c5 100644 --- a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr +++ b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr @@ -38,14 +38,19 @@ error[E0521]: borrowed data escapes outside of function --> $DIR/propagate-approximated-shorter-to-static-no-bound.rs:32:5 | LL | fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) { - | ------ `cell_a` is a reference that is only valid in the function body + | -- ------ `cell_a` is a reference that is only valid in the function body + | | + | lifetime `'a` defined here LL | / establish_relationships(&cell_a, &cell_b, |_outlives, x, y| { LL | | LL | | LL | | // Only works if 'x: 'y: LL | | demand_y(x, y, x.get()) LL | | }); - | |______^ `cell_a` escapes the function body here + | | ^ + | | | + | |______`cell_a` escapes the function body here + | argument requires that `'a` must outlive `'static` error: aborting due to previous error diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr index 06c46ec8259a0..cc67270ad20c1 100644 --- a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr +++ b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr @@ -38,14 +38,19 @@ error[E0521]: borrowed data escapes outside of function --> $DIR/propagate-approximated-shorter-to-static-wrong-bound.rs:35:5 | LL | fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) { - | ------ `cell_a` is a reference that is only valid in the function body + | -- ------ `cell_a` is a reference that is only valid in the function body + | | + | lifetime `'a` defined here LL | / establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| { LL | | LL | | LL | | // Only works if 'x: 'y: LL | | demand_y(x, y, x.get()) LL | | }); - | |______^ `cell_a` escapes the function body here + | | ^ + | | | + | |______`cell_a` escapes the function body here + | argument requires that `'a` must outlive `'static` error: aborting due to previous error diff --git a/src/test/ui/nll/issue-67007-escaping-data.rs b/src/test/ui/nll/issue-67007-escaping-data.rs new file mode 100644 index 0000000000000..8c21737e05fe8 --- /dev/null +++ b/src/test/ui/nll/issue-67007-escaping-data.rs @@ -0,0 +1,26 @@ +// Regression test for issue #67007 +// Ensures that we show information about the specific regions involved + +#![feature(nll)] + +// Covariant over 'a, invariant over 'tcx +struct FnCtxt<'a, 'tcx: 'a>(&'a (), *mut &'tcx ()); + +impl<'a, 'tcx> FnCtxt<'a, 'tcx> { + fn use_it(&self, _: &'tcx ()) {} +} + +struct Consumer<'tcx>(&'tcx ()); + +impl<'tcx> Consumer<'tcx> { + fn bad_method<'a>(&self, fcx: &FnCtxt<'a, 'tcx>) { + let other = self.use_fcx(fcx); //~ ERROR borrowed data + fcx.use_it(other); + } + + fn use_fcx<'a>(&self, _: &FnCtxt<'a, 'tcx>) -> &'a () { + &() + } +} + +fn main() {} diff --git a/src/test/ui/nll/issue-67007-escaping-data.stderr b/src/test/ui/nll/issue-67007-escaping-data.stderr new file mode 100644 index 0000000000000..2834d6fb0d214 --- /dev/null +++ b/src/test/ui/nll/issue-67007-escaping-data.stderr @@ -0,0 +1,21 @@ +error[E0521]: borrowed data escapes outside of associated function + --> $DIR/issue-67007-escaping-data.rs:17:21 + | +LL | impl<'tcx> Consumer<'tcx> { + | ---- lifetime `'tcx` defined here +LL | fn bad_method<'a>(&self, fcx: &FnCtxt<'a, 'tcx>) { + | -- ----- --- `fcx` is a reference that is only valid in the associated function body + | | | + | | `self` declared here, outside of the associated function body + | lifetime `'a` defined here +LL | let other = self.use_fcx(fcx); + | ^^^^^^^^^^^^^^^^^ + | | + | `fcx` escapes the associated function body here + | argument requires that `'a` must outlive `'tcx` + | + = help: consider adding the following bound: `'a: 'tcx` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0521`. diff --git a/src/test/ui/nll/outlives-suggestion-simple.stderr b/src/test/ui/nll/outlives-suggestion-simple.stderr index fa85ce2799083..3b2017d2d03a1 100644 --- a/src/test/ui/nll/outlives-suggestion-simple.stderr +++ b/src/test/ui/nll/outlives-suggestion-simple.stderr @@ -92,13 +92,20 @@ LL | self.x error[E0521]: borrowed data escapes outside of associated function --> $DIR/outlives-suggestion-simple.rs:73:9 | +LL | impl<'a> Foo2<'a> { + | -- lifetime `'a` defined here +LL | // should not produce outlives suggestions to name 'self LL | fn get_bar(&self) -> Bar2 { | ----- | | | `self` declared here, outside of the associated function body | `self` is a reference that is only valid in the associated function body + | let's call the lifetime of this reference `'1` LL | Bar2::new(&self) - | ^^^^^^^^^^^^^^^^ `self` escapes the associated function body here + | ^^^^^^^^^^^^^^^^ + | | + | `self` escapes the associated function body here + | argument requires that `'1` must outlive `'a` error: aborting due to 9 previous errors diff --git a/src/test/ui/nll/user-annotations/closure-substs.stderr b/src/test/ui/nll/user-annotations/closure-substs.stderr index 55bb3a6090c01..20002e4591d1a 100644 --- a/src/test/ui/nll/user-annotations/closure-substs.stderr +++ b/src/test/ui/nll/user-annotations/closure-substs.stderr @@ -28,9 +28,14 @@ error[E0521]: borrowed data escapes outside of closure --> $DIR/closure-substs.rs:29:9 | LL | |x: &i32, b: fn(&'static i32)| { - | - `x` is a reference that is only valid in the closure body + | - - let's call the lifetime of this reference `'1` + | | + | `x` is a reference that is only valid in the closure body LL | b(x); - | ^^^^ `x` escapes the closure body here + | ^^^^ + | | + | `x` escapes the closure body here + | argument requires that `'1` must outlive `'static` error: aborting due to 4 previous errors diff --git a/src/test/ui/object-lifetime/object-lifetime-default-mybox.nll.stderr b/src/test/ui/object-lifetime/object-lifetime-default-mybox.nll.stderr index 6ce1b2eed85d2..af20c5e5fc0da 100644 --- a/src/test/ui/object-lifetime/object-lifetime-default-mybox.nll.stderr +++ b/src/test/ui/object-lifetime/object-lifetime-default-mybox.nll.stderr @@ -15,9 +15,14 @@ error[E0521]: borrowed data escapes outside of function --> $DIR/object-lifetime-default-mybox.rs:31:5 | LL | fn load2<'a>(ss: &MyBox) -> MyBox { - | -- `ss` is a reference that is only valid in the function body + | -- -- `ss` is a reference that is only valid in the function body + | | + | lifetime `'a` defined here LL | load0(ss) - | ^^^^^^^^^ `ss` escapes the function body here + | ^^^^^^^^^ + | | + | `ss` escapes the function body here + | argument requires that `'a` must outlive `'static` error: aborting due to 2 previous errors diff --git a/src/test/ui/regions/issue-78262.nll.stderr b/src/test/ui/regions/issue-78262.nll.stderr index a35d6fd9bf885..721dafac0be76 100644 --- a/src/test/ui/regions/issue-78262.nll.stderr +++ b/src/test/ui/regions/issue-78262.nll.stderr @@ -2,8 +2,11 @@ error[E0521]: borrowed data escapes outside of closure --> $DIR/issue-78262.rs:14:26 | LL | let f = |x: &dyn TT| x.func(); - | - ^^^^^^^^ `x` escapes the closure body here - | | + | - - ^^^^^^^^ + | | | | + | | | `x` escapes the closure body here + | | | argument requires that `'1` must outlive `'static` + | | let's call the lifetime of this reference `'1` | `x` is a reference that is only valid in the closure body error: aborting due to previous error diff --git a/src/test/ui/regions/issue-78262.polonius.stderr b/src/test/ui/regions/issue-78262.polonius.stderr index a35d6fd9bf885..721dafac0be76 100644 --- a/src/test/ui/regions/issue-78262.polonius.stderr +++ b/src/test/ui/regions/issue-78262.polonius.stderr @@ -2,8 +2,11 @@ error[E0521]: borrowed data escapes outside of closure --> $DIR/issue-78262.rs:14:26 | LL | let f = |x: &dyn TT| x.func(); - | - ^^^^^^^^ `x` escapes the closure body here - | | + | - - ^^^^^^^^ + | | | | + | | | `x` escapes the closure body here + | | | argument requires that `'1` must outlive `'static` + | | let's call the lifetime of this reference `'1` | `x` is a reference that is only valid in the closure body error: aborting due to previous error diff --git a/src/test/ui/regions/region-invariant-static-error-reporting.nll.stderr b/src/test/ui/regions/region-invariant-static-error-reporting.nll.stderr index 7221759dbd450..e220cbf555956 100644 --- a/src/test/ui/regions/region-invariant-static-error-reporting.nll.stderr +++ b/src/test/ui/regions/region-invariant-static-error-reporting.nll.stderr @@ -2,10 +2,15 @@ error[E0521]: borrowed data escapes outside of function --> $DIR/region-invariant-static-error-reporting.rs:15:9 | LL | fn unify<'a>(x: Option>, f: fn(Invariant<'a>)) { - | - `x` is a reference that is only valid in the function body + | -- - `x` is a reference that is only valid in the function body + | | + | lifetime `'a` defined here LL | let bad = if x.is_some() { LL | x.unwrap() - | ^^^^^^^^^^ `x` escapes the function body here + | ^^^^^^^^^^ + | | + | `x` escapes the function body here + | argument requires that `'a` must outlive `'static` error: aborting due to previous error diff --git a/src/test/ui/regions/regions-bounded-method-type-parameters-trait-bound.nll.stderr b/src/test/ui/regions/regions-bounded-method-type-parameters-trait-bound.nll.stderr index ed7b17c207c30..83d6e13dc0a68 100644 --- a/src/test/ui/regions/regions-bounded-method-type-parameters-trait-bound.nll.stderr +++ b/src/test/ui/regions/regions-bounded-method-type-parameters-trait-bound.nll.stderr @@ -2,12 +2,17 @@ error[E0521]: borrowed data escapes outside of function --> $DIR/regions-bounded-method-type-parameters-trait-bound.rs:20:5 | LL | fn caller2<'a,'b,F:Foo<'a>>(a: Inv<'a>, b: Inv<'b>, f: F) { - | - - `b` is a reference that is only valid in the function body - | | - | `a` declared here, outside of the function body + | -- -- - - `b` is a reference that is only valid in the function body + | | | | + | | | `a` declared here, outside of the function body + | | lifetime `'b` defined here + | lifetime `'a` defined here LL | // Here the value provided for 'y is 'b, and hence 'b:'a does not hold. LL | f.method(b); - | ^^^^^^^^^^^ `b` escapes the function body here + | ^^^^^^^^^^^ + | | + | `b` escapes the function body here + | argument requires that `'b` must outlive `'a` | = help: consider adding the following bound: `'b: 'a` diff --git a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.nll.stderr b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.nll.stderr index 32a2de1e84d8f..a1ef32c5445b5 100644 --- a/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.nll.stderr +++ b/src/test/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.nll.stderr @@ -2,33 +2,53 @@ error[E0521]: borrowed data escapes outside of function --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:20:9 | LL | fn use_it<'a, T>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a { - | --- `val` is a reference that is only valid in the function body + | -- --- `val` is a reference that is only valid in the function body + | | + | lifetime `'a` defined here LL | val.use_self::() - | ^^^^^^^^^^^^^^^^^^^ `val` escapes the function body here + | ^^^^^^^^^^^^^^^^^^^ + | | + | `val` escapes the function body here + | argument requires that `'a` must outlive `'static` error[E0521]: borrowed data escapes outside of function --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:69:9 | LL | fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a { - | --- `val` is a reference that is only valid in the function body + | -- --- `val` is a reference that is only valid in the function body + | | + | lifetime `'a` defined here LL | val.use_self() - | ^^^^^^^^^^^^^^ `val` escapes the function body here + | ^^^^^^^^^^^^^^ + | | + | `val` escapes the function body here + | argument requires that `'a` must outlive `'static` error[E0521]: borrowed data escapes outside of function --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:88:9 | LL | fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> { - | --- `val` is a reference that is only valid in the function body + | -- --- `val` is a reference that is only valid in the function body + | | + | lifetime `'a` defined here LL | val.use_self() - | ^^^^^^^^^^^^^^ `val` escapes the function body here + | ^^^^^^^^^^^^^^ + | | + | `val` escapes the function body here + | argument requires that `'a` must outlive `'static` error[E0521]: borrowed data escapes outside of function --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:108:9 | LL | fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a { - | --- `val` is a reference that is only valid in the function body + | -- --- `val` is a reference that is only valid in the function body + | | + | lifetime `'a` defined here LL | MyTrait::use_self(val) - | ^^^^^^^^^^^^^^^^^^^^^^ `val` escapes the function body here + | ^^^^^^^^^^^^^^^^^^^^^^ + | | + | `val` escapes the function body here + | argument requires that `'a` must outlive `'static` error: aborting due to 4 previous errors From edfd6d591b51da089b65c68ece0aecd1e9b8a42b Mon Sep 17 00:00:00 2001 From: Ellen Date: Wed, 6 Oct 2021 04:37:07 +0100 Subject: [PATCH 15/15] test --- .../const_eval_resolve_canonical.rs | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 src/test/ui/const-generics/generic_const_exprs/const_eval_resolve_canonical.rs diff --git a/src/test/ui/const-generics/generic_const_exprs/const_eval_resolve_canonical.rs b/src/test/ui/const-generics/generic_const_exprs/const_eval_resolve_canonical.rs new file mode 100644 index 0000000000000..b79bc262d2bac --- /dev/null +++ b/src/test/ui/const-generics/generic_const_exprs/const_eval_resolve_canonical.rs @@ -0,0 +1,29 @@ +// run-pass +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +trait Foo { + type Assoc: Default; +} + +impl Foo<0> for () { + type Assoc = u32; +} + +impl Foo<3> for () { + type Assoc = i64; +} + +fn foo(_: T) -> <() as Foo<{ N + 1 }>>::Assoc +where + (): Foo<{ N + 1 }>, +{ + Default::default() +} + +fn main() { + // Test that we can correctly infer `T` which requires evaluating + // `{ N + 1 }` which has substs containing an inference var + let mut _q = Default::default(); + _q = foo::<_, 2>(_q); +}