From 57e0dea178eba21de2b001f731aeb95692ee84b9 Mon Sep 17 00:00:00 2001 From: John-John Tedro Date: Sun, 28 Jan 2024 15:39:19 +0100 Subject: [PATCH 01/17] Document requirements for unsized {Rc,Arc}::from_raw --- library/alloc/src/rc.rs | 20 ++++++++++++++------ library/alloc/src/sync.rs | 20 ++++++++++++++------ 2 files changed, 28 insertions(+), 12 deletions(-) diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index 7705c86001e6..5e85746656ec 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -1181,12 +1181,19 @@ impl Rc { /// Constructs an `Rc` from a raw pointer. /// /// The raw pointer must have been previously returned by a call to - /// [`Rc::into_raw`][into_raw] where `U` must have the same size - /// and alignment as `T`. This is trivially true if `U` is `T`. - /// Note that if `U` is not `T` but has the same size and alignment, this is - /// basically like transmuting references of different types. See - /// [`mem::transmute`][transmute] for more information on what - /// restrictions apply in this case. + /// [`Rc::into_raw`][into_raw] with the following requirements: + /// + /// * If `U` is sized, it must have the same size and alignment as `T`. This + /// is trivially true if `U` is `T`. + /// * If `U` is unsized, its data pointer must have the same size and + /// alignment as `T`. This is trivially true if `Arc` was constructed + /// through `Arc` and then converted to `Arc` through an [unsized + /// coercion]. + /// + /// Note that if `U` or `U`'s data pointer is not `T` but has the same size + /// and alignment, this is basically like transmuting references of + /// different types. See [`mem::transmute`][transmute] for more information + /// on what restrictions apply in this case. /// /// The raw pointer must point to a block of memory allocated by the global allocator /// @@ -1198,6 +1205,7 @@ impl Rc { /// /// [into_raw]: Rc::into_raw /// [transmute]: core::mem::transmute + /// [unsized coercion]: https://doc.rust-lang.org/reference/type-coercions.html#unsized-coercions /// /// # Examples /// diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index 48c8d9d113b0..95cf2da0ecf7 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -1329,12 +1329,19 @@ impl Arc { /// Constructs an `Arc` from a raw pointer. /// /// The raw pointer must have been previously returned by a call to - /// [`Arc::into_raw`][into_raw] where `U` must have the same size and - /// alignment as `T`. This is trivially true if `U` is `T`. - /// Note that if `U` is not `T` but has the same size and alignment, this is - /// basically like transmuting references of different types. See - /// [`mem::transmute`][transmute] for more information on what - /// restrictions apply in this case. + /// [`Arc::into_raw`][into_raw] with the following requirements: + /// + /// * If `U` is sized, it must have the same size and alignment as `T`. This + /// is trivially true if `U` is `T`. + /// * If `U` is unsized, its data pointer must have the same size and + /// alignment as `T`. This is trivially true if `Arc` was constructed + /// through `Arc` and then converted to `Arc` through an [unsized + /// coercion]. + /// + /// Note that if `U` or `U`'s data pointer is not `T` but has the same size + /// and alignment, this is basically like transmuting references of + /// different types. See [`mem::transmute`][transmute] for more information + /// on what restrictions apply in this case. /// /// The user of `from_raw` has to make sure a specific value of `T` is only /// dropped once. @@ -1344,6 +1351,7 @@ impl Arc { /// /// [into_raw]: Arc::into_raw /// [transmute]: core::mem::transmute + /// [unsized coercion]: https://doc.rust-lang.org/reference/type-coercions.html#unsized-coercions /// /// # Examples /// From d4adb3af585daac5077c8852bc0b26bb661330c8 Mon Sep 17 00:00:00 2001 From: John-John Tedro Date: Sun, 28 Jan 2024 16:07:07 +0100 Subject: [PATCH 02/17] Add examples for unsized {Rc,Arc}::from_raw --- library/alloc/src/rc.rs | 14 ++++++++++++++ library/alloc/src/sync.rs | 14 ++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index 5e85746656ec..0a959738b97e 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -1225,6 +1225,20 @@ impl Rc { /// /// // The memory was freed when `x` went out of scope above, so `x_ptr` is now dangling! /// ``` + /// + /// Convert a slice back into its original array: + /// + /// ``` + /// use std::rc::Rc; + /// + /// let x: Rc<[u32]> = Rc::new([1, 2, 3]); + /// let x_ptr: *const [u32] = Rc::into_raw(x); + /// + /// unsafe { + /// let x: Rc<[u32; 3]> = Rc::from_raw(x_ptr.cast::<[u32; 3]>()) + /// assert_eq!(x.as_ref(), &[1, 2, 3]); + /// } + /// ``` #[inline] #[stable(feature = "rc_raw", since = "1.17.0")] pub unsafe fn from_raw(ptr: *const T) -> Self { diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index 95cf2da0ecf7..708f11edc448 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -1371,6 +1371,20 @@ impl Arc { /// /// // The memory was freed when `x` went out of scope above, so `x_ptr` is now dangling! /// ``` + /// + /// Convert a slice back into its original array: + /// + /// ``` + /// use std::sync::Arc; + /// + /// let x: Arc<[u32]> = Arc::new([1, 2, 3]); + /// let x_ptr: *const [u32] = Arc::into_raw(x); + /// + /// unsafe { + /// let x: Arc<[u32; 3]> = Arc::from_raw(x_ptr.cast::<[u32; 3]>()) + /// assert_eq!(x.as_ref(), &[1, 2, 3]); + /// } + /// ``` #[inline] #[stable(feature = "rc_raw", since = "1.17.0")] pub unsafe fn from_raw(ptr: *const T) -> Self { From 23c83fab2b16d79b248b1b5f2faf7b538afec9f6 Mon Sep 17 00:00:00 2001 From: John-John Tedro Date: Sun, 28 Jan 2024 16:12:09 +0100 Subject: [PATCH 03/17] Tidy up --- library/alloc/src/rc.rs | 2 +- library/alloc/src/sync.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index 0a959738b97e..1d16095db1e4 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -1182,7 +1182,7 @@ impl Rc { /// /// The raw pointer must have been previously returned by a call to /// [`Rc::into_raw`][into_raw] with the following requirements: - /// + /// /// * If `U` is sized, it must have the same size and alignment as `T`. This /// is trivially true if `U` is `T`. /// * If `U` is unsized, its data pointer must have the same size and diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index 708f11edc448..0487dc5a8583 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -1330,7 +1330,7 @@ impl Arc { /// /// The raw pointer must have been previously returned by a call to /// [`Arc::into_raw`][into_raw] with the following requirements: - /// + /// /// * If `U` is sized, it must have the same size and alignment as `T`. This /// is trivially true if `U` is `T`. /// * If `U` is unsized, its data pointer must have the same size and From d63384d689ef9dab759eee57e3c2b0f82dfef4e3 Mon Sep 17 00:00:00 2001 From: John-John Tedro Date: Sun, 28 Jan 2024 16:38:38 +0100 Subject: [PATCH 04/17] Fix doctest --- library/alloc/src/rc.rs | 4 ++-- library/alloc/src/sync.rs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index 1d16095db1e4..8331a2d63a01 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -1235,8 +1235,8 @@ impl Rc { /// let x_ptr: *const [u32] = Rc::into_raw(x); /// /// unsafe { - /// let x: Rc<[u32; 3]> = Rc::from_raw(x_ptr.cast::<[u32; 3]>()) - /// assert_eq!(x.as_ref(), &[1, 2, 3]); + /// let x: Rc<[u32; 3]> = Rc::from_raw(x_ptr.cast::<[u32; 3]>()); + /// assert_eq!(&*x, &[1, 2, 3]); /// } /// ``` #[inline] diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index 0487dc5a8583..bfbdfce57186 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -1381,8 +1381,8 @@ impl Arc { /// let x_ptr: *const [u32] = Arc::into_raw(x); /// /// unsafe { - /// let x: Arc<[u32; 3]> = Arc::from_raw(x_ptr.cast::<[u32; 3]>()) - /// assert_eq!(x.as_ref(), &[1, 2, 3]); + /// let x: Arc<[u32; 3]> = Arc::from_raw(x_ptr.cast::<[u32; 3]>()); + /// assert_eq!(&*x, &[1, 2, 3]); /// } /// ``` #[inline] From eebc7207579d06ccdb38bd79c01bec08f1c29bde Mon Sep 17 00:00:00 2001 From: John-John Tedro Date: Sun, 28 Jan 2024 17:00:13 +0100 Subject: [PATCH 05/17] Replicate documentation in {Rc,Arc}::from_raw_in --- library/alloc/src/rc.rs | 43 +++++++++++++++++++++++++++++++-------- library/alloc/src/sync.rs | 39 ++++++++++++++++++++++++++++------- 2 files changed, 66 insertions(+), 16 deletions(-) diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index 8331a2d63a01..ebd816fba813 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -1186,8 +1186,8 @@ impl Rc { /// * If `U` is sized, it must have the same size and alignment as `T`. This /// is trivially true if `U` is `T`. /// * If `U` is unsized, its data pointer must have the same size and - /// alignment as `T`. This is trivially true if `Arc` was constructed - /// through `Arc` and then converted to `Arc` through an [unsized + /// alignment as `T`. This is trivially true if `Rc` was constructed + /// through `Rc` and then converted to `Rc` through an [unsized /// coercion]. /// /// Note that if `U` or `U`'s data pointer is not `T` but has the same size @@ -1363,13 +1363,20 @@ impl Rc { /// Constructs an `Rc` from a raw pointer in the provided allocator. /// - /// The raw pointer must have been previously returned by a call to - /// [`Rc::into_raw`][into_raw] where `U` must have the same size - /// and alignment as `T`. This is trivially true if `U` is `T`. - /// Note that if `U` is not `T` but has the same size and alignment, this is - /// basically like transmuting references of different types. See - /// [`mem::transmute`] for more information on what - /// restrictions apply in this case. + /// The raw pointer must have been previously returned by a call to [`Rc::into_raw`][into_raw] with the following requirements: + /// + /// * If `U` is sized, it must have the same size and alignment as `T`. This + /// is trivially true if `U` is `T`. + /// * If `U` is unsized, its data pointer must have the same size and + /// alignment as `T`. This is trivially true if `Rc` was constructed + /// through `Rc` and then converted to `Rc` through an [unsized + /// coercion]. + /// + /// Note that if `U` or `U`'s data pointer is not `T` but has the same size + /// and alignment, this is basically like transmuting references of + /// different types. See [`mem::transmute`][transmute] for more information + /// on what restrictions apply in this case. /// /// The raw pointer must point to a block of memory allocated by `alloc` /// @@ -1380,6 +1387,7 @@ impl Rc { /// even if the returned `Rc` is never accessed. /// /// [into_raw]: Rc::into_raw + /// [unsized coercion]: https://doc.rust-lang.org/reference/type-coercions.html#unsized-coercions /// /// # Examples /// @@ -1402,6 +1410,23 @@ impl Rc { /// /// // The memory was freed when `x` went out of scope above, so `x_ptr` is now dangling! /// ``` + /// + /// Convert a slice back into its original array: + /// + /// ``` + /// #![feature(allocator_api)] + /// + /// use std::rc::Rc; + /// use std::alloc::System; + /// + /// let x: Rc<[u32]> = Rc::new_in([1, 2, 3], System); + /// let x_ptr: *const [u32] = Rc::into_raw(x); + /// + /// unsafe { + /// let x: Rc<[u32; 3]> = Rc::from_raw_in(x_ptr.cast::<[u32; 3]>(), System); + /// assert_eq!(&*x, &[1, 2, 3]); + /// } + /// ``` #[unstable(feature = "allocator_api", issue = "32838")] pub unsafe fn from_raw_in(ptr: *const T, alloc: A) -> Self { let offset = unsafe { data_offset(ptr) }; diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index bfbdfce57186..96f8f57f9e09 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -1514,13 +1514,20 @@ impl Arc { /// Constructs an `Arc` from a raw pointer. /// - /// The raw pointer must have been previously returned by a call to - /// [`Arc::into_raw`][into_raw] where `U` must have the same size and - /// alignment as `T`. This is trivially true if `U` is `T`. - /// Note that if `U` is not `T` but has the same size and alignment, this is - /// basically like transmuting references of different types. See - /// [`mem::transmute`] for more information on what - /// restrictions apply in this case. + /// The raw pointer must have been previously returned by a call to [`Arc::into_raw`][into_raw] with the following requirements: + /// + /// * If `U` is sized, it must have the same size and alignment as `T`. This + /// is trivially true if `U` is `T`. + /// * If `U` is unsized, its data pointer must have the same size and + /// alignment as `T`. This is trivially true if `Arc` was constructed + /// through `Arc` and then converted to `Arc` through an [unsized + /// coercion]. + /// + /// Note that if `U` or `U`'s data pointer is not `T` but has the same size + /// and alignment, this is basically like transmuting references of + /// different types. See [`mem::transmute`][transmute] for more information + /// on what restrictions apply in this case. /// /// The raw pointer must point to a block of memory allocated by `alloc` /// @@ -1531,6 +1538,7 @@ impl Arc { /// even if the returned `Arc` is never accessed. /// /// [into_raw]: Arc::into_raw + /// [unsized coercion]: https://doc.rust-lang.org/reference/type-coercions.html#unsized-coercions /// /// # Examples /// @@ -1553,6 +1561,23 @@ impl Arc { /// /// // The memory was freed when `x` went out of scope above, so `x_ptr` is now dangling! /// ``` + /// + /// Convert a slice back into its original array: + /// + /// ``` + /// #![feature(allocator_api)] + /// + /// use std::sync::Arc; + /// use std::alloc::System; + /// + /// let x: Arc<[u32]> = Arc::new_in([1, 2, 3], System); + /// let x_ptr: *const [u32] = Arc::into_raw(x); + /// + /// unsafe { + /// let x: Arc<[u32; 3]> = Arc::from_raw_in(x_ptr.cast::<[u32; 3]>(), System); + /// assert_eq!(&*x, &[1, 2, 3]); + /// } + /// ``` #[inline] #[unstable(feature = "allocator_api", issue = "32838")] pub unsafe fn from_raw_in(ptr: *const T, alloc: A) -> Self { From bdbbf04a03311a79a193196f7ac64e5fd164af44 Mon Sep 17 00:00:00 2001 From: John-John Tedro Date: Sun, 28 Jan 2024 17:33:17 +0100 Subject: [PATCH 06/17] Fix doctest --- library/alloc/src/rc.rs | 5 +++-- library/alloc/src/sync.rs | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index ebd816fba813..ca4ddaa92a54 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -1387,6 +1387,7 @@ impl Rc { /// even if the returned `Rc` is never accessed. /// /// [into_raw]: Rc::into_raw + /// [transmute]: core::mem::transmute /// [unsized coercion]: https://doc.rust-lang.org/reference/type-coercions.html#unsized-coercions /// /// # Examples @@ -1419,11 +1420,11 @@ impl Rc { /// use std::rc::Rc; /// use std::alloc::System; /// - /// let x: Rc<[u32]> = Rc::new_in([1, 2, 3], System); + /// let x: Rc<[u32], _> = Rc::new_in([1, 2, 3], System); /// let x_ptr: *const [u32] = Rc::into_raw(x); /// /// unsafe { - /// let x: Rc<[u32; 3]> = Rc::from_raw_in(x_ptr.cast::<[u32; 3]>(), System); + /// let x: Rc<[u32; 3], _> = Rc::from_raw_in(x_ptr.cast::<[u32; 3]>(), System); /// assert_eq!(&*x, &[1, 2, 3]); /// } /// ``` diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index 96f8f57f9e09..9bf4881869ed 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -1538,6 +1538,7 @@ impl Arc { /// even if the returned `Arc` is never accessed. /// /// [into_raw]: Arc::into_raw + /// [transmute]: core::mem::transmute /// [unsized coercion]: https://doc.rust-lang.org/reference/type-coercions.html#unsized-coercions /// /// # Examples @@ -1570,11 +1571,11 @@ impl Arc { /// use std::sync::Arc; /// use std::alloc::System; /// - /// let x: Arc<[u32]> = Arc::new_in([1, 2, 3], System); + /// let x: Arc<[u32], _> = Arc::new_in([1, 2, 3], System); /// let x_ptr: *const [u32] = Arc::into_raw(x); /// /// unsafe { - /// let x: Arc<[u32; 3]> = Arc::from_raw_in(x_ptr.cast::<[u32; 3]>(), System); + /// let x: Arc<[u32; 3], _> = Arc::from_raw_in(x_ptr.cast::<[u32; 3]>(), System); /// assert_eq!(&*x, &[1, 2, 3]); /// } /// ``` From adb7607189e04a20e67fe089d23d418826177186 Mon Sep 17 00:00:00 2001 From: Amanieu d'Antras Date: Tue, 30 Jan 2024 17:51:20 +0000 Subject: [PATCH 07/17] Fix BTreeMap's Cursor::remove_{next,prev} These would incorrectly leave `current` as `None` after a failed attempt to remove an element (due to the cursor already being at the start/end). --- library/alloc/src/collections/btree/map.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/library/alloc/src/collections/btree/map.rs b/library/alloc/src/collections/btree/map.rs index b585e2082f13..6e0b79b9640f 100644 --- a/library/alloc/src/collections/btree/map.rs +++ b/library/alloc/src/collections/btree/map.rs @@ -3198,9 +3198,15 @@ impl<'a, K: Ord, V, A: Allocator + Clone> CursorMutKey<'a, K, V, A> { #[unstable(feature = "btree_cursors", issue = "107540")] pub fn remove_next(&mut self) -> Option<(K, V)> { let current = self.current.take()?; + if current.reborrow().next_kv().is_err() { + self.current = Some(current); + return None; + } let mut emptied_internal_root = false; let (kv, pos) = current .next_kv() + // This should be unwrap(), but that doesn't work because NodeRef + // doesn't implement Debug. The condition is checked above. .ok()? .remove_kv_tracking(|| emptied_internal_root = true, self.alloc.clone()); self.current = Some(pos); @@ -3221,9 +3227,15 @@ impl<'a, K: Ord, V, A: Allocator + Clone> CursorMutKey<'a, K, V, A> { #[unstable(feature = "btree_cursors", issue = "107540")] pub fn remove_prev(&mut self) -> Option<(K, V)> { let current = self.current.take()?; + if current.reborrow().next_back_kv().is_err() { + self.current = Some(current); + return None; + } let mut emptied_internal_root = false; let (kv, pos) = current .next_back_kv() + // This should be unwrap(), but that doesn't work because NodeRef + // doesn't implement Debug. The condition is checked above. .ok()? .remove_kv_tracking(|| emptied_internal_root = true, self.alloc.clone()); self.current = Some(pos); From 6686ca08a2f1350de83ac91e36cb9132fa6d53ce Mon Sep 17 00:00:00 2001 From: David Carlier Date: Mon, 5 Feb 2024 10:13:48 +0000 Subject: [PATCH 08/17] std::thread update freebsd stack guard handling. up to now, it had been assumed the stack guard setting default is not touched in the field but some user might just want to disable it or increase it. checking it once at runtime should be enough. --- library/std/src/sys/pal/unix/thread.rs | 30 +++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/library/std/src/sys/pal/unix/thread.rs b/library/std/src/sys/pal/unix/thread.rs index 7e4a01a5ecd3..ba8d31c23a51 100644 --- a/library/std/src/sys/pal/unix/thread.rs +++ b/library/std/src/sys/pal/unix/thread.rs @@ -847,11 +847,31 @@ pub mod guard { let stackptr = get_stack_start_aligned()?; let guardaddr = stackptr.addr(); // Technically the number of guard pages is tunable and controlled - // by the security.bsd.stack_guard_page sysctl, but there are - // few reasons to change it from the default. The default value has - // been 1 ever since FreeBSD 11.1 and 10.4. - const GUARD_PAGES: usize = 1; - let guard = guardaddr..guardaddr + GUARD_PAGES * page_size; + // by the security.bsd.stack_guard_page sysctl. + // By default it is 1, checking once is enough since it is + // a boot time config value. + static LOCK: crate::sync::OnceLock = crate::sync::OnceLock::new(); + let guard = guardaddr + ..guardaddr + + *LOCK.get_or_init(|| { + use crate::sys::weak::dlsym; + dlsym!(fn sysctlbyname(*const libc::c_char, *mut libc::c_void, *mut libc::size_t, *const libc::c_void, libc::size_t) -> libc::c_int); + let mut guard: usize = 0; + let mut size = crate::mem::size_of_val(&guard); + let oid = crate::ffi::CStr::from_bytes_with_nul( + b"security.bsd.stack_guard_page\0", + ) + .unwrap(); + match sysctlbyname.get() { + Some(fcn) => { + if fcn(oid.as_ptr(), &mut guard as *mut _ as *mut _, &mut size as *mut _ as *mut _, crate::ptr::null_mut(), 0) == 0 { + return guard; + } + return 1; + }, + _ => { return 1; } + } + }) * page_size; Some(guard) } else if cfg!(target_os = "openbsd") { // OpenBSD stack already includes a guard page, and stack is From 369fff6c0640fe89be9b915adaa83e66a022e00d Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Wed, 14 Feb 2024 16:26:20 +0100 Subject: [PATCH 09/17] Implicitly enable evex512 if avx512 is enabled LLVM 18 requires the evex512 feature to allow use of zmm registers. LLVM automatically sets it when using a generic CPU, but not when `-C target-cpu` is specified. This will result either in backend legalization crashes, or code unexpectedly using ymm instead of zmm registers. For now, make sure that `avx512*` features imply `evex512`. Long term we'll probably have to deal with the AVX10 mess somehow. --- compiler/rustc_codegen_llvm/src/llvm_util.rs | 4 ++++ tests/ui/asm/x86_64/evex512-implicit-feature.rs | 15 +++++++++++++++ 2 files changed, 19 insertions(+) create mode 100644 tests/ui/asm/x86_64/evex512-implicit-feature.rs diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs index e48479c8da27..54e8ed85e325 100644 --- a/compiler/rustc_codegen_llvm/src/llvm_util.rs +++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs @@ -266,6 +266,10 @@ pub fn to_llvm_features<'a>(sess: &Session, s: &'a str) -> LLVMFeature<'a> { ("riscv32" | "riscv64", "fast-unaligned-access") if get_version().0 <= 17 => { LLVMFeature::new("unaligned-scalar-mem") } + // For LLVM 18, enable the evex512 target feature if a avx512 target feature is enabled. + ("x86", s) if get_version().0 >= 18 && s.starts_with("avx512") => { + LLVMFeature::with_dependency(s, TargetFeatureFoldStrength::EnableOnly("evex512")) + } (_, s) => LLVMFeature::new(s), } } diff --git a/tests/ui/asm/x86_64/evex512-implicit-feature.rs b/tests/ui/asm/x86_64/evex512-implicit-feature.rs new file mode 100644 index 000000000000..a15060857ecc --- /dev/null +++ b/tests/ui/asm/x86_64/evex512-implicit-feature.rs @@ -0,0 +1,15 @@ +// build-pass +// only-x86_64 +// compile-flags: --crate-type=lib -C target-cpu=skylake + +#![feature(avx512_target_feature)] +#![feature(stdarch_x86_avx512)] + +use std::arch::x86_64::*; + +#[target_feature(enable = "avx512f")] +#[no_mangle] +pub unsafe fn test(res: *mut f64, p: *const f64) { + let arg = _mm512_load_pd(p); + _mm512_store_pd(res, _mm512_fmaddsub_pd(arg, arg, arg)); +} From ddec8c5edc488e3eec27ed59a4d8e5dbaad4130f Mon Sep 17 00:00:00 2001 From: Urgau Date: Wed, 14 Feb 2024 19:12:19 +0100 Subject: [PATCH 10/17] Ignore unsized types when trying to determine the size of a type --- compiler/rustc_lint/src/reference_casting.rs | 7 +++++++ tests/ui/lint/reference_casting.rs | 5 +++++ 2 files changed, 12 insertions(+) diff --git a/compiler/rustc_lint/src/reference_casting.rs b/compiler/rustc_lint/src/reference_casting.rs index 519ab8bd50fe..f386db9d8dbc 100644 --- a/compiler/rustc_lint/src/reference_casting.rs +++ b/compiler/rustc_lint/src/reference_casting.rs @@ -207,6 +207,13 @@ fn is_cast_to_bigger_memory_layout<'tcx>( } let from_layout = cx.layout_of(*inner_start_ty).ok()?; + + // if the type isn't sized, we bail out, instead of potentially giving + // the user a meaningless warning. + if from_layout.is_unsized() { + return None; + } + let alloc_layout = cx.layout_of(alloc_ty).ok()?; let to_layout = cx.layout_of(*inner_end_ty).ok()?; diff --git a/tests/ui/lint/reference_casting.rs b/tests/ui/lint/reference_casting.rs index 63541943d65c..e5d84e464fdc 100644 --- a/tests/ui/lint/reference_casting.rs +++ b/tests/ui/lint/reference_casting.rs @@ -239,6 +239,11 @@ unsafe fn bigger_layout() { //~^ ERROR casting references to a bigger memory layout } + { + let x: Box = Box::new(0i32); + let _z = unsafe { &*(&*x as *const dyn Send as *const i32) }; + } + unsafe fn from_ref(this: &i32) -> &i64 { &*(this as *const i32 as *const i64) } From 8d4d572e4d8e41f9963dad997214a54df05baabf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Wed, 14 Feb 2024 19:18:28 +0000 Subject: [PATCH 11/17] Fix msg for verbose suggestions with confusable capitalization When encountering a verbose/multipart suggestion that has changes that are only caused by different capitalization of ASCII letters that have little differenciation, expand the message to highlight that fact (like we already do for inline suggestions). The logic to do this was already present, but implemented incorrectly. --- compiler/rustc_errors/src/emitter.rs | 19 ++++++++++--------- compiler/rustc_errors/src/lib.rs | 3 ++- .../tests/ui/match_str_case_mismatch.stderr | 2 +- tests/ui/error-codes/E0423.stderr | 2 +- tests/ui/parser/kw-in-trait-bounds.stderr | 8 ++++---- .../recover-fn-trait-from-fn-kw.stderr | 4 ++-- .../typod-const-in-const-param-def.stderr | 8 ++++---- .../assoc-ct-for-assoc-method.stderr | 2 +- .../suggestions/bool_typo_err_suggest.stderr | 2 +- 9 files changed, 26 insertions(+), 24 deletions(-) diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs index b9e92dbb31c6..edcc23db6de3 100644 --- a/compiler/rustc_errors/src/emitter.rs +++ b/compiler/rustc_errors/src/emitter.rs @@ -1742,9 +1742,17 @@ impl HumanEmitter { buffer.append(0, level.to_str(), Style::Level(*level)); buffer.append(0, ": ", Style::HeaderMsg); + let mut msg = vec![(suggestion.msg.to_owned(), Style::NoStyle)]; + if suggestions + .iter() + .take(MAX_SUGGESTIONS) + .any(|(_, _, _, only_capitalization)| *only_capitalization) + { + msg.push((" (notice the capitalization difference)".into(), Style::NoStyle)); + } self.msgs_to_buffer( &mut buffer, - &[(suggestion.msg.to_owned(), Style::NoStyle)], + &msg, args, max_line_num_len, "suggestion", @@ -1753,12 +1761,8 @@ impl HumanEmitter { let mut row_num = 2; draw_col_separator_no_space(&mut buffer, 1, max_line_num_len + 1); - let mut notice_capitalization = false; - for (complete, parts, highlights, only_capitalization) in - suggestions.iter().take(MAX_SUGGESTIONS) - { + for (complete, parts, highlights, _) in suggestions.iter().take(MAX_SUGGESTIONS) { debug!(?complete, ?parts, ?highlights); - notice_capitalization |= only_capitalization; let has_deletion = parts.iter().any(|p| p.is_deletion(sm)); let is_multiline = complete.lines().count() > 1; @@ -2057,9 +2061,6 @@ impl HumanEmitter { let others = suggestions.len() - MAX_SUGGESTIONS; let msg = format!("and {} other candidate{}", others, pluralize!(others)); buffer.puts(row_num, max_line_num_len + 3, &msg, Style::NoStyle); - } else if notice_capitalization { - let msg = "notice the capitalization difference"; - buffer.puts(row_num, max_line_num_len + 3, msg, Style::NoStyle); } emit_to_destination(&buffer.render(), level, &mut self.dst, self.short_message)?; Ok(()) diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index da9ef6627bea..2a0eddf6a0f3 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -319,7 +319,9 @@ impl CodeSuggestion { // We need to keep track of the difference between the existing code and the added // or deleted code in order to point at the correct column *after* substitution. let mut acc = 0; + let mut only_capitalization = false; for part in &substitution.parts { + only_capitalization |= is_case_difference(sm, &part.snippet, part.span); let cur_lo = sm.lookup_char_pos(part.span.lo()); if prev_hi.line == cur_lo.line { let mut count = @@ -392,7 +394,6 @@ impl CodeSuggestion { } } highlights.push(std::mem::take(&mut line_highlight)); - let only_capitalization = is_case_difference(sm, &buf, bounding_span); // if the replacement already ends with a newline, don't print the next line if !buf.ends_with('\n') { push_trailing(&mut buf, prev_line.as_ref(), &prev_hi, None); diff --git a/src/tools/clippy/tests/ui/match_str_case_mismatch.stderr b/src/tools/clippy/tests/ui/match_str_case_mismatch.stderr index f799a4698b94..b178fb7512cd 100644 --- a/src/tools/clippy/tests/ui/match_str_case_mismatch.stderr +++ b/src/tools/clippy/tests/ui/match_str_case_mismatch.stderr @@ -17,7 +17,7 @@ error: this `match` arm has a differing case than its expression LL | "~!@#$%^&*()-_=+Foo" => {}, | ^^^^^^^^^^^^^^^^^^^^ | -help: consider changing the case of this arm to respect `to_ascii_lowercase` +help: consider changing the case of this arm to respect `to_ascii_lowercase` (notice the capitalization difference) | LL | "~!@#$%^&*()-_=+foo" => {}, | ~~~~~~~~~~~~~~~~~~~~ diff --git a/tests/ui/error-codes/E0423.stderr b/tests/ui/error-codes/E0423.stderr index ac70d905d353..dd7a5b034c58 100644 --- a/tests/ui/error-codes/E0423.stderr +++ b/tests/ui/error-codes/E0423.stderr @@ -53,7 +53,7 @@ help: use struct literal syntax instead | LL | let f = Foo { a: val }; | ~~~~~~~~~~~~~~ -help: a function with a similar name exists +help: a function with a similar name exists (notice the capitalization difference) | LL | let f = foo(); | ~~~ diff --git a/tests/ui/parser/kw-in-trait-bounds.stderr b/tests/ui/parser/kw-in-trait-bounds.stderr index 2d3aad4d6baf..3c54e0319503 100644 --- a/tests/ui/parser/kw-in-trait-bounds.stderr +++ b/tests/ui/parser/kw-in-trait-bounds.stderr @@ -4,7 +4,7 @@ error: expected identifier, found keyword `fn` LL | fn _f(_: impl fn(), _: &dyn fn()) | ^^ | -help: use `Fn` to refer to the trait +help: use `Fn` to refer to the trait (notice the capitalization difference) | LL | fn _f(_: impl fn(), _: &dyn fn()) | ~~ @@ -15,7 +15,7 @@ error: expected identifier, found keyword `fn` LL | fn _f(_: impl fn(), _: &dyn fn()) | ^^ | -help: use `Fn` to refer to the trait +help: use `Fn` to refer to the trait (notice the capitalization difference) | LL | fn _f(_: impl Fn(), _: &dyn fn()) | ~~ @@ -26,7 +26,7 @@ error: expected identifier, found keyword `fn` LL | fn _f(_: impl fn(), _: &dyn fn()) | ^^ | -help: use `Fn` to refer to the trait +help: use `Fn` to refer to the trait (notice the capitalization difference) | LL | fn _f(_: impl fn(), _: &dyn Fn()) | ~~ @@ -37,7 +37,7 @@ error: expected identifier, found keyword `fn` LL | G: fn(), | ^^ | -help: use `Fn` to refer to the trait +help: use `Fn` to refer to the trait (notice the capitalization difference) | LL | G: Fn(), | ~~ diff --git a/tests/ui/parser/recover/recover-fn-trait-from-fn-kw.stderr b/tests/ui/parser/recover/recover-fn-trait-from-fn-kw.stderr index 17138a6f0792..aee31d08fe0e 100644 --- a/tests/ui/parser/recover/recover-fn-trait-from-fn-kw.stderr +++ b/tests/ui/parser/recover/recover-fn-trait-from-fn-kw.stderr @@ -4,7 +4,7 @@ error: expected identifier, found keyword `fn` LL | fn foo(_: impl fn() -> i32) {} | ^^ | -help: use `Fn` to refer to the trait +help: use `Fn` to refer to the trait (notice the capitalization difference) | LL | fn foo(_: impl Fn() -> i32) {} | ~~ @@ -15,7 +15,7 @@ error: expected identifier, found keyword `fn` LL | fn foo2(_: T) {} | ^^ | -help: use `Fn` to refer to the trait +help: use `Fn` to refer to the trait (notice the capitalization difference) | LL | fn foo2(_: T) {} | ~~ diff --git a/tests/ui/parser/typod-const-in-const-param-def.stderr b/tests/ui/parser/typod-const-in-const-param-def.stderr index 75d73c6ea878..80c0f1deae6f 100644 --- a/tests/ui/parser/typod-const-in-const-param-def.stderr +++ b/tests/ui/parser/typod-const-in-const-param-def.stderr @@ -4,7 +4,7 @@ error: `const` keyword was mistyped as `Const` LL | pub fn foo() {} | ^^^^^ | -help: use the `const` keyword +help: use the `const` keyword (notice the capitalization difference) | LL | pub fn foo() {} | ~~~~~ @@ -15,7 +15,7 @@ error: `const` keyword was mistyped as `Const` LL | pub fn baz() {} | ^^^^^ | -help: use the `const` keyword +help: use the `const` keyword (notice the capitalization difference) | LL | pub fn baz() {} | ~~~~~ @@ -26,7 +26,7 @@ error: `const` keyword was mistyped as `Const` LL | pub fn qux() {} | ^^^^^ | -help: use the `const` keyword +help: use the `const` keyword (notice the capitalization difference) | LL | pub fn qux() {} | ~~~~~ @@ -37,7 +37,7 @@ error: `const` keyword was mistyped as `Const` LL | pub fn quux() {} | ^^^^^ | -help: use the `const` keyword +help: use the `const` keyword (notice the capitalization difference) | LL | pub fn quux() {} | ~~~~~ diff --git a/tests/ui/suggestions/assoc-ct-for-assoc-method.stderr b/tests/ui/suggestions/assoc-ct-for-assoc-method.stderr index 211cb1584ad7..8f00a72f1e81 100644 --- a/tests/ui/suggestions/assoc-ct-for-assoc-method.stderr +++ b/tests/ui/suggestions/assoc-ct-for-assoc-method.stderr @@ -8,7 +8,7 @@ LL | let x: i32 = MyS::foo; | = note: expected type `i32` found fn item `fn() -> MyS {MyS::foo}` -help: try referring to the associated const `FOO` instead +help: try referring to the associated const `FOO` instead (notice the capitalization difference) | LL | let x: i32 = MyS::FOO; | ~~~ diff --git a/tests/ui/suggestions/bool_typo_err_suggest.stderr b/tests/ui/suggestions/bool_typo_err_suggest.stderr index 52bde07ca077..8d59ed63e543 100644 --- a/tests/ui/suggestions/bool_typo_err_suggest.stderr +++ b/tests/ui/suggestions/bool_typo_err_suggest.stderr @@ -15,7 +15,7 @@ error[E0425]: cannot find value `False` in this scope LL | let y = False; | ^^^^^ not found in this scope | -help: you may want to use a bool value instead +help: you may want to use a bool value instead (notice the capitalization difference) | LL | let y = false; | ~~~~~ From c1bb352c8bd3457f16053f3d6a3d32b63b55cbbe Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 14 Feb 2024 21:04:51 +0000 Subject: [PATCH 12/17] Continue compilation even if inherent impl checks fail --- compiler/rustc_hir_analysis/src/lib.rs | 5 +- .../ui/const-generics/wrong-normalization.rs | 1 + .../const-generics/wrong-normalization.stderr | 16 +- tests/ui/impl-trait/where-allowed.rs | 6 + tests/ui/impl-trait/where-allowed.stderr | 145 +++++++++++++----- tests/ui/issues/issue-4265.rs | 1 + tests/ui/issues/issue-4265.stderr | 26 +++- tests/ui/kinds-of-primitive-impl.rs | 2 +- tests/ui/kinds-of-primitive-impl.stderr | 18 ++- .../impl-item-type-no-body-semantic-fail.rs | 2 + ...mpl-item-type-no-body-semantic-fail.stderr | 40 ++++- tests/ui/traits/issue-33140.rs | 2 + tests/ui/traits/issue-33140.stderr | 40 ++++- 13 files changed, 244 insertions(+), 60 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs index 1cd77050217a..33092825e891 100644 --- a/compiler/rustc_hir_analysis/src/lib.rs +++ b/compiler/rustc_hir_analysis/src/lib.rs @@ -178,8 +178,9 @@ pub fn check_crate(tcx: TyCtxt<'_>) -> Result<(), ErrorGuaranteed> { let _ = tcx.ensure().coherent_trait(trait_def_id); } // these queries are executed for side-effects (error reporting): - res.and(tcx.ensure().crate_inherent_impls(())) - .and(tcx.ensure().crate_inherent_impls_overlap_check(())) + let _ = tcx.ensure().crate_inherent_impls(()); + let _ = tcx.ensure().crate_inherent_impls_overlap_check(()); + res })?; if tcx.features().rustc_attrs { diff --git a/tests/ui/const-generics/wrong-normalization.rs b/tests/ui/const-generics/wrong-normalization.rs index f1ce317b3f78..8b2323e3d479 100644 --- a/tests/ui/const-generics/wrong-normalization.rs +++ b/tests/ui/const-generics/wrong-normalization.rs @@ -15,5 +15,6 @@ pub struct I8; impl as Identity>::Identity { //~^ ERROR no nominal type found for inherent implementation +//~| ERROR no associated item named `MIN` found for type `i8` pub fn foo(&self) {} } diff --git a/tests/ui/const-generics/wrong-normalization.stderr b/tests/ui/const-generics/wrong-normalization.stderr index 2f8dfc895b27..379a5593dd64 100644 --- a/tests/ui/const-generics/wrong-normalization.stderr +++ b/tests/ui/const-generics/wrong-normalization.stderr @@ -6,6 +6,18 @@ LL | impl as Identity>::Identity { | = note: either implement a trait on it or create a newtype to wrap it instead -error: aborting due to 1 previous error +error[E0599]: no associated item named `MIN` found for type `i8` in the current scope + --> $DIR/wrong-normalization.rs:16:15 + | +LL | impl as Identity>::Identity { + | ^^^ associated item not found in `i8` + | +help: you are looking for the module in `std`, not the primitive type + | +LL | impl as Identity>::Identity { + | +++++ + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0118`. +Some errors have detailed explanations: E0118, E0599. +For more information about an error, try `rustc --explain E0118`. diff --git a/tests/ui/impl-trait/where-allowed.rs b/tests/ui/impl-trait/where-allowed.rs index 5ce63db684f3..505e2d6c171f 100644 --- a/tests/ui/impl-trait/where-allowed.rs +++ b/tests/ui/impl-trait/where-allowed.rs @@ -44,6 +44,7 @@ fn in_dyn_Fn_parameter_in_return() -> &'static dyn Fn(impl Debug) { panic!() } // Allowed fn in_dyn_Fn_return_in_return() -> &'static dyn Fn() -> impl Debug { panic!() } +//~^ ERROR: type annotations needed // Disallowed fn in_impl_Fn_parameter_in_parameters(_: &impl Fn(impl Debug)) { panic!() } @@ -58,9 +59,11 @@ fn in_impl_Fn_return_in_parameters(_: &impl Fn() -> impl Debug) { panic!() } fn in_impl_Fn_parameter_in_return() -> &'static impl Fn(impl Debug) { panic!() } //~^ ERROR `impl Trait` is not allowed in the parameters of `Fn` trait bounds //~| ERROR nested `impl Trait` is not allowed +//~| ERROR: type annotations needed // Allowed fn in_impl_Fn_return_in_return() -> &'static impl Fn() -> impl Debug { panic!() } +//~^ ERROR: type annotations needed // Disallowed fn in_Fn_parameter_in_generics (_: F) { panic!() } @@ -77,6 +80,7 @@ fn in_impl_Trait_in_parameters(_: impl Iterator) { panic!( // Allowed fn in_impl_Trait_in_return() -> impl IntoIterator { vec![vec![0; 10], vec![12; 7], vec![8; 3]] + //~^ ERROR: no function or associated item named `into_vec` found for slice `[_]` } // Disallowed @@ -118,11 +122,13 @@ trait DummyTrait { impl DummyTrait for () { type Out = impl Debug; //~^ ERROR `impl Trait` in associated types is unstable + //~| ERROR unconstrained opaque type fn in_trait_impl_parameter(_: impl Debug) { } // Allowed fn in_trait_impl_return() -> impl Debug { () } + //~^ ERROR `in_trait_impl_return` has an incompatible type for trait // Allowed } diff --git a/tests/ui/impl-trait/where-allowed.stderr b/tests/ui/impl-trait/where-allowed.stderr index 3e1d4e22272d..c22312cce197 100644 --- a/tests/ui/impl-trait/where-allowed.stderr +++ b/tests/ui/impl-trait/where-allowed.stderr @@ -1,5 +1,5 @@ error[E0666]: nested `impl Trait` is not allowed - --> $DIR/where-allowed.rs:49:51 + --> $DIR/where-allowed.rs:50:51 | LL | fn in_impl_Fn_parameter_in_parameters(_: &impl Fn(impl Debug)) { panic!() } | --------^^^^^^^^^^- @@ -8,7 +8,7 @@ LL | fn in_impl_Fn_parameter_in_parameters(_: &impl Fn(impl Debug)) { panic!() } | outer `impl Trait` error[E0666]: nested `impl Trait` is not allowed - --> $DIR/where-allowed.rs:58:57 + --> $DIR/where-allowed.rs:59:57 | LL | fn in_impl_Fn_parameter_in_return() -> &'static impl Fn(impl Debug) { panic!() } | --------^^^^^^^^^^- @@ -17,7 +17,7 @@ LL | fn in_impl_Fn_parameter_in_return() -> &'static impl Fn(impl Debug) { panic | outer `impl Trait` error[E0658]: `impl Trait` in associated types is unstable - --> $DIR/where-allowed.rs:119:16 + --> $DIR/where-allowed.rs:123:16 | LL | type Out = impl Debug; | ^^^^^^^^^^ @@ -27,7 +27,7 @@ LL | type Out = impl Debug; = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: `impl Trait` in type aliases is unstable - --> $DIR/where-allowed.rs:154:23 + --> $DIR/where-allowed.rs:160:23 | LL | type InTypeAlias = impl Debug; | ^^^^^^^^^^ @@ -37,7 +37,7 @@ LL | type InTypeAlias = impl Debug; = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: `impl Trait` in type aliases is unstable - --> $DIR/where-allowed.rs:157:39 + --> $DIR/where-allowed.rs:163:39 | LL | type InReturnInTypeAlias = fn() -> impl Debug; | ^^^^^^^^^^ @@ -103,7 +103,7 @@ LL | fn in_dyn_Fn_parameter_in_return() -> &'static dyn Fn(impl Debug) { panic!( = note: `impl Trait` is only allowed in arguments and return types of functions and methods error[E0562]: `impl Trait` is not allowed in the parameters of `Fn` trait bounds - --> $DIR/where-allowed.rs:49:51 + --> $DIR/where-allowed.rs:50:51 | LL | fn in_impl_Fn_parameter_in_parameters(_: &impl Fn(impl Debug)) { panic!() } | ^^^^^^^^^^ @@ -111,7 +111,7 @@ LL | fn in_impl_Fn_parameter_in_parameters(_: &impl Fn(impl Debug)) { panic!() } = note: `impl Trait` is only allowed in arguments and return types of functions and methods error[E0562]: `impl Trait` is not allowed in the return type of `Fn` trait bounds - --> $DIR/where-allowed.rs:54:53 + --> $DIR/where-allowed.rs:55:53 | LL | fn in_impl_Fn_return_in_parameters(_: &impl Fn() -> impl Debug) { panic!() } | ^^^^^^^^^^ @@ -119,7 +119,7 @@ LL | fn in_impl_Fn_return_in_parameters(_: &impl Fn() -> impl Debug) { panic!() = note: `impl Trait` is only allowed in arguments and return types of functions and methods error[E0562]: `impl Trait` is not allowed in the parameters of `Fn` trait bounds - --> $DIR/where-allowed.rs:58:57 + --> $DIR/where-allowed.rs:59:57 | LL | fn in_impl_Fn_parameter_in_return() -> &'static impl Fn(impl Debug) { panic!() } | ^^^^^^^^^^ @@ -127,7 +127,7 @@ LL | fn in_impl_Fn_parameter_in_return() -> &'static impl Fn(impl Debug) { panic = note: `impl Trait` is only allowed in arguments and return types of functions and methods error[E0562]: `impl Trait` is not allowed in the parameters of `Fn` trait bounds - --> $DIR/where-allowed.rs:66:38 + --> $DIR/where-allowed.rs:69:38 | LL | fn in_Fn_parameter_in_generics (_: F) { panic!() } | ^^^^^^^^^^ @@ -135,7 +135,7 @@ LL | fn in_Fn_parameter_in_generics (_: F) { panic!() } = note: `impl Trait` is only allowed in arguments and return types of functions and methods error[E0562]: `impl Trait` is not allowed in the return type of `Fn` trait bounds - --> $DIR/where-allowed.rs:70:40 + --> $DIR/where-allowed.rs:73:40 | LL | fn in_Fn_return_in_generics impl Debug> (_: F) { panic!() } | ^^^^^^^^^^ @@ -143,7 +143,7 @@ LL | fn in_Fn_return_in_generics impl Debug> (_: F) { panic!() } = note: `impl Trait` is only allowed in arguments and return types of functions and methods error[E0562]: `impl Trait` is not allowed in field types - --> $DIR/where-allowed.rs:83:32 + --> $DIR/where-allowed.rs:87:32 | LL | struct InBraceStructField { x: impl Debug } | ^^^^^^^^^^ @@ -151,7 +151,7 @@ LL | struct InBraceStructField { x: impl Debug } = note: `impl Trait` is only allowed in arguments and return types of functions and methods error[E0562]: `impl Trait` is not allowed in field types - --> $DIR/where-allowed.rs:87:41 + --> $DIR/where-allowed.rs:91:41 | LL | struct InAdtInBraceStructField { x: Vec } | ^^^^^^^^^^ @@ -159,7 +159,7 @@ LL | struct InAdtInBraceStructField { x: Vec } = note: `impl Trait` is only allowed in arguments and return types of functions and methods error[E0562]: `impl Trait` is not allowed in field types - --> $DIR/where-allowed.rs:91:27 + --> $DIR/where-allowed.rs:95:27 | LL | struct InTupleStructField(impl Debug); | ^^^^^^^^^^ @@ -167,7 +167,7 @@ LL | struct InTupleStructField(impl Debug); = note: `impl Trait` is only allowed in arguments and return types of functions and methods error[E0562]: `impl Trait` is not allowed in field types - --> $DIR/where-allowed.rs:96:25 + --> $DIR/where-allowed.rs:100:25 | LL | InBraceVariant { x: impl Debug }, | ^^^^^^^^^^ @@ -175,7 +175,7 @@ LL | InBraceVariant { x: impl Debug }, = note: `impl Trait` is only allowed in arguments and return types of functions and methods error[E0562]: `impl Trait` is not allowed in field types - --> $DIR/where-allowed.rs:98:20 + --> $DIR/where-allowed.rs:102:20 | LL | InTupleVariant(impl Debug), | ^^^^^^^^^^ @@ -183,7 +183,7 @@ LL | InTupleVariant(impl Debug), = note: `impl Trait` is only allowed in arguments and return types of functions and methods error[E0562]: `impl Trait` is not allowed in `extern fn` parameters - --> $DIR/where-allowed.rs:138:33 + --> $DIR/where-allowed.rs:144:33 | LL | fn in_foreign_parameters(_: impl Debug); | ^^^^^^^^^^ @@ -191,7 +191,7 @@ LL | fn in_foreign_parameters(_: impl Debug); = note: `impl Trait` is only allowed in arguments and return types of functions and methods error[E0562]: `impl Trait` is not allowed in `extern fn` return types - --> $DIR/where-allowed.rs:141:31 + --> $DIR/where-allowed.rs:147:31 | LL | fn in_foreign_return() -> impl Debug; | ^^^^^^^^^^ @@ -199,7 +199,7 @@ LL | fn in_foreign_return() -> impl Debug; = note: `impl Trait` is only allowed in arguments and return types of functions and methods error[E0562]: `impl Trait` is not allowed in `fn` pointer return types - --> $DIR/where-allowed.rs:157:39 + --> $DIR/where-allowed.rs:163:39 | LL | type InReturnInTypeAlias = fn() -> impl Debug; | ^^^^^^^^^^ @@ -207,7 +207,7 @@ LL | type InReturnInTypeAlias = fn() -> impl Debug; = note: `impl Trait` is only allowed in arguments and return types of functions and methods error[E0562]: `impl Trait` is not allowed in traits - --> $DIR/where-allowed.rs:162:16 + --> $DIR/where-allowed.rs:168:16 | LL | impl PartialEq for () { | ^^^^^^^^^^ @@ -215,7 +215,7 @@ LL | impl PartialEq for () { = note: `impl Trait` is only allowed in arguments and return types of functions and methods error[E0562]: `impl Trait` is not allowed in impl headers - --> $DIR/where-allowed.rs:167:24 + --> $DIR/where-allowed.rs:173:24 | LL | impl PartialEq<()> for impl Debug { | ^^^^^^^^^^ @@ -223,7 +223,7 @@ LL | impl PartialEq<()> for impl Debug { = note: `impl Trait` is only allowed in arguments and return types of functions and methods error[E0562]: `impl Trait` is not allowed in impl headers - --> $DIR/where-allowed.rs:172:6 + --> $DIR/where-allowed.rs:178:6 | LL | impl impl Debug { | ^^^^^^^^^^ @@ -231,7 +231,7 @@ LL | impl impl Debug { = note: `impl Trait` is only allowed in arguments and return types of functions and methods error[E0562]: `impl Trait` is not allowed in impl headers - --> $DIR/where-allowed.rs:178:24 + --> $DIR/where-allowed.rs:184:24 | LL | impl InInherentImplAdt { | ^^^^^^^^^^ @@ -239,7 +239,7 @@ LL | impl InInherentImplAdt { = note: `impl Trait` is only allowed in arguments and return types of functions and methods error[E0562]: `impl Trait` is not allowed in bounds - --> $DIR/where-allowed.rs:184:11 + --> $DIR/where-allowed.rs:190:11 | LL | where impl Debug: Debug | ^^^^^^^^^^ @@ -247,7 +247,7 @@ LL | where impl Debug: Debug = note: `impl Trait` is only allowed in arguments and return types of functions and methods error[E0562]: `impl Trait` is not allowed in bounds - --> $DIR/where-allowed.rs:191:15 + --> $DIR/where-allowed.rs:197:15 | LL | where Vec: Debug | ^^^^^^^^^^ @@ -255,7 +255,7 @@ LL | where Vec: Debug = note: `impl Trait` is only allowed in arguments and return types of functions and methods error[E0562]: `impl Trait` is not allowed in bounds - --> $DIR/where-allowed.rs:198:24 + --> $DIR/where-allowed.rs:204:24 | LL | where T: PartialEq | ^^^^^^^^^^ @@ -263,7 +263,7 @@ LL | where T: PartialEq = note: `impl Trait` is only allowed in arguments and return types of functions and methods error[E0562]: `impl Trait` is not allowed in the parameters of `Fn` trait bounds - --> $DIR/where-allowed.rs:205:17 + --> $DIR/where-allowed.rs:211:17 | LL | where T: Fn(impl Debug) | ^^^^^^^^^^ @@ -271,7 +271,7 @@ LL | where T: Fn(impl Debug) = note: `impl Trait` is only allowed in arguments and return types of functions and methods error[E0562]: `impl Trait` is not allowed in the return type of `Fn` trait bounds - --> $DIR/where-allowed.rs:212:22 + --> $DIR/where-allowed.rs:218:22 | LL | where T: Fn() -> impl Debug | ^^^^^^^^^^ @@ -279,7 +279,7 @@ LL | where T: Fn() -> impl Debug = note: `impl Trait` is only allowed in arguments and return types of functions and methods error[E0562]: `impl Trait` is not allowed in generic parameter defaults - --> $DIR/where-allowed.rs:218:40 + --> $DIR/where-allowed.rs:224:40 | LL | struct InStructGenericParamDefault(T); | ^^^^^^^^^^ @@ -287,7 +287,7 @@ LL | struct InStructGenericParamDefault(T); = note: `impl Trait` is only allowed in arguments and return types of functions and methods error[E0562]: `impl Trait` is not allowed in generic parameter defaults - --> $DIR/where-allowed.rs:222:36 + --> $DIR/where-allowed.rs:228:36 | LL | enum InEnumGenericParamDefault { Variant(T) } | ^^^^^^^^^^ @@ -295,7 +295,7 @@ LL | enum InEnumGenericParamDefault { Variant(T) } = note: `impl Trait` is only allowed in arguments and return types of functions and methods error[E0562]: `impl Trait` is not allowed in generic parameter defaults - --> $DIR/where-allowed.rs:226:38 + --> $DIR/where-allowed.rs:232:38 | LL | trait InTraitGenericParamDefault {} | ^^^^^^^^^^ @@ -303,7 +303,7 @@ LL | trait InTraitGenericParamDefault {} = note: `impl Trait` is only allowed in arguments and return types of functions and methods error[E0562]: `impl Trait` is not allowed in generic parameter defaults - --> $DIR/where-allowed.rs:230:41 + --> $DIR/where-allowed.rs:236:41 | LL | type InTypeAliasGenericParamDefault = T; | ^^^^^^^^^^ @@ -311,7 +311,7 @@ LL | type InTypeAliasGenericParamDefault = T; = note: `impl Trait` is only allowed in arguments and return types of functions and methods error[E0562]: `impl Trait` is not allowed in generic parameter defaults - --> $DIR/where-allowed.rs:234:11 + --> $DIR/where-allowed.rs:240:11 | LL | impl T {} | ^^^^^^^^^^ @@ -319,7 +319,7 @@ LL | impl T {} = note: `impl Trait` is only allowed in arguments and return types of functions and methods error[E0562]: `impl Trait` is not allowed in generic parameter defaults - --> $DIR/where-allowed.rs:241:40 + --> $DIR/where-allowed.rs:247:40 | LL | fn in_method_generic_param_default(_: T) {} | ^^^^^^^^^^ @@ -327,7 +327,7 @@ LL | fn in_method_generic_param_default(_: T) {} = note: `impl Trait` is only allowed in arguments and return types of functions and methods error[E0562]: `impl Trait` is not allowed in the type of variable bindings - --> $DIR/where-allowed.rs:247:29 + --> $DIR/where-allowed.rs:253:29 | LL | let _in_local_variable: impl Fn() = || {}; | ^^^^^^^^^ @@ -335,7 +335,7 @@ LL | let _in_local_variable: impl Fn() = || {}; = note: `impl Trait` is only allowed in arguments and return types of functions and methods error[E0562]: `impl Trait` is not allowed in closure return types - --> $DIR/where-allowed.rs:249:46 + --> $DIR/where-allowed.rs:255:46 | LL | let _in_return_in_local_variable = || -> impl Fn() { || {} }; | ^^^^^^^^^ @@ -343,7 +343,7 @@ LL | let _in_return_in_local_variable = || -> impl Fn() { || {} }; = note: `impl Trait` is only allowed in arguments and return types of functions and methods error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions - --> $DIR/where-allowed.rs:234:7 + --> $DIR/where-allowed.rs:240:7 | LL | impl T {} | ^^^^^^^^^^^^^^ @@ -353,7 +353,7 @@ LL | impl T {} = note: `#[deny(invalid_type_param_default)]` on by default error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions - --> $DIR/where-allowed.rs:241:36 + --> $DIR/where-allowed.rs:247:36 | LL | fn in_method_generic_param_default(_: T) {} | ^^^^^^^^^^^^^^ @@ -362,14 +362,77 @@ LL | fn in_method_generic_param_default(_: T) {} = note: for more information, see issue #36887 error[E0118]: no nominal type found for inherent implementation - --> $DIR/where-allowed.rs:234:1 + --> $DIR/where-allowed.rs:240:1 | LL | impl T {} | ^^^^^^^^^^^^^^^^^^^^^^^ impl requires a nominal type | = note: either implement a trait on it or create a newtype to wrap it instead -error: aborting due to 45 previous errors +error[E0283]: type annotations needed + --> $DIR/where-allowed.rs:46:57 + | +LL | fn in_dyn_Fn_return_in_return() -> &'static dyn Fn() -> impl Debug { panic!() } + | ^^^^^^^^^^ cannot infer type + | + = note: cannot satisfy `_: Debug` + +error[E0282]: type annotations needed + --> $DIR/where-allowed.rs:59:49 + | +LL | fn in_impl_Fn_parameter_in_return() -> &'static impl Fn(impl Debug) { panic!() } + | ^^^^^^^^^^^^^^^^^^^ cannot infer type + +error[E0283]: type annotations needed + --> $DIR/where-allowed.rs:65:46 + | +LL | fn in_impl_Fn_return_in_return() -> &'static impl Fn() -> impl Debug { panic!() } + | ^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type + | + = note: multiple `impl`s satisfying `_: Fn()` found in the following crates: `alloc`, `core`: + - impl Fn for &F + where A: Tuple, F: Fn, F: ?Sized; + - impl Fn for Box + where Args: Tuple, F: Fn, A: Allocator, F: ?Sized; + +error[E0599]: no function or associated item named `into_vec` found for slice `[_]` in the current scope + --> $DIR/where-allowed.rs:82:5 + | +LL | vec![vec![0; 10], vec![12; 7], vec![8; 3]] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function or associated item not found in `[_]` + | + = note: this error originates in the macro `vec` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0053]: method `in_trait_impl_return` has an incompatible type for trait + --> $DIR/where-allowed.rs:130:34 + | +LL | type Out = impl Debug; + | ---------- the expected opaque type +... +LL | fn in_trait_impl_return() -> impl Debug { () } + | ^^^^^^^^^^ + | | + | expected opaque type, found a different opaque type + | help: change the output type to match the trait: `<() as DummyTrait>::Out` + | +note: type in trait + --> $DIR/where-allowed.rs:120:34 + | +LL | fn in_trait_impl_return() -> Self::Out; + | ^^^^^^^^^ + = note: expected signature `fn() -> <() as DummyTrait>::Out` + found signature `fn() -> impl Debug` + = note: distinct uses of `impl Trait` result in different opaque types + +error: unconstrained opaque type + --> $DIR/where-allowed.rs:123:16 + | +LL | type Out = impl Debug; + | ^^^^^^^^^^ + | + = note: `Out` must be used in combination with a concrete type within the same impl + +error: aborting due to 51 previous errors -Some errors have detailed explanations: E0118, E0562, E0658, E0666. -For more information about an error, try `rustc --explain E0118`. +Some errors have detailed explanations: E0053, E0118, E0282, E0283, E0562, E0599, E0658, E0666. +For more information about an error, try `rustc --explain E0053`. diff --git a/tests/ui/issues/issue-4265.rs b/tests/ui/issues/issue-4265.rs index 2596079d3790..99b13283bc97 100644 --- a/tests/ui/issues/issue-4265.rs +++ b/tests/ui/issues/issue-4265.rs @@ -5,6 +5,7 @@ struct Foo { impl Foo { fn bar() { Foo { baz: 0 }.bar(); + //~^ ERROR: no method named `bar` found } fn bar() { //~ ERROR duplicate definitions diff --git a/tests/ui/issues/issue-4265.stderr b/tests/ui/issues/issue-4265.stderr index 48b1c762e19a..23d00aaa44b5 100644 --- a/tests/ui/issues/issue-4265.stderr +++ b/tests/ui/issues/issue-4265.stderr @@ -1,5 +1,5 @@ error[E0592]: duplicate definitions with name `bar` - --> $DIR/issue-4265.rs:10:5 + --> $DIR/issue-4265.rs:11:5 | LL | fn bar() { | -------- other definition for `bar` @@ -7,6 +7,26 @@ LL | fn bar() { LL | fn bar() { | ^^^^^^^^ duplicate definitions for `bar` -error: aborting due to 1 previous error +error[E0599]: no method named `bar` found for struct `Foo` in the current scope + --> $DIR/issue-4265.rs:7:24 + | +LL | struct Foo { + | ---------- method `bar` not found for this struct +... +LL | Foo { baz: 0 }.bar(); + | ---------------^^^-- + | | | + | | this is an associated function, not a method + | help: use associated function syntax instead: `Foo::bar()` + | + = note: found the following associated functions; to be used as methods, functions must have a `self` parameter +note: the candidate is defined in an impl for the type `Foo` + --> $DIR/issue-4265.rs:6:5 + | +LL | fn bar() { + | ^^^^^^^^ + +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0592`. +Some errors have detailed explanations: E0592, E0599. +For more information about an error, try `rustc --explain E0592`. diff --git a/tests/ui/kinds-of-primitive-impl.rs b/tests/ui/kinds-of-primitive-impl.rs index 6a067a9a3609..f1c2ee8e5506 100644 --- a/tests/ui/kinds-of-primitive-impl.rs +++ b/tests/ui/kinds-of-primitive-impl.rs @@ -6,7 +6,7 @@ impl u8 { impl str { //~^ error: cannot define inherent `impl` for primitive types fn foo() {} - fn bar(self) {} + fn bar(self) {} //~ ERROR: size for values of type `str` cannot be known } impl char { diff --git a/tests/ui/kinds-of-primitive-impl.stderr b/tests/ui/kinds-of-primitive-impl.stderr index 21aac58f1f20..1c8c417e88c1 100644 --- a/tests/ui/kinds-of-primitive-impl.stderr +++ b/tests/ui/kinds-of-primitive-impl.stderr @@ -31,6 +31,20 @@ LL | impl &MyType { = help: consider using an extension trait instead = note: you could also try moving the reference to uses of `MyType` (such as `self`) within the implementation -error: aborting due to 4 previous errors +error[E0277]: the size for values of type `str` cannot be known at compilation time + --> $DIR/kinds-of-primitive-impl.rs:9:12 + | +LL | fn bar(self) {} + | ^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `str` + = help: unsized fn params are gated as an unstable feature +help: function arguments must have a statically known size, borrowed types always have a known size + | +LL | fn bar(&self) {} + | + + +error: aborting due to 5 previous errors -For more information about this error, try `rustc --explain E0390`. +Some errors have detailed explanations: E0277, E0390. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/parser/impl-item-type-no-body-semantic-fail.rs b/tests/ui/parser/impl-item-type-no-body-semantic-fail.rs index 5582e82d11d0..bbd207be06db 100644 --- a/tests/ui/parser/impl-item-type-no-body-semantic-fail.rs +++ b/tests/ui/parser/impl-item-type-no-body-semantic-fail.rs @@ -14,8 +14,10 @@ impl X { //~^ ERROR associated type in `impl` without body //~| ERROR bounds on `type`s in `impl`s have no effect //~| ERROR inherent associated types are unstable + //~| ERROR `X: Eq` is not satisfied type W where Self: Eq; //~^ ERROR associated type in `impl` without body //~| ERROR inherent associated types are unstable //~| ERROR duplicate definitions + //~| ERROR `X: Eq` is not satisfied } diff --git a/tests/ui/parser/impl-item-type-no-body-semantic-fail.stderr b/tests/ui/parser/impl-item-type-no-body-semantic-fail.stderr index d23e6027473d..1c71cdacd89b 100644 --- a/tests/ui/parser/impl-item-type-no-body-semantic-fail.stderr +++ b/tests/ui/parser/impl-item-type-no-body-semantic-fail.stderr @@ -35,7 +35,7 @@ LL | type W: Ord where Self: Eq; | ^^^ error: associated type in `impl` without body - --> $DIR/impl-item-type-no-body-semantic-fail.rs:17:5 + --> $DIR/impl-item-type-no-body-semantic-fail.rs:18:5 | LL | type W where Self: Eq; | ^^^^^^^^^^^^^^^^^^^^^- @@ -73,7 +73,7 @@ LL | type W: Ord where Self: Eq; = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: inherent associated types are unstable - --> $DIR/impl-item-type-no-body-semantic-fail.rs:17:5 + --> $DIR/impl-item-type-no-body-semantic-fail.rs:18:5 | LL | type W where Self: Eq; | ^^^^^^^^^^^^^^^^^^^^^^ @@ -83,7 +83,7 @@ LL | type W where Self: Eq; = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0592]: duplicate definitions with name `W` - --> $DIR/impl-item-type-no-body-semantic-fail.rs:17:5 + --> $DIR/impl-item-type-no-body-semantic-fail.rs:18:5 | LL | type W: Ord where Self: Eq; | ------ other definition for `W` @@ -91,7 +91,35 @@ LL | type W: Ord where Self: Eq; LL | type W where Self: Eq; | ^^^^^^ duplicate definitions for `W` -error: aborting due to 11 previous errors +error[E0277]: the trait bound `X: Eq` is not satisfied + --> $DIR/impl-item-type-no-body-semantic-fail.rs:13:23 + | +LL | type W: Ord where Self: Eq; + | ^^^^^^^^ the trait `Eq` is not implemented for `X` + | + = help: see issue #48214 + = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable +help: consider annotating `X` with `#[derive(Eq)]` + | +LL + #[derive(Eq)] +LL | struct X; + | + +error[E0277]: the trait bound `X: Eq` is not satisfied + --> $DIR/impl-item-type-no-body-semantic-fail.rs:18:18 + | +LL | type W where Self: Eq; + | ^^^^^^^^ the trait `Eq` is not implemented for `X` + | + = help: see issue #48214 + = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable +help: consider annotating `X` with `#[derive(Eq)]` + | +LL + #[derive(Eq)] +LL | struct X; + | + +error: aborting due to 13 previous errors -Some errors have detailed explanations: E0592, E0658. -For more information about an error, try `rustc --explain E0592`. +Some errors have detailed explanations: E0277, E0592, E0658. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/issue-33140.rs b/tests/ui/traits/issue-33140.rs index 9bdac4b8375c..01b16f76be56 100644 --- a/tests/ui/traits/issue-33140.rs +++ b/tests/ui/traits/issue-33140.rs @@ -43,5 +43,7 @@ fn main() { assert_eq!(::uvw(), false); assert_eq!(::uvw(), true); assert_eq!(>::abc(), false); + //~^ ERROR: multiple applicable items in scope assert_eq!(>::abc(), true); + //~^ ERROR: multiple applicable items in scope } diff --git a/tests/ui/traits/issue-33140.stderr b/tests/ui/traits/issue-33140.stderr index d31281f7256e..7d7ee96f209b 100644 --- a/tests/ui/traits/issue-33140.stderr +++ b/tests/ui/traits/issue-33140.stderr @@ -25,7 +25,41 @@ LL | fn abc() -> bool { LL | fn abc() -> bool { | ---------------- other definition for `abc` -error: aborting due to 3 previous errors +error[E0034]: multiple applicable items in scope + --> $DIR/issue-33140.rs:45:40 + | +LL | assert_eq!(>::abc(), false); + | ^^^ multiple `abc` found + | +note: candidate #1 is defined in an impl for the type `Foo<(dyn Send + Sync + 'static)>` + --> $DIR/issue-33140.rs:29:5 + | +LL | fn abc() -> bool { + | ^^^^^^^^^^^^^^^^ +note: candidate #2 is defined in an impl for the type `Foo<(dyn Send + Sync + 'static)>` + --> $DIR/issue-33140.rs:35:5 + | +LL | fn abc() -> bool { + | ^^^^^^^^^^^^^^^^ + +error[E0034]: multiple applicable items in scope + --> $DIR/issue-33140.rs:47:40 + | +LL | assert_eq!(>::abc(), true); + | ^^^ multiple `abc` found + | +note: candidate #1 is defined in an impl for the type `Foo<(dyn Send + Sync + 'static)>` + --> $DIR/issue-33140.rs:29:5 + | +LL | fn abc() -> bool { + | ^^^^^^^^^^^^^^^^ +note: candidate #2 is defined in an impl for the type `Foo<(dyn Send + Sync + 'static)>` + --> $DIR/issue-33140.rs:35:5 + | +LL | fn abc() -> bool { + | ^^^^^^^^^^^^^^^^ + +error: aborting due to 5 previous errors -Some errors have detailed explanations: E0119, E0592. -For more information about an error, try `rustc --explain E0119`. +Some errors have detailed explanations: E0034, E0119, E0592. +For more information about an error, try `rustc --explain E0034`. From 8b35f8e41ea501396c9fb77ed785f8beab90e999 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 14 Feb 2024 19:09:25 +1100 Subject: [PATCH 13/17] Remove `LitError::LexerError`. `cook_lexer_literal` can emit an error about an invalid int literal but then return a non-`Err` token. And then `integer_lit` has to account for this to avoid printing a redundant error message. This commit changes `cook_lexer_literal` to return `Err` in that case. Then `integer_lit` doesn't need the special case, and `LitError::LexerError` can be removed. --- compiler/rustc_ast/src/util/literal.rs | 11 +++------- compiler/rustc_parse/src/lexer/mod.rs | 30 +++++++++++++------------- compiler/rustc_session/src/errors.rs | 3 --- 3 files changed, 18 insertions(+), 26 deletions(-) diff --git a/compiler/rustc_ast/src/util/literal.rs b/compiler/rustc_ast/src/util/literal.rs index aaeb1bb9bff8..fbe72252ec91 100644 --- a/compiler/rustc_ast/src/util/literal.rs +++ b/compiler/rustc_ast/src/util/literal.rs @@ -31,7 +31,6 @@ pub fn escape_byte_str_symbol(bytes: &[u8]) -> Symbol { #[derive(Debug)] pub enum LitError { - LexerError, InvalidSuffix, InvalidIntSuffix, InvalidFloatSuffix, @@ -324,11 +323,7 @@ fn integer_lit(symbol: Symbol, suffix: Option) -> Result= base)); - if from_lexer { LitError::LexerError } else { LitError::IntTooLarge(base) } - }) + u128::from_str_radix(s, base) + .map(|i| LitKind::Int(i.into(), ty)) + .map_err(|_| LitError::IntTooLarge(base)) } diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs index 315524526760..aa4456a1c218 100644 --- a/compiler/rustc_parse/src/lexer/mod.rs +++ b/compiler/rustc_parse/src/lexer/mod.rs @@ -16,7 +16,7 @@ use rustc_session::lint::builtin::{ }; use rustc_session::lint::BuiltinLintDiagnostics; use rustc_session::parse::ParseSess; -use rustc_span::symbol::{sym, Symbol}; +use rustc_span::symbol::Symbol; use rustc_span::{edition::Edition, BytePos, Pos, Span}; mod diagnostics; @@ -478,26 +478,26 @@ impl<'sess, 'src> StringReader<'sess, 'src> { } } rustc_lexer::LiteralKind::Int { base, empty_int } => { + let mut kind = token::Integer; if empty_int { let span = self.mk_sp(start, end); self.dcx().emit_err(errors::NoDigitsLiteral { span }); - (token::Integer, sym::integer(0)) - } else { - if matches!(base, Base::Binary | Base::Octal) { - let base = base as u32; - let s = self.str_from_to(start + BytePos(2), end); - for (idx, c) in s.char_indices() { - let span = self.mk_sp( - start + BytePos::from_usize(2 + idx), - start + BytePos::from_usize(2 + idx + c.len_utf8()), - ); - if c != '_' && c.to_digit(base).is_none() { - self.dcx().emit_err(errors::InvalidDigitLiteral { span, base }); - } + kind = token::Err; + } else if matches!(base, Base::Binary | Base::Octal) { + let base = base as u32; + let s = self.str_from_to(start + BytePos(2), end); + for (idx, c) in s.char_indices() { + let span = self.mk_sp( + start + BytePos::from_usize(2 + idx), + start + BytePos::from_usize(2 + idx + c.len_utf8()), + ); + if c != '_' && c.to_digit(base).is_none() { + self.dcx().emit_err(errors::InvalidDigitLiteral { span, base }); + kind = token::Err; } } - (token::Integer, self.symbol_from_to(start, end)) } + (kind, self.symbol_from_to(start, end)) } rustc_lexer::LiteralKind::Float { base, empty_exponent } => { if empty_exponent { diff --git a/compiler/rustc_session/src/errors.rs b/compiler/rustc_session/src/errors.rs index c36cec6f3532..e4bc6acf46c8 100644 --- a/compiler/rustc_session/src/errors.rs +++ b/compiler/rustc_session/src/errors.rs @@ -375,9 +375,6 @@ pub fn report_lit_error(sess: &ParseSess, err: LitError, lit: token::Lit, span: let token::Lit { kind, symbol, suffix, .. } = lit; let dcx = &sess.dcx; match err { - // `LexerError` is an error, but it was already reported - // by lexer, so here we don't report it the second time. - LitError::LexerError => {} LitError::InvalidSuffix => { if let Some(suffix) = suffix { dcx.emit_err(InvalidLiteralSuffix { span, kind: kind.descr(), suffix }); From a513bb20c39e18bd837934c80355ff468f233a4a Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 14 Feb 2024 19:30:12 +1100 Subject: [PATCH 14/17] Make `report_lit_error` return `ErrorGuaranteed`. This will be helpful for subsequent commits. --- compiler/rustc_session/src/errors.rs | 43 +++++++++++++++------------- 1 file changed, 23 insertions(+), 20 deletions(-) diff --git a/compiler/rustc_session/src/errors.rs b/compiler/rustc_session/src/errors.rs index e4bc6acf46c8..f06e2136c2c5 100644 --- a/compiler/rustc_session/src/errors.rs +++ b/compiler/rustc_session/src/errors.rs @@ -3,7 +3,8 @@ use std::num::NonZeroU32; use rustc_ast::token; use rustc_ast::util::literal::LitError; use rustc_errors::{ - codes::*, DiagCtxt, DiagnosticBuilder, DiagnosticMessage, IntoDiagnostic, Level, MultiSpan, + codes::*, DiagCtxt, DiagnosticBuilder, DiagnosticMessage, ErrorGuaranteed, IntoDiagnostic, + Level, MultiSpan, }; use rustc_macros::Diagnostic; use rustc_span::{Span, Symbol}; @@ -344,7 +345,12 @@ pub(crate) struct BinaryFloatLiteralNotSupported { pub span: Span, } -pub fn report_lit_error(sess: &ParseSess, err: LitError, lit: token::Lit, span: Span) { +pub fn report_lit_error( + sess: &ParseSess, + err: LitError, + lit: token::Lit, + span: Span, +) -> ErrorGuaranteed { // Checks if `s` looks like i32 or u1234 etc. fn looks_like_width_suffix(first_chars: &[char], s: &str) -> bool { s.len() > 1 && s.starts_with(first_chars) && s[1..].chars().all(|c| c.is_ascii_digit()) @@ -372,24 +378,23 @@ pub fn report_lit_error(sess: &ParseSess, err: LitError, lit: token::Lit, span: valid.then(|| format!("0{}{}", base_char.to_ascii_lowercase(), &suffix[1..])) } - let token::Lit { kind, symbol, suffix, .. } = lit; + let token::Lit { kind, symbol, suffix } = lit; let dcx = &sess.dcx; match err { LitError::InvalidSuffix => { - if let Some(suffix) = suffix { - dcx.emit_err(InvalidLiteralSuffix { span, kind: kind.descr(), suffix }); - } + let suffix = suffix.unwrap(); + dcx.emit_err(InvalidLiteralSuffix { span, kind: kind.descr(), suffix }) } LitError::InvalidIntSuffix => { let suf = suffix.expect("suffix error with no suffix"); let suf = suf.as_str(); if looks_like_width_suffix(&['i', 'u'], suf) { // If it looks like a width, try to be helpful. - dcx.emit_err(InvalidIntLiteralWidth { span, width: suf[1..].into() }); + dcx.emit_err(InvalidIntLiteralWidth { span, width: suf[1..].into() }) } else if let Some(fixed) = fix_base_capitalisation(symbol.as_str(), suf) { - dcx.emit_err(InvalidNumLiteralBasePrefix { span, fixed }); + dcx.emit_err(InvalidNumLiteralBasePrefix { span, fixed }) } else { - dcx.emit_err(InvalidNumLiteralSuffix { span, suffix: suf.to_string() }); + dcx.emit_err(InvalidNumLiteralSuffix { span, suffix: suf.to_string() }) } } LitError::InvalidFloatSuffix => { @@ -397,19 +402,17 @@ pub fn report_lit_error(sess: &ParseSess, err: LitError, lit: token::Lit, span: let suf = suf.as_str(); if looks_like_width_suffix(&['f'], suf) { // If it looks like a width, try to be helpful. - dcx.emit_err(InvalidFloatLiteralWidth { span, width: suf[1..].to_string() }); + dcx.emit_err(InvalidFloatLiteralWidth { span, width: suf[1..].to_string() }) } else { - dcx.emit_err(InvalidFloatLiteralSuffix { span, suffix: suf.to_string() }); + dcx.emit_err(InvalidFloatLiteralSuffix { span, suffix: suf.to_string() }) } } - LitError::NonDecimalFloat(base) => { - match base { - 16 => dcx.emit_err(HexadecimalFloatLiteralNotSupported { span }), - 8 => dcx.emit_err(OctalFloatLiteralNotSupported { span }), - 2 => dcx.emit_err(BinaryFloatLiteralNotSupported { span }), - _ => unreachable!(), - }; - } + LitError::NonDecimalFloat(base) => match base { + 16 => dcx.emit_err(HexadecimalFloatLiteralNotSupported { span }), + 8 => dcx.emit_err(OctalFloatLiteralNotSupported { span }), + 2 => dcx.emit_err(BinaryFloatLiteralNotSupported { span }), + _ => unreachable!(), + }, LitError::IntTooLarge(base) => { let max = u128::MAX; let limit = match base { @@ -418,7 +421,7 @@ pub fn report_lit_error(sess: &ParseSess, err: LitError, lit: token::Lit, span: 16 => format!("{max:#x}"), _ => format!("{max}"), }; - dcx.emit_err(IntLiteralTooLarge { span, limit }); + dcx.emit_err(IntLiteralTooLarge { span, limit }) } } } From 332c57723a03e97497d6fba6636e31c2e41fefe9 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 14 Feb 2024 20:29:31 +1100 Subject: [PATCH 15/17] Make `emit_unescape_error` return `Option`. And use the result in `cook_common` to decide whether to return an error token. --- compiler/rustc_parse/src/lexer/mod.rs | 16 ++--- .../src/lexer/unescape_error_reporting.rs | 58 +++++++++---------- 2 files changed, 34 insertions(+), 40 deletions(-) diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs index aa4456a1c218..7502a5567949 100644 --- a/compiler/rustc_parse/src/lexer/mod.rs +++ b/compiler/rustc_parse/src/lexer/mod.rs @@ -691,7 +691,7 @@ impl<'sess, 'src> StringReader<'sess, 'src> { fn cook_common( &self, - kind: token::LitKind, + mut kind: token::LitKind, mode: Mode, start: BytePos, end: BytePos, @@ -699,7 +699,6 @@ impl<'sess, 'src> StringReader<'sess, 'src> { postfix_len: u32, unescape: fn(&str, Mode, &mut dyn FnMut(Range, Result<(), EscapeError>)), ) -> (token::LitKind, Symbol) { - let mut has_fatal_err = false; let content_start = start + BytePos(prefix_len); let content_end = end - BytePos(postfix_len); let lit_content = self.str_from_to(content_start, content_end); @@ -711,10 +710,8 @@ impl<'sess, 'src> StringReader<'sess, 'src> { let lo = content_start + BytePos(start); let hi = lo + BytePos(end - start); let span = self.mk_sp(lo, hi); - if err.is_fatal() { - has_fatal_err = true; - } - emit_unescape_error( + let is_fatal = err.is_fatal(); + if let Some(_guar) = emit_unescape_error( self.dcx(), lit_content, span_with_quotes, @@ -722,13 +719,16 @@ impl<'sess, 'src> StringReader<'sess, 'src> { mode, range, err, - ); + ) { + assert!(is_fatal); + kind = token::Err; + } } }); // We normally exclude the quotes for the symbol, but for errors we // include it because it results in clearer error messages. - if !has_fatal_err { + if kind != token::Err { (kind, Symbol::intern(lit_content)) } else { (token::Err, self.symbol_from_to(start, end)) diff --git a/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs b/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs index 3238f8e23bb0..3ebad6a9fd73 100644 --- a/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs +++ b/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs @@ -3,7 +3,7 @@ use std::iter::once; use std::ops::Range; -use rustc_errors::{Applicability, DiagCtxt}; +use rustc_errors::{Applicability, DiagCtxt, ErrorGuaranteed}; use rustc_lexer::unescape::{EscapeError, Mode}; use rustc_span::{BytePos, Span}; @@ -21,7 +21,7 @@ pub(crate) fn emit_unescape_error( // range of the error inside `lit` range: Range, error: EscapeError, -) { +) -> Option { debug!( "emit_unescape_error: {:?}, {:?}, {:?}, {:?}, {:?}", lit, full_lit_span, mode, range, error @@ -31,12 +31,12 @@ pub(crate) fn emit_unescape_error( let span = err_span.with_lo(err_span.hi() - BytePos(c.len_utf8() as u32)); (c, span) }; - match error { + Some(match error { EscapeError::LoneSurrogateUnicodeEscape => { - dcx.emit_err(UnescapeError::InvalidUnicodeEscape { span: err_span, surrogate: true }); + dcx.emit_err(UnescapeError::InvalidUnicodeEscape { span: err_span, surrogate: true }) } EscapeError::OutOfRangeUnicodeEscape => { - dcx.emit_err(UnescapeError::InvalidUnicodeEscape { span: err_span, surrogate: false }); + dcx.emit_err(UnescapeError::InvalidUnicodeEscape { span: err_span, surrogate: false }) } EscapeError::MoreThanOneChar => { use unicode_normalization::{char::is_combining_mark, UnicodeNormalization}; @@ -106,7 +106,7 @@ pub(crate) fn emit_unescape_error( span: full_lit_span, note, suggestion: sugg, - }); + }) } EscapeError::EscapeOnlyChar => { let (c, char_span) = last_char(); @@ -116,15 +116,15 @@ pub(crate) fn emit_unescape_error( escaped_sugg: c.escape_default().to_string(), escaped_msg: escaped_char(c), byte: mode == Mode::Byte, - }); + }) } EscapeError::BareCarriageReturn => { let double_quotes = mode.in_double_quotes(); - dcx.emit_err(UnescapeError::BareCr { span: err_span, double_quotes }); + dcx.emit_err(UnescapeError::BareCr { span: err_span, double_quotes }) } EscapeError::BareCarriageReturnInRawString => { assert!(mode.in_double_quotes()); - dcx.emit_err(UnescapeError::BareCrRawString(err_span)); + dcx.emit_err(UnescapeError::BareCrRawString(err_span)) } EscapeError::InvalidEscape => { let (c, span) = last_char(); @@ -161,16 +161,14 @@ pub(crate) fn emit_unescape_error( ", ); } - diag.emit(); - } - EscapeError::TooShortHexEscape => { - dcx.emit_err(UnescapeError::TooShortHexEscape(err_span)); + diag.emit() } + EscapeError::TooShortHexEscape => dcx.emit_err(UnescapeError::TooShortHexEscape(err_span)), EscapeError::InvalidCharInHexEscape | EscapeError::InvalidCharInUnicodeEscape => { let (c, span) = last_char(); let is_hex = error == EscapeError::InvalidCharInHexEscape; let ch = escaped_char(c); - dcx.emit_err(UnescapeError::InvalidCharInEscape { span, is_hex, ch }); + dcx.emit_err(UnescapeError::InvalidCharInEscape { span, is_hex, ch }) } EscapeError::NonAsciiCharInByte => { let (c, span) = last_char(); @@ -213,23 +211,23 @@ pub(crate) fn emit_unescape_error( Applicability::MaybeIncorrect, ); } - err.emit(); + err.emit() } EscapeError::OutOfRangeHexEscape => { - dcx.emit_err(UnescapeError::OutOfRangeHexEscape(err_span)); + dcx.emit_err(UnescapeError::OutOfRangeHexEscape(err_span)) } EscapeError::LeadingUnderscoreUnicodeEscape => { let (c, span) = last_char(); dcx.emit_err(UnescapeError::LeadingUnderscoreUnicodeEscape { span, ch: escaped_char(c), - }); + }) } EscapeError::OverlongUnicodeEscape => { - dcx.emit_err(UnescapeError::OverlongUnicodeEscape(err_span)); + dcx.emit_err(UnescapeError::OverlongUnicodeEscape(err_span)) } EscapeError::UnclosedUnicodeEscape => { - dcx.emit_err(UnescapeError::UnclosedUnicodeEscape(err_span, err_span.shrink_to_hi())); + dcx.emit_err(UnescapeError::UnclosedUnicodeEscape(err_span, err_span.shrink_to_hi())) } EscapeError::NoBraceInUnicodeEscape => { let mut suggestion = "\\u{".to_owned(); @@ -248,23 +246,17 @@ pub(crate) fn emit_unescape_error( } else { (Some(err_span), NoBraceUnicodeSub::Help) }; - dcx.emit_err(UnescapeError::NoBraceInUnicodeEscape { span: err_span, label, sub }); + dcx.emit_err(UnescapeError::NoBraceInUnicodeEscape { span: err_span, label, sub }) } EscapeError::UnicodeEscapeInByte => { - dcx.emit_err(UnescapeError::UnicodeEscapeInByte(err_span)); + dcx.emit_err(UnescapeError::UnicodeEscapeInByte(err_span)) } EscapeError::EmptyUnicodeEscape => { - dcx.emit_err(UnescapeError::EmptyUnicodeEscape(err_span)); - } - EscapeError::ZeroChars => { - dcx.emit_err(UnescapeError::ZeroChars(err_span)); - } - EscapeError::LoneSlash => { - dcx.emit_err(UnescapeError::LoneSlash(err_span)); - } - EscapeError::NulInCStr => { - dcx.emit_err(UnescapeError::NulInCStr { span: err_span }); + dcx.emit_err(UnescapeError::EmptyUnicodeEscape(err_span)) } + EscapeError::ZeroChars => dcx.emit_err(UnescapeError::ZeroChars(err_span)), + EscapeError::LoneSlash => dcx.emit_err(UnescapeError::LoneSlash(err_span)), + EscapeError::NulInCStr => dcx.emit_err(UnescapeError::NulInCStr { span: err_span }), EscapeError::UnskippedWhitespaceWarning => { let (c, char_span) = last_char(); dcx.emit_warn(UnescapeError::UnskippedWhitespace { @@ -272,11 +264,13 @@ pub(crate) fn emit_unescape_error( ch: escaped_char(c), char_span, }); + return None; } EscapeError::MultipleSkippedLinesWarning => { dcx.emit_warn(UnescapeError::MultipleSkippedLinesWarning(err_span)); + return None; } - } + }) } /// Pushes a character to a message string for error reporting From 25ed6e43b0ea03ca48692741624f3e70d717ea43 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 14 Feb 2024 20:12:05 +1100 Subject: [PATCH 16/17] Add `ErrorGuaranteed` to `ast::LitKind::Err`, `token::LitKind::Err`. This mostly works well, and eliminates a couple of delayed bugs. One annoying thing is that we should really also add an `ErrorGuaranteed` to `proc_macro::bridge::LitKind::Err`. But that's difficult because `proc_macro` doesn't have access to `ErrorGuaranteed`, so we have to fake it. --- compiler/rustc_ast/src/ast.rs | 4 ++-- compiler/rustc_ast/src/token.rs | 12 +++++----- compiler/rustc_ast/src/util/literal.rs | 6 ++--- compiler/rustc_ast_lowering/src/expr.rs | 9 ++++++-- compiler/rustc_ast_lowering/src/lib.rs | 3 ++- compiler/rustc_ast_pretty/src/pprust/state.rs | 2 +- compiler/rustc_builtin_macros/src/concat.rs | 2 +- .../rustc_builtin_macros/src/concat_bytes.rs | 2 +- compiler/rustc_expand/src/base.rs | 2 +- .../rustc_expand/src/proc_macro_server.rs | 22 +++++++++++++++---- .../rustc_hir_typeck/src/fn_ctxt/checks.rs | 2 +- .../src/build/expr/as_constant.rs | 6 +---- compiler/rustc_mir_build/src/thir/constant.rs | 6 +---- compiler/rustc_mir_build/src/thir/cx/expr.rs | 12 +++++----- compiler/rustc_parse/src/lexer/mod.rs | 22 ++++++++++--------- compiler/rustc_parse/src/parser/expr.rs | 4 ++-- compiler/rustc_parse/src/parser/mod.rs | 2 +- compiler/rustc_parse/src/validate_attr.rs | 4 ++-- library/proc_macro/src/bridge/mod.rs | 8 +++++-- library/proc_macro/src/lib.rs | 2 +- .../src/matches/match_same_arms.rs | 3 ++- .../src/redundant_type_annotations.rs | 2 +- .../clippy/clippy_lints/src/utils/author.rs | 2 +- src/tools/clippy/clippy_utils/src/consts.rs | 2 +- .../src/server/rust_analyzer_span.rs | 4 ++-- .../proc-macro-srv/src/server/token_id.rs | 4 ++-- 26 files changed, 85 insertions(+), 64 deletions(-) diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 098e2606a3be..b74938621b30 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -1846,7 +1846,7 @@ pub enum LitKind { /// A boolean literal (`true`, `false`). Bool(bool), /// Placeholder for a literal that wasn't well-formed in some way. - Err, + Err(ErrorGuaranteed), } impl LitKind { @@ -1893,7 +1893,7 @@ impl LitKind { | LitKind::Int(_, LitIntType::Unsuffixed) | LitKind::Float(_, LitFloatType::Unsuffixed) | LitKind::Bool(..) - | LitKind::Err => false, + | LitKind::Err(_) => false, } } } diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs index d62462b1ae33..50fe37dcdb6f 100644 --- a/compiler/rustc_ast/src/token.rs +++ b/compiler/rustc_ast/src/token.rs @@ -13,7 +13,7 @@ use rustc_macros::HashStable_Generic; use rustc_span::symbol::{kw, sym}; #[allow(hidden_glob_reexports)] use rustc_span::symbol::{Ident, Symbol}; -use rustc_span::{edition::Edition, Span, DUMMY_SP}; +use rustc_span::{edition::Edition, ErrorGuaranteed, Span, DUMMY_SP}; use std::borrow::Cow; use std::fmt; @@ -75,7 +75,7 @@ pub enum LitKind { ByteStrRaw(u8), // raw byte string delimited by `n` hash symbols CStr, CStrRaw(u8), - Err, + Err(ErrorGuaranteed), } /// A literal token. @@ -144,7 +144,7 @@ impl fmt::Display for Lit { CStrRaw(n) => { write!(f, "cr{delim}\"{symbol}\"{delim}", delim = "#".repeat(n as usize))? } - Integer | Float | Bool | Err => write!(f, "{symbol}")?, + Integer | Float | Bool | Err(_) => write!(f, "{symbol}")?, } if let Some(suffix) = suffix { @@ -159,7 +159,7 @@ impl LitKind { /// An English article for the literal token kind. pub fn article(self) -> &'static str { match self { - Integer | Err => "an", + Integer | Err(_) => "an", _ => "a", } } @@ -174,12 +174,12 @@ impl LitKind { Str | StrRaw(..) => "string", ByteStr | ByteStrRaw(..) => "byte string", CStr | CStrRaw(..) => "C string", - Err => "error", + Err(_) => "error", } } pub(crate) fn may_have_suffix(self) -> bool { - matches!(self, Integer | Float | Err) + matches!(self, Integer | Float | Err(_)) } } diff --git a/compiler/rustc_ast/src/util/literal.rs b/compiler/rustc_ast/src/util/literal.rs index fbe72252ec91..e4bb23675cb9 100644 --- a/compiler/rustc_ast/src/util/literal.rs +++ b/compiler/rustc_ast/src/util/literal.rs @@ -144,7 +144,7 @@ impl LitKind { buf.push(0); LitKind::CStr(buf.into(), StrStyle::Raw(n)) } - token::Err => LitKind::Err, + token::Err(guar) => LitKind::Err(guar), }) } } @@ -201,7 +201,7 @@ impl fmt::Display for LitKind { } } LitKind::Bool(b) => write!(f, "{}", if b { "true" } else { "false" })?, - LitKind::Err => { + LitKind::Err(_) => { // This only shows up in places like `-Zunpretty=hir` output, so we // don't bother to produce something useful. write!(f, "")?; @@ -237,7 +237,7 @@ impl MetaItemLit { LitKind::Char(_) => token::Char, LitKind::Int(..) => token::Integer, LitKind::Float(..) => token::Float, - LitKind::Err => token::Err, + LitKind::Err(guar) => token::Err(guar), }; token::Lit::new(kind, self.symbol, self.suffix) diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 73d1d891bb98..2112040621ee 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -124,8 +124,13 @@ impl<'hir> LoweringContext<'_, 'hir> { let lit_kind = match LitKind::from_token_lit(*token_lit) { Ok(lit_kind) => lit_kind, Err(err) => { - report_lit_error(&self.tcx.sess.parse_sess, err, *token_lit, e.span); - LitKind::Err + let guar = report_lit_error( + &self.tcx.sess.parse_sess, + err, + *token_lit, + e.span, + ); + LitKind::Err(guar) } }; let lit = self.arena.alloc(respan(self.lower_span(e.span), lit_kind)); diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 6b5fc0142408..eab1383b635c 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -966,10 +966,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { { lit } else { + let guar = self.dcx().has_errors().unwrap(); MetaItemLit { symbol: kw::Empty, suffix: None, - kind: LitKind::Err, + kind: LitKind::Err(guar), span: DUMMY_SP, } }; diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index cda746894e86..2765b235f991 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -254,7 +254,7 @@ fn literal_to_string(lit: token::Lit) -> String { token::CStrRaw(n) => { format!("cr{delim}\"{symbol}\"{delim}", delim = "#".repeat(n as usize)) } - token::Integer | token::Float | token::Bool | token::Err => symbol.to_string(), + token::Integer | token::Float | token::Bool | token::Err(_) => symbol.to_string(), }; if let Some(suffix) = suffix { diff --git a/compiler/rustc_builtin_macros/src/concat.rs b/compiler/rustc_builtin_macros/src/concat.rs index dade29593af1..795161e65d81 100644 --- a/compiler/rustc_builtin_macros/src/concat.rs +++ b/compiler/rustc_builtin_macros/src/concat.rs @@ -40,7 +40,7 @@ pub fn expand_concat( cx.dcx().emit_err(errors::ConcatBytestr { span: e.span }); has_errors = true; } - Ok(ast::LitKind::Err) => { + Ok(ast::LitKind::Err(_)) => { has_errors = true; } Err(err) => { diff --git a/compiler/rustc_builtin_macros/src/concat_bytes.rs b/compiler/rustc_builtin_macros/src/concat_bytes.rs index a01bbeac8249..3ef8cb7bffef 100644 --- a/compiler/rustc_builtin_macros/src/concat_bytes.rs +++ b/compiler/rustc_builtin_macros/src/concat_bytes.rs @@ -44,7 +44,7 @@ fn invalid_type_err( Ok(ast::LitKind::Bool(_)) => { dcx.emit_err(ConcatBytesInvalid { span, lit_kind: "boolean", sugg: None }); } - Ok(ast::LitKind::Err) => {} + Ok(ast::LitKind::Err(_)) => {} Ok(ast::LitKind::Int(_, _)) if !is_nested => { let sugg = snippet.map(|snippet| ConcatBytesInvalidSuggestion::IntLit { span: span, snippet }); diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index cfeb31fc4c81..09ab26421d65 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -1266,7 +1266,7 @@ pub fn expr_to_spanned_string<'a>( ); Some((err, true)) } - Ok(ast::LitKind::Err) => None, + Ok(ast::LitKind::Err(_)) => None, Err(err) => { report_lit_error(&cx.sess.parse_sess, err, token_lit, expr.span); None diff --git a/compiler/rustc_expand/src/proc_macro_server.rs b/compiler/rustc_expand/src/proc_macro_server.rs index 3a78bd945057..8f31b5801da7 100644 --- a/compiler/rustc_expand/src/proc_macro_server.rs +++ b/compiler/rustc_expand/src/proc_macro_server.rs @@ -10,7 +10,7 @@ use rustc_ast::util::literal::escape_byte_str_symbol; use rustc_ast_pretty::pprust; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sync::Lrc; -use rustc_errors::{MultiSpan, PResult}; +use rustc_errors::{ErrorGuaranteed, MultiSpan, PResult}; use rustc_parse::lexer::nfc_normalize; use rustc_parse::parse_stream_from_source_str; use rustc_session::parse::ParseSess; @@ -63,7 +63,12 @@ impl FromInternal for LitKind { token::ByteStrRaw(n) => LitKind::ByteStrRaw(n), token::CStr => LitKind::CStr, token::CStrRaw(n) => LitKind::CStrRaw(n), - token::Err => LitKind::Err, + token::Err(_guar) => { + // This is the only place a `pm::bridge::LitKind::ErrWithGuar` + // is constructed. Note that an `ErrorGuaranteed` is available, + // as required. See the comment in `to_internal`. + LitKind::ErrWithGuar + } token::Bool => unreachable!(), } } @@ -82,7 +87,16 @@ impl ToInternal for LitKind { LitKind::ByteStrRaw(n) => token::ByteStrRaw(n), LitKind::CStr => token::CStr, LitKind::CStrRaw(n) => token::CStrRaw(n), - LitKind::Err => token::Err, + LitKind::ErrWithGuar => { + // This is annoying but valid. `LitKind::ErrWithGuar` would + // have an `ErrorGuaranteed` except that type isn't available + // in that crate. So we have to fake one. And we don't want to + // use a delayed bug because there might be lots of these, + // which would be expensive. + #[allow(deprecated)] + let guar = ErrorGuaranteed::unchecked_error_guaranteed(); + token::Err(guar) + } } } } @@ -477,7 +491,7 @@ impl server::FreeFunctions for Rustc<'_, '_> { | token::LitKind::ByteStrRaw(_) | token::LitKind::CStr | token::LitKind::CStrRaw(_) - | token::LitKind::Err => return Err(()), + | token::LitKind::Err(_) => return Err(()), token::LitKind::Integer | token::LitKind::Float => {} } diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index 65b8505c0909..3bce8a1dd450 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -1319,7 +1319,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { tcx.type_of(tcx.require_lang_item(hir::LangItem::CStr, Some(lit.span))) .skip_binder(), ), - ast::LitKind::Err => Ty::new_misc_error(tcx), + ast::LitKind::Err(guar) => Ty::new_error(tcx, guar), } } diff --git a/compiler/rustc_mir_build/src/build/expr/as_constant.rs b/compiler/rustc_mir_build/src/build/expr/as_constant.rs index 6636f75d9981..7c3d2671d592 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_constant.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_constant.rs @@ -164,11 +164,7 @@ fn lit_to_mir_constant<'tcx>( })?, (ast::LitKind::Bool(b), ty::Bool) => ConstValue::Scalar(Scalar::from_bool(*b)), (ast::LitKind::Char(c), ty::Char) => ConstValue::Scalar(Scalar::from_char(*c)), - (ast::LitKind::Err, _) => { - return Err(LitToConstError::Reported( - tcx.dcx().delayed_bug("encountered LitKind::Err during mir build"), - )); - } + (ast::LitKind::Err(guar), _) => return Err(LitToConstError::Reported(*guar)), _ => return Err(LitToConstError::TypeError), }; diff --git a/compiler/rustc_mir_build/src/thir/constant.rs b/compiler/rustc_mir_build/src/thir/constant.rs index 71aebd13003b..d444de8b28ee 100644 --- a/compiler/rustc_mir_build/src/thir/constant.rs +++ b/compiler/rustc_mir_build/src/thir/constant.rs @@ -71,11 +71,7 @@ pub(crate) fn lit_to_const<'tcx>( ty::ValTree::from_scalar_int(bits) } (ast::LitKind::Char(c), ty::Char) => ty::ValTree::from_scalar_int((*c).into()), - (ast::LitKind::Err, _) => { - return Err(LitToConstError::Reported( - tcx.dcx().delayed_bug("encountered LitKind::Err during mir build"), - )); - } + (ast::LitKind::Err(guar), _) => return Err(LitToConstError::Reported(*guar)), _ => return Err(LitToConstError::TypeError), }; diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs index 99952e1c1787..62762168cf42 100644 --- a/compiler/rustc_mir_build/src/thir/cx/expr.rs +++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs @@ -897,12 +897,14 @@ impl<'tcx> Cx<'tcx> { let hir_id = self.tcx.local_def_id_to_hir_id(def_id.expect_local()); let generics = self.tcx.generics_of(hir_id.owner); let Some(&index) = generics.param_def_id_to_index.get(&def_id) else { - self.tcx.dcx().has_errors().unwrap(); + let guar = self.tcx.dcx().has_errors().unwrap(); // We already errored about a late bound const - return ExprKind::Literal { - lit: &Spanned { span: DUMMY_SP, node: LitKind::Err }, - neg: false, - }; + + let lit = self + .tcx + .hir_arena + .alloc(Spanned { span: DUMMY_SP, node: LitKind::Err(guar) }); + return ExprKind::Literal { lit, neg: false }; }; let name = self.tcx.hir().name(hir_id); let param = ty::ParamConst::new(index, name); diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs index 7502a5567949..c768ea93b5fe 100644 --- a/compiler/rustc_parse/src/lexer/mod.rs +++ b/compiler/rustc_parse/src/lexer/mod.rs @@ -481,8 +481,8 @@ impl<'sess, 'src> StringReader<'sess, 'src> { let mut kind = token::Integer; if empty_int { let span = self.mk_sp(start, end); - self.dcx().emit_err(errors::NoDigitsLiteral { span }); - kind = token::Err; + let guar = self.dcx().emit_err(errors::NoDigitsLiteral { span }); + kind = token::Err(guar); } else if matches!(base, Base::Binary | Base::Octal) { let base = base as u32; let s = self.str_from_to(start + BytePos(2), end); @@ -492,8 +492,9 @@ impl<'sess, 'src> StringReader<'sess, 'src> { start + BytePos::from_usize(2 + idx + c.len_utf8()), ); if c != '_' && c.to_digit(base).is_none() { - self.dcx().emit_err(errors::InvalidDigitLiteral { span, base }); - kind = token::Err; + let guar = + self.dcx().emit_err(errors::InvalidDigitLiteral { span, base }); + kind = token::Err(guar); } } } @@ -711,7 +712,7 @@ impl<'sess, 'src> StringReader<'sess, 'src> { let hi = lo + BytePos(end - start); let span = self.mk_sp(lo, hi); let is_fatal = err.is_fatal(); - if let Some(_guar) = emit_unescape_error( + if let Some(guar) = emit_unescape_error( self.dcx(), lit_content, span_with_quotes, @@ -721,18 +722,19 @@ impl<'sess, 'src> StringReader<'sess, 'src> { err, ) { assert!(is_fatal); - kind = token::Err; + kind = token::Err(guar); } } }); // We normally exclude the quotes for the symbol, but for errors we // include it because it results in clearer error messages. - if kind != token::Err { - (kind, Symbol::intern(lit_content)) + let sym = if !matches!(kind, token::Err(_)) { + Symbol::intern(lit_content) } else { - (token::Err, self.symbol_from_to(start, end)) - } + self.symbol_from_to(start, end) + }; + (kind, sym) } fn cook_unicode( diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 1a57474bac28..2424b6c130d2 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -2140,12 +2140,12 @@ impl<'a> Parser<'a> { Err(err) => { let span = token.uninterpolated_span(); self.bump(); - report_lit_error(self.sess, err, lit, span); + let guar = report_lit_error(self.sess, err, lit, span); // Pack possible quotes and prefixes from the original literal into // the error literal's symbol so they can be pretty-printed faithfully. let suffixless_lit = token::Lit::new(lit.kind, lit.symbol, None); let symbol = Symbol::intern(&suffixless_lit.to_string()); - let lit = token::Lit::new(token::Err, symbol, lit.suffix); + let lit = token::Lit::new(token::Err(guar), symbol, lit.suffix); Some( MetaItemLit::from_token_lit(lit, span) .unwrap_or_else(|_| unreachable!()), diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index 623407eb3800..dea2b9e6ca70 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -1459,7 +1459,7 @@ impl<'a> Parser<'a> { match self.parse_str_lit() { Ok(str_lit) => Some(str_lit), Err(Some(lit)) => match lit.kind { - ast::LitKind::Err => None, + ast::LitKind::Err(_) => None, _ => { self.dcx().emit_err(NonStringAbiLiteral { span: lit.span }); None diff --git a/compiler/rustc_parse/src/validate_attr.rs b/compiler/rustc_parse/src/validate_attr.rs index 2fafbd6d97b5..b0982029657b 100644 --- a/compiler/rustc_parse/src/validate_attr.rs +++ b/compiler/rustc_parse/src/validate_attr.rs @@ -70,11 +70,11 @@ pub fn parse_meta<'a>(sess: &'a ParseSess, attr: &Attribute) -> PResult<'a, Meta } } Err(err) => { - report_lit_error(sess, err, token_lit, expr.span); + let guar = report_lit_error(sess, err, token_lit, expr.span); let lit = ast::MetaItemLit { symbol: token_lit.symbol, suffix: token_lit.suffix, - kind: ast::LitKind::Err, + kind: ast::LitKind::Err(guar), span: expr.span, }; MetaItemKind::NameValue(lit) diff --git a/library/proc_macro/src/bridge/mod.rs b/library/proc_macro/src/bridge/mod.rs index 55e24b6491c7..9b337f23867f 100644 --- a/library/proc_macro/src/bridge/mod.rs +++ b/library/proc_macro/src/bridge/mod.rs @@ -337,7 +337,11 @@ pub enum LitKind { ByteStrRaw(u8), CStr, CStrRaw(u8), - Err, + // This should have an `ErrorGuaranteed`, except that type isn't available + // in this crate. (Imagine it is there.) Hence the `WithGuar` suffix. Must + // only be constructed in `LitKind::from_internal`, where an + // `ErrorGuaranteed` is available. + ErrWithGuar, } rpc_encode_decode!( @@ -352,7 +356,7 @@ rpc_encode_decode!( ByteStrRaw(n), CStr, CStrRaw(n), - Err, + ErrWithGuar, } ); diff --git a/library/proc_macro/src/lib.rs b/library/proc_macro/src/lib.rs index 90b76cbc26eb..7c4929417132 100644 --- a/library/proc_macro/src/lib.rs +++ b/library/proc_macro/src/lib.rs @@ -1451,7 +1451,7 @@ impl Literal { f(&["cr", hashes, "\"", symbol, "\"", hashes, suffix]) } - bridge::LitKind::Integer | bridge::LitKind::Float | bridge::LitKind::Err => { + bridge::LitKind::Integer | bridge::LitKind::Float | bridge::LitKind::ErrWithGuar => { f(&[symbol, suffix]) } }) diff --git a/src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs b/src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs index 6595658b7692..b8f7d9668201 100644 --- a/src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs +++ b/src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs @@ -295,7 +295,8 @@ impl<'a> NormalizedPat<'a> { LitKind::Char(val) => Self::LitInt(val.into()), LitKind::Int(val, _) => Self::LitInt(val.get()), LitKind::Bool(val) => Self::LitBool(val), - LitKind::Float(..) | LitKind::Err => Self::Wild, + LitKind::Float(..) => Self::Wild, + LitKind::Err(guar) => Self::Err(guar), }, _ => Self::Wild, }, diff --git a/src/tools/clippy/clippy_lints/src/redundant_type_annotations.rs b/src/tools/clippy/clippy_lints/src/redundant_type_annotations.rs index c8352c052659..079e6500e3cf 100644 --- a/src/tools/clippy/clippy_lints/src/redundant_type_annotations.rs +++ b/src/tools/clippy/clippy_lints/src/redundant_type_annotations.rs @@ -200,7 +200,7 @@ impl LateLintPass<'_> for RedundantTypeAnnotations { span_lint(cx, REDUNDANT_TYPE_ANNOTATIONS, local.span, "redundant type annotation"); } }, - LitKind::Err => (), + LitKind::Err(_) => (), LitKind::ByteStr(..) => { // We only lint if the type annotation is an array type (e.g. &[u8; 4]). // If instead it is a slice (e.g. &[u8]) it may not be redundant, so we diff --git a/src/tools/clippy/clippy_lints/src/utils/author.rs b/src/tools/clippy/clippy_lints/src/utils/author.rs index 29c67341a467..a0a6382046d0 100644 --- a/src/tools/clippy/clippy_lints/src/utils/author.rs +++ b/src/tools/clippy/clippy_lints/src/utils/author.rs @@ -279,7 +279,7 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> { match lit.value.node { LitKind::Bool(val) => kind!("Bool({val:?})"), LitKind::Char(c) => kind!("Char({c:?})"), - LitKind::Err => kind!("Err"), + LitKind::Err(_) => kind!("Err"), LitKind::Byte(b) => kind!("Byte({b})"), LitKind::Int(i, suffix) => { let int_ty = match suffix { diff --git a/src/tools/clippy/clippy_utils/src/consts.rs b/src/tools/clippy/clippy_utils/src/consts.rs index 61b38391d9e0..79c691992a85 100644 --- a/src/tools/clippy/clippy_utils/src/consts.rs +++ b/src/tools/clippy/clippy_utils/src/consts.rs @@ -286,7 +286,7 @@ pub fn lit_to_mir_constant<'tcx>(lit: &LitKind, ty: Option>) -> Constan _ => bug!(), }, LitKind::Bool(b) => Constant::Bool(b), - LitKind::Err => Constant::Err, + LitKind::Err(_) => Constant::Err, } } diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/server/rust_analyzer_span.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/server/rust_analyzer_span.rs index c7c7bea99410..8a9d52a37a2f 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/server/rust_analyzer_span.rs +++ b/src/tools/rust-analyzer/crates/proc-macro-srv/src/server/rust_analyzer_span.rs @@ -72,7 +72,7 @@ impl server::FreeFunctions for RaSpanServer { ) -> Result, ()> { // FIXME: keep track of LitKind and Suffix Ok(bridge::Literal { - kind: bridge::LitKind::Err, + kind: bridge::LitKind::Integer, // dummy symbol: Symbol::intern(self.interner, s), suffix: None, span: self.call_site, @@ -202,7 +202,7 @@ impl server::TokenStream for RaSpanServer { tt::TokenTree::Leaf(tt::Leaf::Literal(lit)) => { bridge::TokenTree::Literal(bridge::Literal { // FIXME: handle literal kinds - kind: bridge::LitKind::Err, + kind: bridge::LitKind::Integer, // dummy symbol: Symbol::intern(self.interner, &lit.text), // FIXME: handle suffixes suffix: None, diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/server/token_id.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/server/token_id.rs index edbdc67b482f..15a9e0deae44 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/server/token_id.rs +++ b/src/tools/rust-analyzer/crates/proc-macro-srv/src/server/token_id.rs @@ -64,7 +64,7 @@ impl server::FreeFunctions for TokenIdServer { ) -> Result, ()> { // FIXME: keep track of LitKind and Suffix Ok(bridge::Literal { - kind: bridge::LitKind::Err, + kind: bridge::LitKind::Integer, // dummy symbol: Symbol::intern(self.interner, s), suffix: None, span: self.call_site, @@ -187,7 +187,7 @@ impl server::TokenStream for TokenIdServer { tt::TokenTree::Leaf(tt::Leaf::Literal(lit)) => { bridge::TokenTree::Literal(bridge::Literal { // FIXME: handle literal kinds - kind: bridge::LitKind::Err, + kind: bridge::LitKind::Integer, // dummy symbol: Symbol::intern(self.interner, &lit.text), // FIXME: handle suffixes suffix: None, From ac47f6c666a6ba90c565a40ba16e56d95e36cd44 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 15 Feb 2024 15:46:38 +1100 Subject: [PATCH 17/17] Add suffixes to `LitError`. To avoid some unwrapping. --- compiler/rustc_ast/src/util/literal.rs | 24 +++++++++++++----------- compiler/rustc_session/src/errors.rs | 18 +++++++----------- 2 files changed, 20 insertions(+), 22 deletions(-) diff --git a/compiler/rustc_ast/src/util/literal.rs b/compiler/rustc_ast/src/util/literal.rs index e4bb23675cb9..5ed2762b7262 100644 --- a/compiler/rustc_ast/src/util/literal.rs +++ b/compiler/rustc_ast/src/util/literal.rs @@ -31,19 +31,21 @@ pub fn escape_byte_str_symbol(bytes: &[u8]) -> Symbol { #[derive(Debug)] pub enum LitError { - InvalidSuffix, - InvalidIntSuffix, - InvalidFloatSuffix, - NonDecimalFloat(u32), - IntTooLarge(u32), + InvalidSuffix(Symbol), + InvalidIntSuffix(Symbol), + InvalidFloatSuffix(Symbol), + NonDecimalFloat(u32), // u32 is the base + IntTooLarge(u32), // u32 is the base } impl LitKind { /// Converts literal token into a semantic literal. pub fn from_token_lit(lit: token::Lit) -> Result { let token::Lit { kind, symbol, suffix } = lit; - if suffix.is_some() && !kind.may_have_suffix() { - return Err(LitError::InvalidSuffix); + if let Some(suffix) = suffix + && !kind.may_have_suffix() + { + return Err(LitError::InvalidSuffix(suffix)); } // For byte/char/string literals, chars and escapes have already been @@ -271,12 +273,12 @@ fn filtered_float_lit( return Err(LitError::NonDecimalFloat(base)); } Ok(match suffix { - Some(suf) => LitKind::Float( + Some(suffix) => LitKind::Float( symbol, - ast::LitFloatType::Suffixed(match suf { + ast::LitFloatType::Suffixed(match suffix { sym::f32 => ast::FloatTy::F32, sym::f64 => ast::FloatTy::F64, - _ => return Err(LitError::InvalidFloatSuffix), + _ => return Err(LitError::InvalidFloatSuffix(suffix)), }), ), None => LitKind::Float(symbol, ast::LitFloatType::Unsuffixed), @@ -317,7 +319,7 @@ fn integer_lit(symbol: Symbol, suffix: Option) -> Result return filtered_float_lit(symbol, suffix, base), - _ => return Err(LitError::InvalidIntSuffix), + _ => return Err(LitError::InvalidIntSuffix(suf)), }, _ => ast::LitIntType::Unsuffixed, }; diff --git a/compiler/rustc_session/src/errors.rs b/compiler/rustc_session/src/errors.rs index f06e2136c2c5..82846e3b4e82 100644 --- a/compiler/rustc_session/src/errors.rs +++ b/compiler/rustc_session/src/errors.rs @@ -378,28 +378,24 @@ pub fn report_lit_error( valid.then(|| format!("0{}{}", base_char.to_ascii_lowercase(), &suffix[1..])) } - let token::Lit { kind, symbol, suffix } = lit; let dcx = &sess.dcx; match err { - LitError::InvalidSuffix => { - let suffix = suffix.unwrap(); - dcx.emit_err(InvalidLiteralSuffix { span, kind: kind.descr(), suffix }) + LitError::InvalidSuffix(suffix) => { + dcx.emit_err(InvalidLiteralSuffix { span, kind: lit.kind.descr(), suffix }) } - LitError::InvalidIntSuffix => { - let suf = suffix.expect("suffix error with no suffix"); - let suf = suf.as_str(); + LitError::InvalidIntSuffix(suffix) => { + let suf = suffix.as_str(); if looks_like_width_suffix(&['i', 'u'], suf) { // If it looks like a width, try to be helpful. dcx.emit_err(InvalidIntLiteralWidth { span, width: suf[1..].into() }) - } else if let Some(fixed) = fix_base_capitalisation(symbol.as_str(), suf) { + } else if let Some(fixed) = fix_base_capitalisation(lit.symbol.as_str(), suf) { dcx.emit_err(InvalidNumLiteralBasePrefix { span, fixed }) } else { dcx.emit_err(InvalidNumLiteralSuffix { span, suffix: suf.to_string() }) } } - LitError::InvalidFloatSuffix => { - let suf = suffix.expect("suffix error with no suffix"); - let suf = suf.as_str(); + LitError::InvalidFloatSuffix(suffix) => { + let suf = suffix.as_str(); if looks_like_width_suffix(&['f'], suf) { // If it looks like a width, try to be helpful. dcx.emit_err(InvalidFloatLiteralWidth { span, width: suf[1..].to_string() })