From 69edf45897dd7a72dc8a30ee53f73951981b6125 Mon Sep 17 00:00:00 2001 From: Walnut <39544927+Walnut356@users.noreply.github.com> Date: Fri, 24 Jul 2026 07:11:05 -0500 Subject: [PATCH 01/13] apply str visualizer to `*const`, `*mut` and `Box` --- src/etc/lldb_lookup.py | 18 +++++++++++-- src/etc/lldb_providers.py | 42 ++++++++++++++++++----------- tests/debuginfo/strings-and-strs.rs | 7 +++-- 3 files changed, 45 insertions(+), 22 deletions(-) diff --git a/src/etc/lldb_lookup.py b/src/etc/lldb_lookup.py index 3533d149e7494..f23081246ede7 100644 --- a/src/etc/lldb_lookup.py +++ b/src/etc/lldb_lookup.py @@ -175,14 +175,28 @@ def register_providers_compatibility(): register( StdSliceSyntheticProvider, StdStrSummaryProvider, - r"^&(mut )?str$", + r"^((&(mut )?)|(\*(const|mut) ))str$", + ) + + # Box GNU + register( + StdSliceSyntheticProvider, + StdStrSummaryProvider, + r"^(alloc::([a-z_]+::)+)Box$", ) # str MSVC register( MSVCStrSyntheticProvider, StdStrSummaryProvider, - r"^ref(_mut)?\$$", + r"^((ref(_mut)?)|(ptr_(const|mut)))\$$", + ) + + # Box MSVC + register( + MSVCStrSyntheticProvider, + StdStrSummaryProvider, + r"^(alloc::([a-z_]+::)+)Box$", ) # slice GNU diff --git a/src/etc/lldb_providers.py b/src/etc/lldb_providers.py index f6c2ab8f2b8c7..729214ff45e1e 100644 --- a/src/etc/lldb_providers.py +++ b/src/etc/lldb_providers.py @@ -1,31 +1,31 @@ from __future__ import annotations + import sys -from typing import Generator, Dict, List, TYPE_CHECKING, Optional from enum import Flag, auto +from typing import TYPE_CHECKING, Dict, Generator, List, Optional from lldb import ( SBData, SBError, + eBasicTypeChar32, + eBasicTypeDouble, + eBasicTypeFloat, + eBasicTypeHalf, eBasicTypeLong, - eBasicTypeUnsignedLong, + eBasicTypeLongLong, + eBasicTypeShort, + eBasicTypeSignedChar, eBasicTypeUnsignedChar, - eBasicTypeUnsignedShort, + eBasicTypeUnsignedLong, eBasicTypeUnsignedLongLong, - eBasicTypeSignedChar, - eBasicTypeShort, - eBasicTypeLongLong, - eBasicTypeFloat, - eBasicTypeDouble, - eBasicTypeHalf, - eBasicTypeChar32, + eBasicTypeUnsignedShort, eFormatChar, eTypeIsInteger, ) - from rust_types import is_tuple_fields if TYPE_CHECKING: - from lldb import SBValue, SBType, SBTypeStaticField, SBTarget, SBProcess + from lldb import SBProcess, SBTarget, SBType, SBTypeStaticField, SBValue # from lldb.formatters import Logger @@ -564,7 +564,13 @@ def get_child_at_index(self, index: int) -> Optional[SBValue]: class MSVCStrSyntheticProvider: - __slots__ = ["valobj", "data_ptr", "length"] + _name_map: Dict[str, str] = { + "ref$": "&str", + "ref_mut$": "&mut str", + "ptr_const$": "*const str", + "ptr_mut$": "*mut str", + } + __slots__ = ["data_ptr", "length", "valobj"] def __init__(self, valobj: SBValue, _dict: LLDBOpaque): self.valobj = valobj @@ -598,10 +604,14 @@ def get_child_at_index(self, index: int) -> Optional[SBValue]: return element def get_type_name(self): - if self.valobj.GetTypeName().startswith("ref_mut"): - return "&mut str" + name = self.valobj.GetTypeName() + + if (type_name := self._name_map.get(name)) is not None: + return type_name + elif name.startswith("alloc::boxed::Box" else: - return "&str" + return name def _getVariantName(variant: SBValue) -> str: diff --git a/tests/debuginfo/strings-and-strs.rs b/tests/debuginfo/strings-and-strs.rs index ee2702d1bcf74..a860aa6106d07 100644 --- a/tests/debuginfo/strings-and-strs.rs +++ b/tests/debuginfo/strings-and-strs.rs @@ -1,6 +1,5 @@ //@ min-gdb-version: 15.1 // LLDB 1800+ tests were not tested in CI, broke, and now are disabled -//@ ignore-lldb //@ compile-flags:-g //@ disable-gdb-pretty-printers @@ -38,16 +37,16 @@ //@ lldb-check:(&str) plain_str = "Hello" { [0] = 'H' [1] = 'e' [2] = 'l' [3] = 'l' [4] = 'o' } //@ lldb-command:v str_in_struct -//@ lldb-check:(strings_and_strs::Foo) str_in_struct = { inner = "Hello" { [0] = 'H' [1] = 'e' [2] = 'l' [3] = 'l' [4] = 'o' } } +//@ lldb-check:(strings_and_strs::Foo) str_in_struct = {inner:"Hello"} //@ lldb-command:v str_in_tuple -//@ lldb-check:((&str, &str)) str_in_tuple = ("Hello", "World") { 0 = "Hello" { [0] = 'H' [1] = 'e' [2] = 'l' [3] = 'l' [4] = 'o' } 1 = "World" { [0] = 'W' [1] = 'o' [2] = 'r' [3] = 'l' [4] = 'd' } } +//@ lldb-check:((&str, &str)) str_in_tuple = ("Hello", "World") //@ lldb-command:v str_in_rc //@ lldb-check:(alloc::rc::Rc<&str, alloc::alloc::Global>) str_in_rc = strong=1, weak=0 { value = "Hello" { [0] = 'H' [1] = 'e' [2] = 'l' [3] = 'l' [4] = 'o' } } //@ lldb-command:v box_str -//@ lldb-check:(alloc::boxed::Box) box_str = { __0 = { pointer = { pointer = { data_ptr = 0x[...] "World" length = 5 } } _marker = } __1 = } +//@ lldb-check:(alloc::boxed::Box) box_str = "World" { [0] = 'W' [1] = 'o' [2] = 'r' [3] = 'l' [4] = 'd' } //@ lldb-command:v rc_str //@ lldb-check:(alloc::rc::Rc) rc_str = strong=1, weak=0 { value = "World" } From ef9e727583af49b5c6a919b1879cf28ebd5a4a02 Mon Sep 17 00:00:00 2001 From: Alice Ryhl Date: Mon, 25 May 2026 20:36:32 +0000 Subject: [PATCH 02/13] Generalize PinCoerceUnsized into a new PinSafePointer trait --- library/alloc/src/boxed.rs | 23 ++++- library/alloc/src/rc.rs | 13 ++- library/alloc/src/sync.rs | 14 ++- library/core/src/cell.rs | 12 ++- library/core/src/pin.rs | 184 ++++++++++++++++++++++++++++++------- 5 files changed, 201 insertions(+), 45 deletions(-) diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs index 90a2330629c1c..cd2508a76a10e 100644 --- a/library/alloc/src/boxed.rs +++ b/library/alloc/src/boxed.rs @@ -200,7 +200,7 @@ use core::ops::{ }; #[cfg(not(no_global_oom_handling))] use core::ops::{Residual, Try}; -use core::pin::{Pin, PinCoerceUnsized}; +use core::pin::{Pin, PinSafePointer}; use core::ptr::{self, NonNull, Unique}; use core::task::{Context, Poll}; @@ -2365,8 +2365,27 @@ impl + ?Sized, A: Allocator> AsyncFn for Box #[unstable(feature = "coerce_unsized", issue = "18598")] impl, U: ?Sized, A: Allocator> CoerceUnsized> for Box {} +// A pointer can only be pin safe if it does not implement certain safe traits +// maliciously. Since `Box` is fundamental, downstream crates may be able to +// implement those traits for `Box`, so we must carefully check that +// this is not a problem for each trait. +// +// The `Box` type always implements `Deref` and `DerefMut`, so despite being +// fundamental, downstream crates cannot implement these traits for +// `Box`. +// +// Conversely, downstream crates are able to implement `Clone`, `Debug`, and +// `Display` for `Box` as long as `LocalType` does not implement +// said trait. However, the `Box` type does not treat the existence of an +// `&Box` as evidence that the `T` is not pinned, so this is not +// problematic. +// +// Finally, even if downstream crates provide their own implementation of +// `Clone` for `Box`, it is not problematic for the cloned box to be +// wrapped in `Pin`, since the same conversion could have been carried out +// safely as `Box::pin((*p).clone())`. #[unstable(feature = "pin_coerce_unsized_trait", issue = "150112")] -unsafe impl PinCoerceUnsized for Box {} +unsafe impl PinSafePointer for Box {} // It is quite crucial that we only allow the `Global` allocator here. // Handling arbitrary custom allocators (which can affect the `Box` layout heavily!) diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index ffd02e2f4f6e5..84df5e1ff28e1 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -260,7 +260,7 @@ use core::ops::{Residual, Try}; use core::panic::{RefUnwindSafe, UnwindSafe}; #[cfg(not(no_global_oom_handling))] use core::pin::Pin; -use core::pin::PinCoerceUnsized; +use core::pin::PinSafePointer; use core::ptr::{self, NonNull, drop_in_place}; #[cfg(not(no_global_oom_handling))] use core::slice::from_raw_parts_mut; @@ -2446,12 +2446,19 @@ impl Deref for Rc { } } +// The API of this pointer type enforces that if the `T` is pinned, then *all* +// clones of this `Rc` are wrapped as `Pin>`. Since an `&Rc` could +// be used to obtain an `Rc` that is not wrapped in `Pin` (and later used +// with `Rc::get_mut`), this means that this type treats `&Rc` as evidence +// that the `T` is not pinned. The implementations of various traits are written +// accordingly. Since this type is not fundamental, downstream crates cannot +// provide malicious implementations of any of the traits relevant for `Pin`. #[unstable(feature = "pin_coerce_unsized_trait", issue = "150112")] -unsafe impl PinCoerceUnsized for Rc {} +unsafe impl PinSafePointer for Rc {} //#[unstable(feature = "unique_rc_arc", issue = "112566")] #[unstable(feature = "pin_coerce_unsized_trait", issue = "150112")] -unsafe impl PinCoerceUnsized for UniqueRc {} +unsafe impl PinSafePointer for UniqueRc {} #[unstable(feature = "deref_pure_trait", issue = "87121")] unsafe impl DerefPure for Rc {} diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index 4f86d6c596050..18fc19cba27d1 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -25,7 +25,7 @@ use core::ops::{CoerceUnsized, Deref, DerefMut, DerefPure, DispatchFromDyn, Lega #[cfg(not(no_global_oom_handling))] use core::ops::{Residual, Try}; use core::panic::{RefUnwindSafe, UnwindSafe}; -use core::pin::{Pin, PinCoerceUnsized}; +use core::pin::{Pin, PinSafePointer}; use core::ptr::{self, NonNull}; #[cfg(not(no_global_oom_handling))] use core::slice::from_raw_parts_mut; @@ -2453,8 +2453,16 @@ impl Deref for Arc { } } +// The API of this pointer type enforces that if the `T` is pinned, then *all* +// clones of this `Arc` are wrapped as `Pin>`. Since an `&Arc` +// could be used to obtain an `Arc` that is not wrapped in `Pin` (and later +// used with `Arc::get_mut`), this means that this type treats `&Arc` as +// evidence that the `T` is not pinned. The implementations of various traits +// are written accordingly. Since this type is not fundamental, downstream +// crates cannot provide malicious implementations of any of the traits relevant +// for `Pin`. #[unstable(feature = "pin_coerce_unsized_trait", issue = "150112")] -unsafe impl PinCoerceUnsized for Arc {} +unsafe impl PinSafePointer for Arc {} #[unstable(feature = "deref_pure_trait", issue = "87121")] unsafe impl DerefPure for Arc {} @@ -4914,7 +4922,7 @@ impl Deref for UniqueArc { // #[unstable(feature = "unique_rc_arc", issue = "112566")] #[unstable(feature = "pin_coerce_unsized_trait", issue = "150112")] -unsafe impl PinCoerceUnsized for UniqueArc {} +unsafe impl PinSafePointer for UniqueArc {} #[unstable(feature = "unique_rc_arc", issue = "112566")] impl DerefMut for UniqueArc { diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs index 0e18d2bcc8469..2dc2c5981cafd 100644 --- a/library/core/src/cell.rs +++ b/library/core/src/cell.rs @@ -255,7 +255,7 @@ use crate::marker::{Destruct, PhantomData, Unsize}; use crate::mem::{self, ManuallyDrop}; use crate::ops::{self, CoerceUnsized, Deref, DerefMut, DerefPure, DispatchFromDyn}; use crate::panic::const_panic; -use crate::pin::PinCoerceUnsized; +use crate::pin::PinSafePointer; use crate::ptr::{self, NonNull}; use crate::range; @@ -2710,8 +2710,14 @@ fn assert_coerce_unsized( let _: RefCell<&dyn Send> = d; } +// The implementations of Deref/DerefMut are not malicious, so we can allow the +// user to perform unsizing coercions with `Pin>` pointers if they +// can manage to create one. #[unstable(feature = "pin_coerce_unsized_trait", issue = "150112")] -unsafe impl<'b, T: ?Sized> PinCoerceUnsized for Ref<'b, T> {} +unsafe impl<'b, T: ?Sized> PinSafePointer for Ref<'b, T> {} +// The implementations of Deref/DerefMut are not malicious, so we can allow the +// user to perform unsizing coercions with `Pin>` pointers if they +// can manage to create one. #[unstable(feature = "pin_coerce_unsized_trait", issue = "150112")] -unsafe impl<'b, T: ?Sized> PinCoerceUnsized for RefMut<'b, T> {} +unsafe impl<'b, T: ?Sized> PinSafePointer for RefMut<'b, T> {} diff --git a/library/core/src/pin.rs b/library/core/src/pin.rs index 931eafef61501..52a84082f3b92 100644 --- a/library/core/src/pin.rs +++ b/library/core/src/pin.rs @@ -1080,9 +1080,8 @@ pub use self::unsafe_pinned::UnsafePinned; /// [subtle-details]: self#subtle-details-and-the-drop-guarantee "pin subtle details" /// [`unsafe`]: ../../std/keyword.unsafe.html "keyword unsafe" // -// Note: the `Clone` derive below causes unsoundness as it's possible to implement -// `Clone` for mutable references. -// See for more details. +// Note: the `Clone` derive below is sound because either `Ptr: PinSafePointer` +// or the pointee is `Unpin`. #[stable(feature = "pin", since = "1.33.0")] #[lang = "pin"] #[fundamental] @@ -1097,7 +1096,8 @@ pub struct Pin { // issues. `&self.pointer` should not be accessible to untrusted trait // implementations. // -// See for more details. +// See and the +// `PinSafePointer` trait for more details. #[stable(feature = "pin_trait_impls", since = "1.41.0")] impl PartialEq> for Pin @@ -1230,11 +1230,15 @@ impl Pin { /// points to is pinned, that is a violation of the API contract and may lead to undefined /// behavior in later (even safe) operations. /// - /// By using this method, you are also making a promise about the [`Deref`], - /// [`DerefMut`], and [`Drop`] implementations of `Ptr`, if they exist. Most importantly, they - /// must not move out of their `self` arguments: `Pin::as_mut` and `Pin::as_ref` - /// will call `DerefMut::deref_mut` and `Deref::deref` *on the pointer type `Ptr`* - /// and expect these methods to uphold the pinning invariants. + /// By using this method, you are also making a promise about several trait + /// implementations of `Ptr` itself, if they exist. Most importantly, they + /// must not move out of their `self` arguments: `Pin::as_mut` and + /// `Pin::as_ref` will call `DerefMut::deref_mut` and `Deref::deref` *on the + /// pointer type `Ptr`* and expect these methods to uphold the pinning + /// invariants. These requirements are specified in more detail on the + /// [`PinSafePointer`] trait, and `Ptr` must abide by the safety + /// requirements of that trait. + /// /// Moreover, by calling this method you promise that the reference `Ptr` /// dereferences to will not be moved out of again; in particular, it /// must not be possible to obtain a `&mut Ptr::Target` and then @@ -1690,7 +1694,7 @@ const impl Deref for Pin { mod helper { /// Helper that prevents downstream crates from implementing `DerefMut` for `Pin`. /// - /// The `Pin` type implements the unsafe trait `PinCoerceUnsized`, which essentially requires + /// The `Pin` type implements the unsafe trait `PinSafePointer`, which essentially requires /// that the type does not have a malicious `Deref` or `DerefMut` impl. However, without this /// helper module, downstream crates are able to write `impl DerefMut for Pin` as /// long as it does not overlap with the impl provided by stdlib. This is because `Pin` is @@ -1781,6 +1785,10 @@ unsafe impl DerefPure for Pin {} #[unstable(feature = "legacy_receiver_trait", issue = "none")] impl LegacyReceiver for Pin {} +// The following implementations allow untrusted trait implementations to access +// `&self.pointer`, which is only sound because these traits are mentioned in +// the safety requirements of `PinSafePointer`. + #[stable(feature = "pin", since = "1.33.0")] impl fmt::Debug for Pin { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { @@ -1810,49 +1818,157 @@ impl fmt::Pointer for Pin { #[stable(feature = "pin", since = "1.33.0")] impl CoerceUnsized> for Pin where - Ptr: CoerceUnsized + PinCoerceUnsized, - U: PinCoerceUnsized, + Ptr: CoerceUnsized + PinSafePointer, + U: PinSafePointer, { } #[stable(feature = "pin", since = "1.33.0")] impl DispatchFromDyn> for Pin where - Ptr: DispatchFromDyn + PinCoerceUnsized, - U: PinCoerceUnsized, + Ptr: DispatchFromDyn + PinSafePointer, + U: PinSafePointer, { } #[unstable(feature = "pin_coerce_unsized_trait", issue = "150112")] -/// Trait that indicates that this is a pointer or a wrapper for one, where -/// unsizing can be performed on the pointee when it is pinned. +/// Trait that indicates that this is a pointer that does not misbehave when +/// combined with [`Pin`]. +/// +/// Note that for backwards compatibility reasons, it is possible to create a +/// [`Pin

`] for pointer types `P` that do not implement this trait. However, +/// this can only be done safely if `

::Target` implements `Unpin`, +/// which means that pinning has no effect. /// /// # Safety /// -/// Given a pointer of this type, the concrete type returned by its -/// `deref` method and (if it implements `DerefMut`) its `deref_mut` method -/// must be the same type and must not change without a modification. -/// The following operations are not considered modifications: -/// -/// * Moving the pointer. -/// * Performing unsizing coercions on the pointer. -/// * Performing dynamic dispatch with the pointer. -/// * Calling `deref` or `deref_mut` on the pointer. -/// -/// The concrete type of a trait object is the type that the vtable corresponds -/// to. The concrete type of a slice is an array of the same element type and -/// the length specified in the metadata. The concrete type of a sized type -/// is the type itself. -pub unsafe trait PinCoerceUnsized: Deref {} +/// Types that implement this trait must not provide "malicious" implementations +/// of any safe traits used by [`Pin`]. +/// +/// ## The pointer must always reference the same object +/// +/// Calls to [`deref`]/[`deref_mut`] on the same `Pin

` instance must always +/// refer to the same object. That is, the address returned by these methods +/// must not change. This applies even if the pointer type is moved. +/// +/// These coercions must also not change the underlying concrete type. Here, the +/// concrete type of a trait object is the type that the vtable corresponds to. +/// The concrete type of a slice is an array of the same element type and the +/// length specified in the metadata. The concrete type of a sized type is the +/// type itself. +/// +/// As an example, after unsizing coercing a pinned pointer, `deref_mut` must +/// not return a `#[repr(transparent)]` wrapper around the value it referenced +/// before being unsized, even if the address is unchanged. +/// +/// ## The pointer must not move its pointee +/// +/// The [`deref_mut`] method and the pointer type's destructor are called with a +/// `&mut self` receiver, but they must behave as-if it was a `self: Pin<&mut +/// Self>` receiver. That is, they must not move out of the underlying value. +/// +/// As an example, `deref_mut` must not invoke `swap` on the inner value. +/// +/// ## Shared access to the pointer +/// +/// If this pointer type uses `&P` references as evidence that this value is not +/// pinned, then it must not treat the `&self` argument passed to [`Clone`] or +/// the formatting traits ([`fmt::Debug`], [`fmt::Display`], [`fmt::Pointer`]) +/// as such evidence. +/// +/// As an example, given a `Pin>` there is no way to obtain an `&Arc` +/// (note that `Deref` just gives a `&T`). Because of this, the [`Arc`] type can +/// assume that an `&Arc` value can only exist if the `T` is not pinned, +/// which justifies the soundness of the [`Arc::get_mut`] method. +/// +/// ## Cloning pinned pointers +/// +/// When a [`Pin

`] is cloned, the `P` pointer value returned by `clone` is +/// passed to [`Pin::new_unchecked`]. The implementation of [`Clone`] must +/// return a value such that this is sound. +/// +/// For example, when a `Pin<&T>` is cloned, the resulting `&T` points at the +/// same value. The value is known to be pinned since a `Pin<&T>` to it exists, +/// so it is safe to wrap the `&T` returned by `clone` in `Pin`. +/// +/// [`deref`]: Deref::deref +/// [`deref_mut`]: DerefMut::deref_mut +/// [`clone`]: Clone::clone +/// [`Arc`]: ../../std/sync/struct.Arc.html "Arc" +/// [`Arc::get_mut`]: ../../std/sync/struct.Arc.html#method.get_mut "Arc::get_mut" +pub unsafe trait PinSafePointer: Deref + Sized {} +// A pointer can only be pin safe if it does not implement certain safe traits +// maliciously. Since `&T` is fundamental, downstream crates may be able to +// implement those traits for `&LocalType`, so we must carefully check that +// this is not a problem for each trait. +// +// The `&T` type always implements [`Deref`] and [`Clone`], so despite being +// fundamental, downstream crates cannot implement these traits for +// `&LocalType`. +// +// The `&T` type has a negative blanket implementations for [`DerefMut`], so +// downstream crates cannot implement `DerefMut` for `&LocalType`. +// +// Conversely, downstream crates are able to implement `Debug` and `Display` for +// `&LocalType` as long as `LocalType` does not implement said trait. However, +// the existence of an `&&T` cannot be treated as evidence that the `T` is not +// pinned, so this is not problematic. #[stable(feature = "pin", since = "1.33.0")] -unsafe impl<'a, T: ?Sized> PinCoerceUnsized for &'a T {} +unsafe impl<'a, T: ?Sized> PinSafePointer for &'a T {} +// A pointer can only be pin safe if it does not implement certain safe traits +// maliciously. Since `&mut T` is fundamental, downstream crates may be able to +// implement those traits for `&mut LocalType`, so we must carefully check that +// this is not a problem for each trait. +// +// The `&mut T` type always implements [`Deref`] and [`DerefMut`], so despite +// being fundamental, downstream crates cannot implement these traits for `&mut +// LocalType`. +// +// The `&mut T` type has a negative blanket implementations for [`Clone`], so +// downstream crates cannot implement `Clone` for `&mut LocalType`. +// +// Conversely, downstream crates are able to implement `Debug` and `Display` +// for `&mut LocalType` as long as `LocalType` does not implement said trait. +// However, the existence of an `&&mut T` cannot be treated as evidence that the +// `T` is not pinned, so this is not problematic. #[stable(feature = "pin", since = "1.33.0")] -unsafe impl<'a, T: ?Sized> PinCoerceUnsized for &'a mut T {} +unsafe impl<'a, T: ?Sized> PinSafePointer for &'a mut T {} +// A pointer can only be pin safe if it does not implement certain safe traits +// maliciously. `Pin` implements these traits by forwarding to `P`, which also +// asserts that these implementations are not malicious, so the implementations +// provided by `core` are ok. However, since `Pin` is fundamental, +// downstream crates may be able to implement those traits for `Pin` +// directly, so we must carefully check that if a downstream crate can +// implement these traits for `Pin`, then this does not lead to any +// problems for the `Pin>` type. +// +// The `Pin

` type only implements `Deref` when `P: Deref`, so downstream +// crates can implement `Deref` for `Pin` in cases where `LocalType: +// !Deref`. However, as `Deref` is a super-trait for `PinSafePointer`, we do +// not assert that `Pin

` is pin safe in that scenario. +// +// The `Pin

` type only implements `DerefMut` when `P: DerefMut` and +// `P::Target: Unpin`, so normally downstream crates would be able to provide +// an implementation of `DerefMut` for `Pin` when `LocalType` does +// not satisfy those conditions. However, a special hack is used to prevent +// such downstream implementations, so this is not a problem. See +// [#145608](https://github.com/rust-lang/rust/pull/145608) for details. +// +// Conversely, downstream crates are able to implement `Clone`, `Debug` and +// `Display` for `Pin` as long as `LocalType` does not implement +// said trait. However, the existence of an `&Pin

` cannot be treated as +// evidence that the value is not pinned, so this is not problematic. +// +// Furthermore, in the case of `Clone`, cloning a `Pin>` will utilize +// `Pin::new_unchecked` to convert from `Pin

` to `Pin>`. However, +// given that the implementation of `Clone` returned a `Pin

`, we know that +// the target value is pinned, so this conversion is okay even if `Clone` was +// implemented for `Pin

` by a downstream crate. #[stable(feature = "pin", since = "1.33.0")] -unsafe impl PinCoerceUnsized for Pin {} +unsafe impl PinSafePointer for Pin

{} /// Constructs a [Pin]<[&mut] T>, by pinning a `value: T` locally. /// From aed866a14209b8a2262b6333d3a3c74be6e6de87 Mon Sep 17 00:00:00 2001 From: Yukang Date: Fri, 7 Aug 2026 09:24:14 +0800 Subject: [PATCH 03/13] Suggest add async for function sig with return expr in body --- .../rustc_trait_selection/src/diagnostics.rs | 12 ++++ .../src/error_reporting/infer/suggest.rs | 70 +++++++++++++++++-- ...returned-future-ineligible-issue-159495.rs | 29 ++++++++ ...rned-future-ineligible-issue-159495.stderr | 17 +++++ ...-fn-for-returned-future-issue-159495.fixed | 36 ++++++++++ ...ync-fn-for-returned-future-issue-159495.rs | 36 ++++++++++ ...fn-for-returned-future-issue-159495.stderr | 55 +++++++++++++++ 7 files changed, 251 insertions(+), 4 deletions(-) create mode 100644 tests/ui/async-await/suggest-async-fn-for-returned-future-ineligible-issue-159495.rs create mode 100644 tests/ui/async-await/suggest-async-fn-for-returned-future-ineligible-issue-159495.stderr create mode 100644 tests/ui/async-await/suggest-async-fn-for-returned-future-issue-159495.fixed create mode 100644 tests/ui/async-await/suggest-async-fn-for-returned-future-issue-159495.rs create mode 100644 tests/ui/async-await/suggest-async-fn-for-returned-future-issue-159495.stderr diff --git a/compiler/rustc_trait_selection/src/diagnostics.rs b/compiler/rustc_trait_selection/src/diagnostics.rs index 44b5e669d5251..eea574a70cb3f 100644 --- a/compiler/rustc_trait_selection/src/diagnostics.rs +++ b/compiler/rustc_trait_selection/src/diagnostics.rs @@ -1426,6 +1426,18 @@ pub(crate) enum ConsiderAddingAwait { #[suggestion_part(code = ".await")] spans: Vec, }, + #[multipart_suggestion( + "consider making the function `async` and `await`ing on the `Future`", + style = "verbose", + applicability = "maybe-incorrect" + )] + MakeFunctionAsync { + #[suggestion_part(code = "{async_prefix}")] + async_span: Span, + async_prefix: String, + #[suggestion_part(code = ".await")] + await_span: Span, + }, } #[derive(Diagnostic)] diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/suggest.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/suggest.rs index 5bd9a9c52de7f..db852701051cf 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/suggest.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/suggest.rs @@ -159,8 +159,9 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { /// ``` /// /// This routine checks if the found type `T` implements `Future` where `U` is the - /// expected type. If this is the case, and we are inside of an async body, it suggests adding - /// `.await` to the tail of the expression. + /// expected type. In an async body, it suggests adding `.await` to the expression. For a + /// return expression in a synchronous function, it suggests making the function async and + /// awaiting the expression together. pub(super) fn suggest_await_on_expect_found( &self, cause: &ObligationCause<'tcx>, @@ -178,11 +179,14 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { hir::CoroutineDesugaring::Async | hir::CoroutineDesugaring::AsyncGen, _, )) => (), - None - | Some( + Some( hir::CoroutineKind::Coroutine(_) | hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Gen, _), ) => return, + None => { + self.suggest_add_async_for_tail_return_expr(cause, exp_span, exp_found, diag); + return; + } } if let ObligationCauseCode::CompareImplItem { .. } = cause.code() { @@ -268,6 +272,64 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { } } + fn suggest_add_async_for_tail_return_expr( + &self, + cause: &ObligationCause<'tcx>, + exp_span: Span, + exp_found: &ty::error::ExpectedFound>, + diag: &mut Diag<'_>, + ) { + let (ObligationCauseCode::BlockTailExpression(return_hir_id, ..) + | ObligationCauseCode::ReturnValue(return_hir_id)) = cause.code() + else { + return; + }; + + let body_def_id = cause.body_def_id; + if !self.tcx.sess.at_least_rust_2018() || self.tcx.is_entrypoint(body_def_id.to_def_id()) { + return; + } + + let node = self.tcx.hir_node_by_def_id(body_def_id); + let (item_span, vis_span) = match node { + Node::Item(item) if matches!(item.kind, hir::ItemKind::Fn { .. }) => { + (item.span, item.vis_span) + } + Node::ImplItem(item) if matches!(item.kind, hir::ImplItemKind::Fn(..)) => { + let Some(vis_span) = item.vis_span() else { return }; + (item.span, vis_span) + } + _ => return, + }; + let Some(sig) = node.fn_sig() else { + return; + }; + if sig.header.asyncness.is_async() + || sig.header.constness != hir::Constness::NotConst + || item_span.from_expansion() + { + return; + } + + let (async_span, async_prefix) = if vis_span.is_empty() { + (item_span.shrink_to_lo(), "async ".to_string()) + } else { + (vis_span.shrink_to_hi(), " async".to_string()) + }; + let body_hir_id = self.tcx.local_def_id_to_hir_id(body_def_id); + if self.tcx.hir_get_fn_id_for_return_block(*return_hir_id) == Some(body_hir_id) + && let Some(found) = self.tcx.get_impl_future_output_ty(exp_found.found) + && self.same_type_modulo_infer(exp_found.expected, found) + && exp_span.can_be_used_for_suggestions() + { + diag.subdiagnostic(ConsiderAddingAwait::MakeFunctionAsync { + async_span, + async_prefix, + await_span: exp_span.shrink_to_hi(), + }); + } + } + pub(super) fn suggest_accessing_field_where_appropriate( &self, cause: &ObligationCause<'tcx>, diff --git a/tests/ui/async-await/suggest-async-fn-for-returned-future-ineligible-issue-159495.rs b/tests/ui/async-await/suggest-async-fn-for-returned-future-ineligible-issue-159495.rs new file mode 100644 index 0000000000000..fa65f7ec77b4f --- /dev/null +++ b/tests/ui/async-await/suggest-async-fn-for-returned-future-ineligible-issue-159495.rs @@ -0,0 +1,29 @@ +//@ edition: 2018 + +// Do not suggest changing a function when the future is not its return value or when doing so +// would make a trait method incompatible with its declaration. + +async fn number() -> i32 { + 42 +} + +// A local block tail does not contribute to the function's return value. +fn local_block() { + let _: i32 = { number() }; + //~^ ERROR mismatched types +} + +struct Wrapper; + +trait Trait { + fn trait_method() -> i32; +} + +impl Trait for Wrapper { + fn trait_method() -> i32 { + number() + //~^ ERROR mismatched types + } +} + +fn main() {} diff --git a/tests/ui/async-await/suggest-async-fn-for-returned-future-ineligible-issue-159495.stderr b/tests/ui/async-await/suggest-async-fn-for-returned-future-ineligible-issue-159495.stderr new file mode 100644 index 0000000000000..9efba3a55df66 --- /dev/null +++ b/tests/ui/async-await/suggest-async-fn-for-returned-future-ineligible-issue-159495.stderr @@ -0,0 +1,17 @@ +error[E0308]: mismatched types + --> $DIR/suggest-async-fn-for-returned-future-ineligible-issue-159495.rs:12:20 + | +LL | let _: i32 = { number() }; + | ^^^^^^^^ expected `i32`, found future + +error[E0308]: mismatched types + --> $DIR/suggest-async-fn-for-returned-future-ineligible-issue-159495.rs:24:9 + | +LL | fn trait_method() -> i32 { + | --- expected `i32` because of return type +LL | number() + | ^^^^^^^^ expected `i32`, found future + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/async-await/suggest-async-fn-for-returned-future-issue-159495.fixed b/tests/ui/async-await/suggest-async-fn-for-returned-future-issue-159495.fixed new file mode 100644 index 0000000000000..d0312ce7d726a --- /dev/null +++ b/tests/ui/async-await/suggest-async-fn-for-returned-future-issue-159495.fixed @@ -0,0 +1,36 @@ +//@ edition: 2021 +//@ run-rustfix + +#![allow(dead_code, unused_must_use)] + +// Suggest making eligible enclosing functions async when a return expression produces a future. + +async fn number() -> i32 { + 42 +} + +async fn unit() {} + +async fn wrapped_number() -> i32 { + number().await + //~^ ERROR mismatched types +} + +async fn explicit_return() -> i32 { + return number().await; + //~^ ERROR mismatched types +} + +struct Wrapper; + +impl Wrapper { + pub async unsafe fn inherent_method() -> i32 { + number().await + //~^ ERROR mismatched types + } +} + +fn main() { + unit(); + //~^ ERROR mismatched types +} diff --git a/tests/ui/async-await/suggest-async-fn-for-returned-future-issue-159495.rs b/tests/ui/async-await/suggest-async-fn-for-returned-future-issue-159495.rs new file mode 100644 index 0000000000000..ab1e05d95a8b8 --- /dev/null +++ b/tests/ui/async-await/suggest-async-fn-for-returned-future-issue-159495.rs @@ -0,0 +1,36 @@ +//@ edition: 2021 +//@ run-rustfix + +#![allow(dead_code, unused_must_use)] + +// Suggest making eligible enclosing functions async when a return expression produces a future. + +async fn number() -> i32 { + 42 +} + +async fn unit() {} + +fn wrapped_number() -> i32 { + number() + //~^ ERROR mismatched types +} + +fn explicit_return() -> i32 { + return number(); + //~^ ERROR mismatched types +} + +struct Wrapper; + +impl Wrapper { + pub unsafe fn inherent_method() -> i32 { + number() + //~^ ERROR mismatched types + } +} + +fn main() { + unit() + //~^ ERROR mismatched types +} diff --git a/tests/ui/async-await/suggest-async-fn-for-returned-future-issue-159495.stderr b/tests/ui/async-await/suggest-async-fn-for-returned-future-issue-159495.stderr new file mode 100644 index 0000000000000..dd0abc84e6a18 --- /dev/null +++ b/tests/ui/async-await/suggest-async-fn-for-returned-future-issue-159495.stderr @@ -0,0 +1,55 @@ +error[E0308]: mismatched types + --> $DIR/suggest-async-fn-for-returned-future-issue-159495.rs:15:5 + | +LL | fn wrapped_number() -> i32 { + | --- expected `i32` because of return type +LL | number() + | ^^^^^^^^ expected `i32`, found future + | +help: consider making the function `async` and `await`ing on the `Future` + | +LL ~ async fn wrapped_number() -> i32 { +LL ~ number().await + | + +error[E0308]: mismatched types + --> $DIR/suggest-async-fn-for-returned-future-issue-159495.rs:20:12 + | +LL | fn explicit_return() -> i32 { + | --- expected `i32` because of return type +LL | return number(); + | ^^^^^^^^ expected `i32`, found future + | +help: consider making the function `async` and `await`ing on the `Future` + | +LL ~ async fn explicit_return() -> i32 { +LL ~ return number().await; + | + +error[E0308]: mismatched types + --> $DIR/suggest-async-fn-for-returned-future-issue-159495.rs:28:9 + | +LL | pub unsafe fn inherent_method() -> i32 { + | --- expected `i32` because of return type +LL | number() + | ^^^^^^^^ expected `i32`, found future + | +help: consider making the function `async` and `await`ing on the `Future` + | +LL ~ pub async unsafe fn inherent_method() -> i32 { +LL ~ number().await + | + +error[E0308]: mismatched types + --> $DIR/suggest-async-fn-for-returned-future-issue-159495.rs:34:5 + | +LL | fn main() { + | - expected `()` because of default return type +LL | unit() + | ^^^^^^- help: consider using a semicolon here: `;` + | | + | expected `()`, found future + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0308`. From 8109a4b8cf9a3ed87626e0f357b5b2aed954e312 Mon Sep 17 00:00:00 2001 From: SomeFlyingThing <306498559+SomeFlyingThing@users.noreply.github.com> Date: Fri, 7 Aug 2026 21:35:01 -0700 Subject: [PATCH 04/13] Optimize slice::contains for one-byte BytewiseEq types --- library/core/src/cmp/bytewise.rs | 2 +- library/core/src/slice/cmp.rs | 38 ++++++++----------- library/coretests/tests/slice.rs | 21 ++++++++++ .../lib-optimizations/slice-contains.rs | 30 ++++++++++++++- 4 files changed, 66 insertions(+), 25 deletions(-) diff --git a/library/core/src/cmp/bytewise.rs b/library/core/src/cmp/bytewise.rs index 88b83b5273dbe..07e24441cf51d 100644 --- a/library/core/src/cmp/bytewise.rs +++ b/library/core/src/cmp/bytewise.rs @@ -33,7 +33,7 @@ is_bytewise_comparable!(u8, u16, u32, u64, u128, usize, i8, i16, i32, i64, i128, // SAFETY: These have *niches*, but no *padding* and no *provenance*, // so we can compare them directly. -is_bytewise_comparable!(bool, char, super::Ordering); +is_bytewise_comparable!(bool, char, super::Ordering, crate::ascii::Char); // SAFETY: Similarly, the `NonZero` type has a niche, but no undef and no pointers, // and they compare like their underlying numeric type. diff --git a/library/core/src/slice/cmp.rs b/library/core/src/slice/cmp.rs index 3a62e7f61b2b4..9c670d360b633 100644 --- a/library/core/src/slice/cmp.rs +++ b/library/core/src/slice/cmp.rs @@ -391,29 +391,23 @@ where } } -impl SliceContains for T { +impl SliceContains for T { #[inline] - fn slice_contains(&self, x: &[Self]) -> bool { - // SAFETY: `UnsignedBytewiseOrd` guarantees that `Self` has the same - // layout as `u8` and is initialized, so both the value and slice can - // be read as bytes. - let (byte, bytes) = unsafe { - (*(self as *const Self).cast::(), from_raw_parts(x.as_ptr().cast::(), x.len())) - }; - memchr::memchr(byte, bytes).is_some() - } -} - -impl SliceContains for i8 { - #[inline] - fn slice_contains(&self, x: &[Self]) -> bool { - let byte = *self as u8; - // SAFETY: `i8` and `u8` have the same memory layout, thus casting `x.as_ptr()` - // as `*const u8` is safe. The `x.as_ptr()` comes from a reference and is thus guaranteed - // to be valid for reads for the length of the slice `x.len()`, which cannot be larger - // than `isize::MAX`. The returned slice is never mutated. - let bytes: &[u8] = unsafe { from_raw_parts(x.as_ptr() as *const u8, x.len()) }; - memchr::memchr(byte, bytes).is_some() + default fn slice_contains(&self, x: &[Self]) -> bool { + if size_of::() == 1 { + // SAFETY: `BytewiseEq` guarantees that values have no padding or provenance and + // compare like their underlying bytes. Since `T` is one byte, both the value and + // slice can be read as `u8`s. + let (byte, bytes) = unsafe { + ( + *(self as *const Self).cast::(), + from_raw_parts(x.as_ptr().cast::(), x.len()), + ) + }; + memchr::memchr(byte, bytes).is_some() + } else { + x.iter().any(|y| *y == *self) + } } } diff --git a/library/coretests/tests/slice.rs b/library/coretests/tests/slice.rs index 276aab67085b3..9b0db0e733c57 100644 --- a/library/coretests/tests/slice.rs +++ b/library/coretests/tests/slice.rs @@ -28,6 +28,27 @@ fn test_contains_bytewise_types() { assert!(optional_nonzeros.contains(&None)); assert!(!optional_nonzeros.contains(&Some(two))); + let minus_one = NonZero::new(-1_i8).unwrap(); + let signed_one = NonZero::new(1_i8).unwrap(); + let signed_two = NonZero::new(2_i8).unwrap(); + let mut signed_nonzeros = [minus_one; 64]; + signed_nonzeros[31] = signed_one; + assert!(signed_nonzeros.contains(&minus_one)); + assert!(signed_nonzeros.contains(&signed_one)); + assert!(!signed_nonzeros.contains(&signed_two)); + + let mut optional_signed_nonzeros = [Some(minus_one); 64]; + optional_signed_nonzeros[31] = None; + assert!(optional_signed_nonzeros.contains(&Some(minus_one))); + assert!(optional_signed_nonzeros.contains(&None)); + assert!(!optional_signed_nonzeros.contains(&Some(signed_one))); + + let mut orderings = [Ordering::Less; 64]; + orderings[31] = Ordering::Greater; + assert!(orderings.contains(&Ordering::Less)); + assert!(orderings.contains(&Ordering::Greater)); + assert!(!orderings.contains(&Ordering::Equal)); + let a = core::ascii::Char::CapitalA; let q = core::ascii::Char::CapitalQ; let z = core::ascii::Char::CapitalZ; diff --git a/tests/codegen-llvm/lib-optimizations/slice-contains.rs b/tests/codegen-llvm/lib-optimizations/slice-contains.rs index ecca007875148..de0567eea41ba 100644 --- a/tests/codegen-llvm/lib-optimizations/slice-contains.rs +++ b/tests/codegen-llvm/lib-optimizations/slice-contains.rs @@ -1,11 +1,12 @@ -// Ensure one-byte slice `contains` specializations use the optimized byte search. +// Ensure one-byte bytewise-equality slice `contains` specializations use the optimized byte search. //@ compile-flags: -Copt-level=3 -Zinline-mir=false #![crate_type = "lib"] #![feature(ascii_char)] use std::ascii::Char as AsciiChar; -use std::num::NonZeroU8; +use std::cmp::Ordering; +use std::num::{NonZeroI8, NonZeroU8}; // CHECK-LABEL: @contains_bool #[no_mangle] @@ -21,6 +22,13 @@ pub fn contains_nonzero_u8(x: NonZeroU8, data: &[NonZeroU8]) -> bool { data.contains(&x) } +// CHECK-LABEL: @contains_nonzero_i8 +#[no_mangle] +pub fn contains_nonzero_i8(x: NonZeroI8, data: &[NonZeroI8], invert: bool) -> bool { + // CHECK: call core::slice::memchr + data.contains(&x) ^ invert +} + // CHECK-LABEL: @contains_option_nonzero_u8 #[no_mangle] pub fn contains_option_nonzero_u8(x: Option, data: &[Option]) -> bool { @@ -28,9 +36,27 @@ pub fn contains_option_nonzero_u8(x: Option, data: &[Option, + data: &[Option], + invert: bool, +) -> bool { + // CHECK: call core::slice::memchr + data.contains(&x) ^ invert +} + // CHECK-LABEL: @contains_ascii_char #[no_mangle] pub fn contains_ascii_char(x: AsciiChar, data: &[AsciiChar]) -> bool { // CHECK: call core::slice::memchr data.contains(&x) } + +// CHECK-LABEL: @contains_ordering +#[no_mangle] +pub fn contains_ordering(x: Ordering, data: &[Ordering]) -> bool { + // CHECK: call core::slice::memchr + data.contains(&x) +} From 57a359351d24c055023f1099c587c49189bdcd9e Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Sat, 8 Aug 2026 14:50:23 +0200 Subject: [PATCH 05/13] Rename `rustc_query_impl/error.rs` to `diagnostics.rs` --- .../src/{error.rs => diagnostics.rs} | 0 compiler/rustc_query_impl/src/job.rs | 16 ++++++++-------- compiler/rustc_query_impl/src/lib.rs | 2 +- compiler/rustc_query_impl/src/plumbing.rs | 2 +- 4 files changed, 10 insertions(+), 10 deletions(-) rename compiler/rustc_query_impl/src/{error.rs => diagnostics.rs} (100%) diff --git a/compiler/rustc_query_impl/src/error.rs b/compiler/rustc_query_impl/src/diagnostics.rs similarity index 100% rename from compiler/rustc_query_impl/src/error.rs rename to compiler/rustc_query_impl/src/diagnostics.rs diff --git a/compiler/rustc_query_impl/src/job.rs b/compiler/rustc_query_impl/src/job.rs index 4922a17253c45..1b604409f38a6 100644 --- a/compiler/rustc_query_impl/src/job.rs +++ b/compiler/rustc_query_impl/src/job.rs @@ -421,7 +421,7 @@ pub(crate) fn create_cycle_error<'tcx>( let mut cycle_stack = Vec::new(); - use crate::error::StackCount; + use crate::diagnostics::StackCount; let stack_bottom = frames[0].tagged_key.catch_description(tcx); let stack_count = if frames.len() == 1 { StackCount::Single { stack_bottom: stack_bottom.clone() } @@ -433,7 +433,7 @@ pub(crate) fn create_cycle_error<'tcx>( for i in 1..frames.len() { let frame = &frames[i]; let span = frame.tagged_key.catch_default_span(tcx, frames[(i + 1) % frames.len()].span); - cycle_stack.push(crate::error::CycleStack { + cycle_stack.push(crate::diagnostics::CycleStack { span: if span == prev { DUMMY_SP } else { span }, desc: frame.tagged_key.catch_description(tcx), }); @@ -442,7 +442,7 @@ pub(crate) fn create_cycle_error<'tcx>( let cycle_usage = usage.as_ref().map(|usage| { let cycle_span = usage.tagged_key.catch_default_span(tcx, usage.span); - crate::error::CycleUsage { + crate::diagnostics::CycleUsage { span: if cycle_span != span { cycle_span } else { DUMMY_SP }, usage: usage.tagged_key.catch_description(tcx), } @@ -464,9 +464,9 @@ pub(crate) fn create_cycle_error<'tcx>( let alias = if !nested { if is_all_def_kind(DefKind::TyAlias) { - Some(crate::error::Alias::Ty) + Some(crate::diagnostics::Alias::Ty) } else if is_all_def_kind(DefKind::TraitAlias) { - Some(crate::error::Alias::Trait) + Some(crate::diagnostics::Alias::Trait) } else { None } @@ -475,16 +475,16 @@ pub(crate) fn create_cycle_error<'tcx>( }; if nested { - tcx.sess.dcx().create_err(crate::error::NestedCycle { + tcx.sess.dcx().create_err(crate::diagnostics::NestedCycle { span, cycle_stack, - stack_bottom: crate::error::NestedCycleBottom { stack_bottom }, + stack_bottom: crate::diagnostics::NestedCycleBottom { stack_bottom }, cycle_usage, stack_count, note_span: (), }) } else { - tcx.sess.dcx().create_err(crate::error::Cycle { + tcx.sess.dcx().create_err(crate::diagnostics::Cycle { span, cycle_stack, stack_bottom, diff --git a/compiler/rustc_query_impl/src/lib.rs b/compiler/rustc_query_impl/src/lib.rs index d5133aa04dccc..0a8b25c2fa878 100644 --- a/compiler/rustc_query_impl/src/lib.rs +++ b/compiler/rustc_query_impl/src/lib.rs @@ -20,7 +20,7 @@ pub use crate::execution::{CollectActiveJobsKind, collect_active_query_jobs}; pub use crate::job::{QueryJobMap, break_query_cycle, print_query_stack}; mod dep_kind_vtables; -mod error; +mod diagnostics; mod execution; mod handle_cycle_error; mod job; diff --git a/compiler/rustc_query_impl/src/plumbing.rs b/compiler/rustc_query_impl/src/plumbing.rs index 83badcb269af6..8de442309d7b2 100644 --- a/compiler/rustc_query_impl/src/plumbing.rs +++ b/compiler/rustc_query_impl/src/plumbing.rs @@ -16,7 +16,7 @@ use rustc_middle::verify_ich::incremental_verify_ich; use rustc_serialize::{Decodable, Encodable}; use rustc_span::def_id::LOCAL_CRATE; -use crate::error::{QueryOverflow, QueryOverflowNote}; +use crate::diagnostics::{QueryOverflow, QueryOverflowNote}; use crate::execution::{all_inactive, should_verify_loaded_value}; use crate::job::find_dep_kind_root; use crate::query_impl::for_each_query_vtable; From 98621aa995fe425f8cadf5da5fb45f6b46a3f0eb Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Sat, 8 Aug 2026 14:53:57 +0200 Subject: [PATCH 06/13] Rename `rustc_middle/error.rs` to `diagnostics.rs` --- compiler/rustc_codegen_ssa/src/back/link.rs | 2 +- .../rustc_middle/src/{error.rs => diagnostics.rs} | 0 compiler/rustc_middle/src/lib.rs | 2 +- compiler/rustc_middle/src/middle/lang_items.rs | 3 ++- compiler/rustc_middle/src/mir/interpret/error.rs | 4 ++-- compiler/rustc_middle/src/mir/interpret/queries.rs | 8 ++++---- compiler/rustc_middle/src/traits/query.rs | 2 +- .../rustc_middle/src/traits/specialization_graph.rs | 2 +- compiler/rustc_middle/src/ty/adt.rs | 2 +- compiler/rustc_middle/src/ty/context.rs | 4 +++- compiler/rustc_middle/src/ty/instance.rs | 4 ++-- compiler/rustc_middle/src/ty/layout.rs | 11 ++++++----- compiler/rustc_middle/src/ty/mod.rs | 2 +- compiler/rustc_middle/src/ty/opaque_types.rs | 2 +- compiler/rustc_middle/src/ty/util.rs | 2 +- compiler/rustc_middle/src/verify_ich.rs | 4 ++-- compiler/rustc_passes/src/eii.rs | 2 +- 17 files changed, 30 insertions(+), 26 deletions(-) rename compiler/rustc_middle/src/{error.rs => diagnostics.rs} (100%) diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index e3e4a9bd4a712..014e3ee8bd365 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -28,7 +28,7 @@ use rustc_macros::Diagnostic; use rustc_metadata::EncodedMetadata; use rustc_metadata::fs::{METADATA_FILENAME, copy_to_stdout, emit_wrapper_file}; use rustc_middle::bug; -use rustc_middle::error::DuplicateEiiImpls; +use rustc_middle::diagnostics::DuplicateEiiImpls; use rustc_middle::lint::emit_lint_base; use rustc_middle::middle::debugger_visualizer::DebuggerVisualizerFile; use rustc_middle::middle::dependency_format::Linkage; diff --git a/compiler/rustc_middle/src/error.rs b/compiler/rustc_middle/src/diagnostics.rs similarity index 100% rename from compiler/rustc_middle/src/error.rs rename to compiler/rustc_middle/src/diagnostics.rs diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs index ed1a2f7a831b1..0f30498ee09cb 100644 --- a/compiler/rustc_middle/src/lib.rs +++ b/compiler/rustc_middle/src/lib.rs @@ -71,7 +71,7 @@ mod macros; pub mod arena; pub mod dep_graph; -pub mod error; +pub mod diagnostics; pub mod hir; pub mod hooks; pub mod ich; diff --git a/compiler/rustc_middle/src/middle/lang_items.rs b/compiler/rustc_middle/src/middle/lang_items.rs index 07153d688d477..b6db67342a072 100644 --- a/compiler/rustc_middle/src/middle/lang_items.rs +++ b/compiler/rustc_middle/src/middle/lang_items.rs @@ -19,7 +19,8 @@ impl<'tcx> TyCtxt<'tcx> { /// If not found, fatally aborts compilation. pub fn require_lang_item(self, lang_item: LangItem, span: Span) -> DefId { self.lang_items().get(lang_item).unwrap_or_else(|| { - self.dcx().emit_fatal(crate::error::RequiresLangItem { span, name: lang_item.name() }); + self.dcx() + .emit_fatal(crate::diagnostics::RequiresLangItem { span, name: lang_item.name() }); }) } diff --git a/compiler/rustc_middle/src/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs index 6c2fcfa749a30..ecca86bbd0e50 100644 --- a/compiler/rustc_middle/src/mir/interpret/error.rs +++ b/compiler/rustc_middle/src/mir/interpret/error.rs @@ -13,7 +13,7 @@ use rustc_span::def_id::DefId; use rustc_span::{DUMMY_SP, Span, Symbol}; use super::{AllocId, AllocRange, ConstAllocation, Pointer, Scalar}; -use crate::error; +use crate::diagnostics; use crate::mir::interpret::CtfeProvenance; use crate::mir::{ConstAlloc, ConstValue}; use crate::ty::{self, Ty, TyCtxt, ValTree, layout, tls}; @@ -47,7 +47,7 @@ impl ErrorHandled { match self { &ErrorHandled::Reported(err, span) => { if !err.allowed_in_infallible && !span.is_dummy() { - tcx.dcx().emit_note(error::ErroneousConstant { span }); + tcx.dcx().emit_note(diagnostics::ErroneousConstant { span }); } } &ErrorHandled::TooGeneric(_) => {} diff --git a/compiler/rustc_middle/src/mir/interpret/queries.rs b/compiler/rustc_middle/src/mir/interpret/queries.rs index 2fe175dd363ce..efe7c29820b4d 100644 --- a/compiler/rustc_middle/src/mir/interpret/queries.rs +++ b/compiler/rustc_middle/src/mir/interpret/queries.rs @@ -9,7 +9,7 @@ use super::{ }; use crate::mir::interpret::ValTreeCreationError; use crate::ty::{self, ConstToValTreeResult, GenericArgs, TyCtxt, TypeVisitableExt}; -use crate::{error, mir}; +use crate::{diagnostics, mir}; impl<'tcx> TyCtxt<'tcx> { /// Evaluates a constant without providing any generic parameters. This is useful to evaluate consts @@ -219,21 +219,21 @@ impl<'tcx> TyCtxt<'tcx> { ValTreeCreationError::NonSupportedType(ty) => Ok(Err(ty)), // Report the others. ValTreeCreationError::NodesOverflow => { - let handled = self.dcx().emit_err(error::MaxNumNodesInValtree { + let handled = self.dcx().emit_err(diagnostics::MaxNumNodesInValtree { span, global_const_id: cid.display(self), }); Err(ReportedErrorInfo::allowed_in_infallible(handled).into()) } ValTreeCreationError::InvalidConst => { - let handled = self.dcx().emit_err(error::InvalidConstInValtree { + let handled = self.dcx().emit_err(diagnostics::InvalidConstInValtree { span, global_const_id: cid.display(self), }); Err(ReportedErrorInfo::allowed_in_infallible(handled).into()) } ValTreeCreationError::CyclicConst => { - let handled = self.dcx().emit_err(error::CyclicConstInValtree { + let handled = self.dcx().emit_err(diagnostics::CyclicConstInValtree { span, global_const_id: cid.display(self), }); diff --git a/compiler/rustc_middle/src/traits/query.rs b/compiler/rustc_middle/src/traits/query.rs index 92aa6fe47a7e4..85d88b9892bec 100644 --- a/compiler/rustc_middle/src/traits/query.rs +++ b/compiler/rustc_middle/src/traits/query.rs @@ -8,7 +8,7 @@ use rustc_macros::{StableHash, TypeFoldable, TypeVisitable}; use rustc_span::Span; -use crate::error::DropCheckOverflow; +use crate::diagnostics::DropCheckOverflow; use crate::infer::canonical::{Canonical, CanonicalQueryInput, QueryResponse}; use crate::traits::solve; pub use crate::traits::solve::NoSolution; diff --git a/compiler/rustc_middle/src/traits/specialization_graph.rs b/compiler/rustc_middle/src/traits/specialization_graph.rs index b7b20bcdb850a..19b72d1a7d1c4 100644 --- a/compiler/rustc_middle/src/traits/specialization_graph.rs +++ b/compiler/rustc_middle/src/traits/specialization_graph.rs @@ -4,7 +4,7 @@ use rustc_hir::def_id::{DefId, DefIdMap}; use rustc_hir::find_attr; use rustc_macros::{StableHash, TyDecodable, TyEncodable}; -use crate::error::StrictCoherenceNeedsNegativeCoherence; +use crate::diagnostics::StrictCoherenceNeedsNegativeCoherence; use crate::ty::fast_reject::SimplifiedType; use crate::ty::{self, TyCtxt, TypeVisitableExt}; diff --git a/compiler/rustc_middle/src/ty/adt.rs b/compiler/rustc_middle/src/ty/adt.rs index bf8b650f4594e..e141ae49bcb90 100644 --- a/compiler/rustc_middle/src/ty/adt.rs +++ b/compiler/rustc_middle/src/ty/adt.rs @@ -658,7 +658,7 @@ impl<'tcx> AdtDef<'tcx> { Ok(Discr { val: b, ty }) } else { info!("invalid enum discriminant: {:#?}", val); - let guar = tcx.dcx().emit_err(crate::error::ConstEvalNonIntError { + let guar = tcx.dcx().emit_err(crate::diagnostics::ConstEvalNonIntError { span: tcx.def_span(expr_did), }); Err(guar) diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 30ee1d945dc18..3d146508ec287 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -1598,7 +1598,9 @@ impl<'tcx> TyCtxt<'tcx> { self.verify_query_key_hashes(); if let Err((path, error)) = self.dep_graph.finish_encoding() { - self.sess.dcx().emit_fatal(crate::error::FailedWritingFile { path: &path, error }); + self.sess + .dcx() + .emit_fatal(crate::diagnostics::FailedWritingFile { path: &path, error }); } } diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs index 6a04357827360..9e11bc83ac7cd 100644 --- a/compiler/rustc_middle/src/ty/instance.rs +++ b/compiler/rustc_middle/src/ty/instance.rs @@ -11,7 +11,7 @@ use rustc_span::def_id::LOCAL_CRATE; use rustc_span::{DUMMY_SP, Span}; use tracing::{debug, instrument}; -use crate::error; +use crate::diagnostics; use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags; use crate::ty::normalize_erasing_regions::NormalizationError; use crate::ty::print::{FmtPrinter, Print}; @@ -618,7 +618,7 @@ impl<'tcx> Instance<'tcx> { Ok(None) => { let type_length = type_length(args); if !tcx.type_length_limit().value_within_limit(type_length) { - tcx.dcx().emit_fatal(error::TypeLengthLimit { + tcx.dcx().emit_fatal(diagnostics::TypeLengthLimit { // We don't use `def_span(def_id)` so that diagnostics point // to the crate root during mono instead of to foreign items. // This is arguably better. diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index d798cf02f1e49..41672a7b92710 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -366,11 +366,12 @@ impl<'tcx> SizeSkeleton<'tcx> { Limit(0) => Limit(2), limit => limit * 2, }; - let reported = tcx.dcx().emit_err(crate::error::RecursionLimitReachedSizeSkeleton { - span, - ty, - suggested_limit, - }); + let reported = + tcx.dcx().emit_err(crate::diagnostics::RecursionLimitReachedSizeSkeleton { + span, + ty, + suggested_limit, + }); return Err(tcx.arena.alloc(LayoutError::ReferencesError(reported))); } diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 149fa69f2abbb..f5905cdefdec6 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -111,7 +111,7 @@ pub use self::typeck_results::{ Rust2024IncompatiblePatInfo, SplattedDef, TypeckResults, UserType, UserTypeAnnotationIndex, UserTypeKind, }; -use crate::error::{OpaqueHiddenTypeMismatch, TypeMismatchReason}; +use crate::diagnostics::{OpaqueHiddenTypeMismatch, TypeMismatchReason}; use crate::metadata::{AmbigModChild, ModChild}; use crate::middle::privacy::EffectiveVisibilities; use crate::mir::{Body, CoroutineLayout, CoroutineSavedLocal, MirPhase, SourceInfo}; diff --git a/compiler/rustc_middle/src/ty/opaque_types.rs b/compiler/rustc_middle/src/ty/opaque_types.rs index 31ca9c0a54db4..8d835a3d2153a 100644 --- a/compiler/rustc_middle/src/ty/opaque_types.rs +++ b/compiler/rustc_middle/src/ty/opaque_types.rs @@ -3,7 +3,7 @@ use rustc_span::Span; use rustc_span::def_id::DefId; use tracing::{debug, instrument, trace}; -use crate::error::ConstNotUsedTraitAlias; +use crate::diagnostics::ConstNotUsedTraitAlias; use crate::ty::{ self, GenericArg, GenericArgKind, RegionExt, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index 8e84ee6ab03e1..0c4e1a85351fd 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -268,7 +268,7 @@ impl<'tcx> TyCtxt<'tcx> { Limit(0) => Limit(2), limit => limit * 2, }; - let reported = self.dcx().emit_err(crate::error::RecursionLimitReached { + let reported = self.dcx().emit_err(crate::diagnostics::RecursionLimitReached { span: cause.span, ty, suggested_limit, diff --git a/compiler/rustc_middle/src/verify_ich.rs b/compiler/rustc_middle/src/verify_ich.rs index b0bc65bcc8a5c..06b7d11df94a3 100644 --- a/compiler/rustc_middle/src/verify_ich.rs +++ b/compiler/rustc_middle/src/verify_ich.rs @@ -66,7 +66,7 @@ fn incremental_verify_ich_failed<'tcx>( let old_in_panic = INSIDE_VERIFY_PANIC.replace(true); if old_in_panic { - tcx.dcx().emit_err(crate::error::Reentrant); + tcx.dcx().emit_err(crate::diagnostics::Reentrant); } else { let run_cmd = if was_invoked_from_cargo() { format!("run `cargo clean -p {}` or `cargo clean`", tcx.crate_name(LOCAL_CRATE)) @@ -75,7 +75,7 @@ fn incremental_verify_ich_failed<'tcx>( }; let dep_node = tcx.dep_graph.data().unwrap().prev_node_of(prev_index); - tcx.dcx().emit_err(crate::error::IncrementCompilation { + tcx.dcx().emit_err(crate::diagnostics::IncrementCompilation { run_cmd, dep_node: format!("{dep_node:?}"), }); diff --git a/compiler/rustc_passes/src/eii.rs b/compiler/rustc_passes/src/eii.rs index 439450fa80bd4..48621faeecc2f 100644 --- a/compiler/rustc_passes/src/eii.rs +++ b/compiler/rustc_passes/src/eii.rs @@ -6,7 +6,7 @@ use std::iter; use rustc_data_structures::fx::FxIndexMap; use rustc_hir::attrs::{EiiDecl, EiiImpl}; use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE}; -use rustc_middle::error::DuplicateEiiImpls; +use rustc_middle::diagnostics::DuplicateEiiImpls; use rustc_middle::ty::TyCtxt; use rustc_session::config::CrateType; From f03631c43daa5e2191cd0ce272c051a423a788ae Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Sat, 8 Aug 2026 14:55:19 +0200 Subject: [PATCH 07/13] Rename `rustc_driver_impl/session_diagnostics.rs` to `diagnostics.rs` --- ...{session_diagnostics.rs => diagnostics.rs} | 0 compiler/rustc_driver_impl/src/lib.rs | 24 +++++++++---------- 2 files changed, 12 insertions(+), 12 deletions(-) rename compiler/rustc_driver_impl/src/{session_diagnostics.rs => diagnostics.rs} (100%) diff --git a/compiler/rustc_driver_impl/src/session_diagnostics.rs b/compiler/rustc_driver_impl/src/diagnostics.rs similarity index 100% rename from compiler/rustc_driver_impl/src/session_diagnostics.rs rename to compiler/rustc_driver_impl/src/diagnostics.rs diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 752452067a381..e2c9f3f909b8b 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -87,8 +87,8 @@ pub mod args; pub mod pretty; #[macro_use] mod print; +mod diagnostics; pub mod highlighter; -mod session_diagnostics; // Keep the OS parts of this `cfg` in sync with the `cfg` on the `libc` // dependency in `compiler/rustc_driver/Cargo.toml`, to keep @@ -103,7 +103,7 @@ mod signal_handler { pub(super) fn install() {} } -use crate::session_diagnostics::{ +use crate::diagnostics::{ CantEmitMIR, RLinkEmptyVersionNumber, RLinkEncodingVersionMismatch, RLinkRustcVersionMismatch, RLinkWrongFileType, RlinkCorruptFile, RlinkNotAFile, RlinkUnableToRead, UnstableFeatureUsage, }; @@ -1539,17 +1539,17 @@ fn report_ice( if !info.payload().is::() && !info.payload().is::() { - dcx.emit_err(session_diagnostics::Ice); + dcx.emit_err(diagnostics::Ice); } if using_internal_features.load(std::sync::atomic::Ordering::Relaxed) { - dcx.emit_note(session_diagnostics::IceBugReportInternalFeature); + dcx.emit_note(diagnostics::IceBugReportInternalFeature); } else { - dcx.emit_note(session_diagnostics::IceBugReport { bug_report_url }); + dcx.emit_note(diagnostics::IceBugReport { bug_report_url }); // Only emit update nightly hint for users on nightly builds. if rustc_feature::UnstableFeatures::from_environment(None).is_nightly_build() { - dcx.emit_note(session_diagnostics::UpdateNightlyNote); + dcx.emit_note(diagnostics::UpdateNightlyNote); } } @@ -1562,7 +1562,7 @@ fn report_ice( // Create the ICE dump target file. match crate::fs::File::options().create(true).append(true).open(path) { Ok(mut file) => { - dcx.emit_note(session_diagnostics::IcePath { path: path.clone() }); + dcx.emit_note(diagnostics::IcePath { path: path.clone() }); if FIRST_PANIC.swap(false, Ordering::SeqCst) { let _ = write!(file, "\n\nrustc version: {version}\nplatform: {tuple}"); } @@ -1570,12 +1570,12 @@ fn report_ice( } Err(err) => { // The path ICE couldn't be written to disk, provide feedback to the user as to why. - dcx.emit_warn(session_diagnostics::IcePathError { + dcx.emit_warn(diagnostics::IcePathError { path: path.clone(), error: err.to_string(), env_var: std::env::var_os("RUSTC_ICE") .map(PathBuf::from) - .map(|env_var| session_diagnostics::IcePathErrorEnv { env_var }), + .map(|env_var| diagnostics::IcePathErrorEnv { env_var }), }); None } @@ -1584,12 +1584,12 @@ fn report_ice( None }; - dcx.emit_note(session_diagnostics::IceVersion { version, triple: tuple }); + dcx.emit_note(diagnostics::IceVersion { version, triple: tuple }); if let Some((flags, excluded_cargo_defaults)) = rustc_session::utils::extra_compiler_flags() { - dcx.emit_note(session_diagnostics::IceFlags { flags: flags.join(" ") }); + dcx.emit_note(diagnostics::IceFlags { flags: flags.join(" ") }); if excluded_cargo_defaults { - dcx.emit_note(session_diagnostics::IceExcludeCargoDefaults); + dcx.emit_note(diagnostics::IceExcludeCargoDefaults); } } From 92c6357cae2c0e54aac8d086366a7de05981b306 Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Sat, 8 Aug 2026 15:07:46 +0200 Subject: [PATCH 08/13] Merge `rustc_lint/lints.rs` into `diagnostics.rs` --- compiler/rustc_lint/src/async_fn_in_trait.rs | 2 +- compiler/rustc_lint/src/autorefs.rs | 2 +- compiler/rustc_lint/src/builtin.rs | 22 +- compiler/rustc_lint/src/c_void_returns.rs | 2 +- compiler/rustc_lint/src/dangling.rs | 2 +- .../src/deref_into_dyn_supertrait.rs | 2 +- compiler/rustc_lint/src/diagnostics.rs | 3046 ++++++++++++++++- .../rustc_lint/src/disallowed_pass_by_ref.rs | 2 +- .../rustc_lint/src/drop_forget_useless.rs | 2 +- .../src/enum_intrinsics_non_enums.rs | 2 +- compiler/rustc_lint/src/expect.rs | 2 +- .../src/for_loops_over_fallibles.rs | 2 +- compiler/rustc_lint/src/foreign_modules.rs | 2 +- .../src/function_cast_as_integer.rs | 2 +- compiler/rustc_lint/src/gpukernel_abi.rs | 2 +- .../src/implicit_provenance_casts.rs | 2 +- .../rustc_lint/src/interior_mutable_consts.rs | 4 +- compiler/rustc_lint/src/internal.rs | 2 +- compiler/rustc_lint/src/invalid_from_utf8.rs | 2 +- compiler/rustc_lint/src/let_underscore.rs | 2 +- compiler/rustc_lint/src/levels.rs | 13 +- compiler/rustc_lint/src/lib.rs | 1 - compiler/rustc_lint/src/lifetime_syntax.rs | 12 +- compiler/rustc_lint/src/lints.rs | 3045 ---------------- ..._expr_fragment_specifier_2024_migration.rs | 2 +- compiler/rustc_lint/src/map_unit_fn.rs | 2 +- .../src/multiple_supertrait_upcastable.rs | 2 +- compiler/rustc_lint/src/non_ascii_idents.rs | 2 +- compiler/rustc_lint/src/non_fmt_panic.rs | 2 +- compiler/rustc_lint/src/non_local_def.rs | 2 +- compiler/rustc_lint/src/nonstandard_style.rs | 2 +- compiler/rustc_lint/src/noop_method_call.rs | 2 +- compiler/rustc_lint/src/precedence.rs | 2 +- compiler/rustc_lint/src/ptr_nulls.rs | 2 +- .../src/raw_borrows_via_references.rs | 2 +- .../rustc_lint/src/redundant_semicolon.rs | 2 +- compiler/rustc_lint/src/reference_casting.rs | 2 +- compiler/rustc_lint/src/runtime_symbols.rs | 2 +- compiler/rustc_lint/src/shadowed_into_iter.rs | 2 +- compiler/rustc_lint/src/static_mut_refs.rs | 2 +- compiler/rustc_lint/src/traits.rs | 2 +- compiler/rustc_lint/src/transmute.rs | 2 +- compiler/rustc_lint/src/types.rs | 2 +- .../rustc_lint/src/types/improper_ctypes.rs | 2 +- compiler/rustc_lint/src/types/literal.rs | 2 +- compiler/rustc_lint/src/unit_bindings.rs | 2 +- .../src/unqualified_local_imports.rs | 4 +- compiler/rustc_lint/src/unused.rs | 2 +- compiler/rustc_lint/src/unused/must_use.rs | 2 +- 49 files changed, 3110 insertions(+), 3119 deletions(-) delete mode 100644 compiler/rustc_lint/src/lints.rs diff --git a/compiler/rustc_lint/src/async_fn_in_trait.rs b/compiler/rustc_lint/src/async_fn_in_trait.rs index 9923f05df3c73..744dd4256d884 100644 --- a/compiler/rustc_lint/src/async_fn_in_trait.rs +++ b/compiler/rustc_lint/src/async_fn_in_trait.rs @@ -2,7 +2,7 @@ use rustc_hir as hir; use rustc_session::{declare_lint, declare_lint_pass}; use rustc_trait_selection::error_reporting::traits::suggestions::suggest_desugaring_async_fn_to_impl_future_in_trait; -use crate::lints::AsyncFnInTraitDiag; +use crate::diagnostics::AsyncFnInTraitDiag; use crate::{LateContext, LateLintPass}; declare_lint! { diff --git a/compiler/rustc_lint/src/autorefs.rs b/compiler/rustc_lint/src/autorefs.rs index 24759f3ee4a01..d67fcf6336f62 100644 --- a/compiler/rustc_lint/src/autorefs.rs +++ b/compiler/rustc_lint/src/autorefs.rs @@ -5,7 +5,7 @@ use rustc_middle::ty::adjustment::{ }; use rustc_session::{declare_lint, declare_lint_pass}; -use crate::lints::{ +use crate::diagnostics::{ ImplicitUnsafeAutorefsDiag, ImplicitUnsafeAutorefsMethodNote, ImplicitUnsafeAutorefsOrigin, ImplicitUnsafeAutorefsSuggestion, }; diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index 3382bbd761455..35b0785c7847d 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -47,18 +47,18 @@ use rustc_trait_selection::traits; use rustc_trait_selection::traits::misc::type_allowed_to_implement_copy; use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _; -use crate::diagnostics::BuiltinEllipsisInclusiveRangePatterns; -use crate::lints::{ +use crate::diagnostics::{ BuiltinAnonymousParams, BuiltinConstNoMangle, BuiltinDerefNullptr, BuiltinDoubleNegations, - BuiltinDoubleNegationsAddParens, BuiltinEllipsisInclusiveRangePatternsLint, - BuiltinExplicitOutlives, BuiltinExplicitOutlivesSuggestion, BuiltinFeatureIssueNote, - BuiltinIncompleteFeatures, BuiltinIncompleteFeaturesHelp, BuiltinInternalFeatures, - BuiltinKeywordIdents, BuiltinMissingCopyImpl, BuiltinMissingDebugImpl, BuiltinMissingDoc, - BuiltinMutablesTransmutes, BuiltinNonShorthandFieldPatterns, BuiltinSpecialModuleNameUsed, - BuiltinTrivialBounds, BuiltinTypeAliasBounds, BuiltinUngatedAsyncFnTrackCaller, - BuiltinUnpermittedTypeInit, BuiltinUnpermittedTypeInitSub, BuiltinUnreachablePub, - BuiltinUnsafe, BuiltinUnstableFeatures, BuiltinUnusedDocComment, BuiltinUnusedDocCommentSub, - BuiltinWhileTrue, EqInternalMethodImplemented, InvalidAsmLabel, + BuiltinDoubleNegationsAddParens, BuiltinEllipsisInclusiveRangePatterns, + BuiltinEllipsisInclusiveRangePatternsLint, BuiltinExplicitOutlives, + BuiltinExplicitOutlivesSuggestion, BuiltinFeatureIssueNote, BuiltinIncompleteFeatures, + BuiltinIncompleteFeaturesHelp, BuiltinInternalFeatures, BuiltinKeywordIdents, + BuiltinMissingCopyImpl, BuiltinMissingDebugImpl, BuiltinMissingDoc, BuiltinMutablesTransmutes, + BuiltinNonShorthandFieldPatterns, BuiltinSpecialModuleNameUsed, BuiltinTrivialBounds, + BuiltinTypeAliasBounds, BuiltinUngatedAsyncFnTrackCaller, BuiltinUnpermittedTypeInit, + BuiltinUnpermittedTypeInitSub, BuiltinUnreachablePub, BuiltinUnsafe, BuiltinUnstableFeatures, + BuiltinUnusedDocComment, BuiltinUnusedDocCommentSub, BuiltinWhileTrue, + EqInternalMethodImplemented, InvalidAsmLabel, }; use crate::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext}; diff --git a/compiler/rustc_lint/src/c_void_returns.rs b/compiler/rustc_lint/src/c_void_returns.rs index f4dd260dd5ae4..b9d9e9ef54c4d 100644 --- a/compiler/rustc_lint/src/c_void_returns.rs +++ b/compiler/rustc_lint/src/c_void_returns.rs @@ -6,7 +6,7 @@ use rustc_hir::{self as hir, LangItem}; use rustc_session::{declare_lint, declare_lint_pass}; use rustc_span::Span; -use crate::lints::{CVoidReturn, ExternCVoidReturn}; +use crate::diagnostics::{CVoidReturn, ExternCVoidReturn}; use crate::{LateContext, LateLintPass, LintContext}; declare_lint! { diff --git a/compiler/rustc_lint/src/dangling.rs b/compiler/rustc_lint/src/dangling.rs index 88161e99b1759..54356422a11ad 100644 --- a/compiler/rustc_lint/src/dangling.rs +++ b/compiler/rustc_lint/src/dangling.rs @@ -7,7 +7,7 @@ use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_session::{declare_lint, impl_lint_pass}; use rustc_span::{Span, sym}; -use crate::lints::{DanglingPointersFromLocals, DanglingPointersFromTemporaries}; +use crate::diagnostics::{DanglingPointersFromLocals, DanglingPointersFromTemporaries}; use crate::{LateContext, LateLintPass}; declare_lint! { diff --git a/compiler/rustc_lint/src/deref_into_dyn_supertrait.rs b/compiler/rustc_lint/src/deref_into_dyn_supertrait.rs index 5d487ddfe25b8..caaf115c9133a 100644 --- a/compiler/rustc_lint/src/deref_into_dyn_supertrait.rs +++ b/compiler/rustc_lint/src/deref_into_dyn_supertrait.rs @@ -4,7 +4,7 @@ use rustc_session::{declare_lint, declare_lint_pass}; use rustc_span::{Ident, sym}; use rustc_trait_selection::traits::supertraits; -use crate::lints::{SupertraitAsDerefTarget, SupertraitAsDerefTargetLabel}; +use crate::diagnostics::{SupertraitAsDerefTarget, SupertraitAsDerefTargetLabel}; use crate::{LateContext, LateLintPass, LintContext}; declare_lint! { diff --git a/compiler/rustc_lint/src/diagnostics.rs b/compiler/rustc_lint/src/diagnostics.rs index 37aa7bccc6745..aca4149199010 100644 --- a/compiler/rustc_lint/src/diagnostics.rs +++ b/compiler/rustc_lint/src/diagnostics.rs @@ -1,8 +1,26 @@ +// ignore-tidy-file-filelength +use std::num::NonZero; + +use rustc_data_structures::fx::FxIndexMap; use rustc_errors::codes::*; -use rustc_errors::{Diag, EmissionGuarantee, Subdiagnostic, msg}; +use rustc_errors::formatting::DiagMessageAddArg; +use rustc_errors::{ + Applicability, Diag, DiagCtxtHandle, DiagMessage, DiagStyledString, Diagnostic, + EmissionGuarantee, Level, Subdiagnostic, SuggestionStyle, msg, +}; +use rustc_hir as hir; +use rustc_hir::def_id::DefId; +use rustc_hir::intravisit::VisitorExt; use rustc_macros::{Diagnostic, Subdiagnostic}; -use rustc_session::lint::Level; -use rustc_span::{Span, Symbol}; +use rustc_middle::ty::inhabitedness::InhabitedPredicate; +use rustc_middle::ty::{Clause, PolyExistentialTraitRef, Ty, TyCtxt}; +use rustc_session::Session; +use rustc_span::edition::Edition; +use rustc_span::{Ident, Span, Symbol, sym}; + +use crate::LateContext; +use crate::builtin::{InitError, ShorthandAssocTyCollector, TypeAliasBounds}; +use crate::lifetime_syntax::LifetimeSyntaxCategories; #[derive(Diagnostic)] #[diag("{$lint_level}({$lint_source}) incompatible with previous forbid", code = E0453)] @@ -108,7 +126,7 @@ pub(crate) struct BuiltinEllipsisInclusiveRangePatterns { #[derive(Subdiagnostic)] #[note("requested on the command line with `{$level} {$lint_name}`")] pub(crate) struct RequestedLevel<'a> { - pub level: Level, + pub level: rustc_session::lint::Level, pub lint_name: &'a str, } @@ -125,3 +143,3023 @@ pub(crate) struct CheckNameUnknownTool<'a> { #[subdiagnostic] pub sub: RequestedLevel<'a>, } + +// array_into_iter.rs +#[derive(Diagnostic)] +#[diag( + "this method call resolves to `<&{$target} as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to `<{$target} as IntoIterator>::into_iter` in Rust {$edition}" +)] +pub(crate) struct ShadowedIntoIterDiag { + pub target: &'static str, + pub edition: &'static str, + #[suggestion( + "use `.iter()` instead of `.into_iter()` to avoid ambiguity", + code = "iter", + applicability = "machine-applicable" + )] + pub suggestion: Span, + #[subdiagnostic] + pub sub: Option, +} + +#[derive(Subdiagnostic)] +pub(crate) enum ShadowedIntoIterDiagSub { + #[suggestion( + "or remove `.into_iter()` to iterate by value", + code = "", + applicability = "maybe-incorrect" + )] + RemoveIntoIter { + #[primary_span] + span: Span, + }, + #[multipart_suggestion( + "or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicitly iterate by value", + applicability = "maybe-incorrect" + )] + UseExplicitIntoIter { + #[suggestion_part(code = "IntoIterator::into_iter(")] + start_span: Span, + #[suggestion_part(code = ")")] + end_span: Span, + }, +} + +// autorefs.rs +#[derive(Diagnostic)] +#[diag("implicit autoref creates a reference to the dereference of a raw pointer")] +#[note( + "creating a reference requires the pointer target to be valid and imposes aliasing requirements" +)] +pub(crate) struct ImplicitUnsafeAutorefsDiag<'a> { + #[label("this raw pointer has type `{$raw_ptr_ty}`")] + pub raw_ptr_span: Span, + pub raw_ptr_ty: Ty<'a>, + #[subdiagnostic] + pub origin: ImplicitUnsafeAutorefsOrigin<'a>, + #[subdiagnostic] + pub method: Option, + #[subdiagnostic] + pub suggestion: ImplicitUnsafeAutorefsSuggestion, +} + +#[derive(Subdiagnostic)] +pub(crate) enum ImplicitUnsafeAutorefsOrigin<'a> { + #[note("autoref is being applied to this expression, resulting in: `{$autoref_ty}`")] + Autoref { + #[primary_span] + autoref_span: Span, + autoref_ty: Ty<'a>, + }, + #[note( + "references are created through calls to explicit `Deref(Mut)::deref(_mut)` implementations" + )] + OverloadedDeref, +} + +#[derive(Subdiagnostic)] +#[note("method calls to `{$method_name}` require a reference")] +pub(crate) struct ImplicitUnsafeAutorefsMethodNote { + #[primary_span] + pub def_span: Span, + pub method_name: Symbol, +} + +#[derive(Subdiagnostic)] +#[multipart_suggestion( + "try using a raw pointer method instead; or if this reference is intentional, make it explicit", + applicability = "maybe-incorrect" +)] +pub(crate) struct ImplicitUnsafeAutorefsSuggestion { + pub mutbl: &'static str, + pub deref: &'static str, + #[suggestion_part(code = "({mutbl}{deref}")] + pub start_span: Span, + #[suggestion_part(code = ")")] + pub end_span: Span, +} + +// builtin.rs +#[derive(Diagnostic)] +#[diag("denote infinite loops with `loop {\"{\"} ... {\"}\"}`")] +pub(crate) struct BuiltinWhileTrue { + #[suggestion( + "use `loop`", + style = "short", + code = "{replace}", + applicability = "machine-applicable" + )] + pub suggestion: Span, + pub replace: String, +} + +#[derive(Diagnostic)] +#[diag("the `{$ident}:` in this pattern is redundant")] +pub(crate) struct BuiltinNonShorthandFieldPatterns { + pub ident: Ident, + #[suggestion( + "use shorthand field pattern", + code = "{prefix}{ident}", + applicability = "machine-applicable" + )] + pub suggestion: Span, + pub prefix: &'static str, +} + +#[derive(Diagnostic)] +pub(crate) enum BuiltinUnsafe { + #[diag( + "`allow_internal_unsafe` allows defining macros using unsafe without triggering the `unsafe_code` lint at their call site" + )] + AllowInternalUnsafe, + #[diag("usage of an `unsafe` block")] + UnsafeBlock, + #[diag("usage of an `unsafe extern` block")] + UnsafeExternBlock, + #[diag("declaration of an `unsafe` trait")] + UnsafeTrait, + #[diag("implementation of an `unsafe` trait")] + UnsafeImpl, + #[diag("declaration of an `unsafe` function")] + DeclUnsafeFn, + #[diag("declaration of an `unsafe` method")] + DeclUnsafeMethod, + #[diag("implementation of an `unsafe` method")] + ImplUnsafeMethod, + #[diag("usage of `core::arch::global_asm`")] + #[note("using this macro is unsafe even though it does not need an `unsafe` block")] + GlobalAsm, +} + +#[derive(Diagnostic)] +#[diag("missing documentation for {$article} {$desc}")] +pub(crate) struct BuiltinMissingDoc<'a> { + pub article: &'a str, + pub desc: &'a str, +} + +#[derive(Diagnostic)] +#[diag("type could implement `Copy`; consider adding `impl Copy`")] +pub(crate) struct BuiltinMissingCopyImpl; + +pub(crate) struct BuiltinMissingDebugImpl<'a> { + pub tcx: TyCtxt<'a>, + pub def_id: DefId, +} + +// Needed for def_path_str +impl<'a> Diagnostic<'a, ()> for BuiltinMissingDebugImpl<'_> { + fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> { + let Self { tcx, def_id } = self; + Diag::new( + dcx, + level, + msg!("type does not implement `{$debug}`; consider adding `#[derive(Debug)]` or a manual implementation"), + ).with_arg("debug", tcx.def_path_str(def_id)) + } +} + +#[derive(Diagnostic)] +#[diag("anonymous parameters are deprecated and will be removed in the next edition")] +pub(crate) struct BuiltinAnonymousParams<'a> { + #[suggestion("try naming the parameter or explicitly ignoring it", code = "_: {ty_snip}")] + pub suggestion: (Span, Applicability), + pub ty_snip: &'a str, +} + +#[derive(Diagnostic)] +#[diag("unused doc comment")] +pub(crate) struct BuiltinUnusedDocComment<'a> { + pub kind: &'a str, + #[label("rustdoc does not generate documentation for {$kind}")] + pub label: Span, + #[subdiagnostic] + pub sub: BuiltinUnusedDocCommentSub, +} + +#[derive(Subdiagnostic)] +pub(crate) enum BuiltinUnusedDocCommentSub { + #[help("use `//` for a plain comment")] + PlainHelp, + #[help("use `/* */` for a plain comment")] + BlockHelp, +} + +#[derive(Diagnostic)] +#[diag("const items should never be `#[no_mangle]`")] +pub(crate) struct BuiltinConstNoMangle { + #[suggestion("try a static value", code = "pub static ", applicability = "machine-applicable")] + pub suggestion: Option, +} + +#[derive(Diagnostic)] +#[diag( + "transmuting &T to &mut T is undefined behavior, even if the reference is unused, consider instead using an UnsafeCell" +)] +pub(crate) struct BuiltinMutablesTransmutes; + +#[derive(Diagnostic)] +#[diag("use of an unstable feature")] +pub(crate) struct BuiltinUnstableFeatures; + +// lint_ungated_async_fn_track_caller +pub(crate) struct BuiltinUngatedAsyncFnTrackCaller<'a> { + pub label: Span, + pub session: &'a Session, +} + +impl<'a> Diagnostic<'a, ()> for BuiltinUngatedAsyncFnTrackCaller<'_> { + fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> { + let mut diag = Diag::new(dcx, level, "`#[track_caller]` on async functions is a no-op") + .with_span_label(self.label, "this function will not propagate the caller location"); + rustc_session::diagnostics::add_feature_diagnostics( + &mut diag, + self.session, + sym::async_fn_track_caller, + ); + diag + } +} + +#[derive(Diagnostic)] +#[diag("unreachable `pub` {$what}")] +pub(crate) struct BuiltinUnreachablePub<'a> { + pub what: &'a str, + pub new_vis: &'a str, + #[suggestion("consider restricting its visibility", code = "{new_vis}")] + pub suggestion: (Span, Applicability), + #[help("or consider exporting it for use by other crates")] + pub help: bool, +} + +#[derive(Diagnostic)] +#[diag("the `expr` fragment specifier will accept more expressions in the 2024 edition")] +pub(crate) struct MacroExprFragment2024 { + #[suggestion( + "to keep the existing behavior, use the `expr_2021` fragment specifier", + code = "expr_2021", + applicability = "machine-applicable" + )] + pub suggestion: Span, +} + +pub(crate) struct BuiltinTypeAliasBounds<'hir> { + pub in_where_clause: bool, + pub label: Span, + pub enable_feat_help: bool, + pub suggestions: Vec<(Span, String)>, + pub preds: &'hir [hir::WherePredicate<'hir>], + pub ty: Option<&'hir hir::Ty<'hir>>, +} + +impl<'a> Diagnostic<'a, ()> for BuiltinTypeAliasBounds<'_> { + fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> { + let mut diag = Diag::new(dcx, level, if self.in_where_clause { + msg!("where clauses on type aliases are not enforced") + } else { + msg!("bounds on generic parameters in type aliases are not enforced") + }) + .with_span_label(self.label, msg!("will not be checked at usage sites of the type alias")) + .with_note(msg!( + "this is a known limitation of the type checker that may be lifted in a future edition. + see issue #112792 for more information" + )); + if self.enable_feat_help { + diag.help(msg!("add `#![feature(checked_type_aliases)]` to the crate attributes to enable the desired semantics")); + } + + // We perform the walk in here instead of in `` to + // avoid doing throwaway work in case the lint ends up getting suppressed. + let mut collector = ShorthandAssocTyCollector { qselves: Vec::new() }; + if let Some(ty) = self.ty { + collector.visit_ty_unambig(ty); + } + + let affect_object_lifetime_defaults = self + .preds + .iter() + .filter(|pred| pred.kind.in_where_clause() == self.in_where_clause) + .any(|pred| TypeAliasBounds::affects_object_lifetime_defaults(pred)); + + // If there are any shorthand assoc tys, then the bounds can't be removed automatically. + // The user first needs to fully qualify the assoc tys. + let applicability = if !collector.qselves.is_empty() || affect_object_lifetime_defaults { + Applicability::MaybeIncorrect + } else { + Applicability::MachineApplicable + }; + + diag.arg("count", self.suggestions.len()); + diag.multipart_suggestion( + if self.in_where_clause { + msg!("remove this where clause") + } else { + msg!( + "remove {$count -> + [one] this bound + *[other] these bounds + }" + ) + }, + self.suggestions, + applicability, + ); + + // Suggest fully qualifying paths of the form `T::Assoc` with `T` type param via + // `::Assoc` to remove their reliance on any type param bounds. + // + // Instead of attempting to figure out the necessary trait ref, just use a + // placeholder. Since we don't record type-dependent resolutions for non-body + // items like type aliases, we can't simply deduce the corresp. trait from + // the HIR path alone without rerunning parts of HIR ty lowering here + // (namely `probe_single_ty_param_bound_for_assoc_ty`) which is infeasible. + // + // (We could employ some simple heuristics but that's likely not worth it). + for qself in collector.qselves { + diag.multipart_suggestion( + msg!("fully qualify this associated type"), + vec![ + (qself.shrink_to_lo(), "<".into()), + (qself.shrink_to_hi(), " as /* Trait */>".into()), + ], + Applicability::HasPlaceholders, + ); + } + diag + } +} + +#[derive(Diagnostic)] +#[diag("{$clause_kind_name} bound {$clause} does not depend on any type or lifetime parameters")] +pub(crate) struct BuiltinTrivialBounds<'a> { + pub clause_kind_name: &'a str, + pub clause: Clause<'a>, +} + +#[derive(Diagnostic)] +#[diag("use of a double negation")] +#[note( + "the prefix `--` could be misinterpreted as a decrement operator which exists in other languages" +)] +#[note("use `-= 1` if you meant to decrement the value")] +pub(crate) struct BuiltinDoubleNegations { + #[subdiagnostic] + pub add_parens: BuiltinDoubleNegationsAddParens, +} + +#[derive(Subdiagnostic)] +#[multipart_suggestion("add parentheses for clarity", applicability = "maybe-incorrect")] +pub(crate) struct BuiltinDoubleNegationsAddParens { + #[suggestion_part(code = "(")] + pub start_span: Span, + #[suggestion_part(code = ")")] + pub end_span: Span, +} + +#[derive(Diagnostic)] +pub(crate) enum BuiltinEllipsisInclusiveRangePatternsLint { + #[diag("`...` range patterns are deprecated")] + Parenthesise { + #[suggestion( + "use `..=` for an inclusive range", + code = "{replace}", + applicability = "machine-applicable" + )] + suggestion: Span, + replace: String, + }, + #[diag("`...` range patterns are deprecated")] + NonParenthesise { + #[suggestion( + "use `..=` for an inclusive range", + style = "short", + code = "..=", + applicability = "machine-applicable" + )] + suggestion: Span, + }, +} + +#[derive(Diagnostic)] +#[diag("`{$kw}` is a keyword in the {$next} edition")] +pub(crate) struct BuiltinKeywordIdents { + pub kw: Ident, + pub next: Edition, + #[suggestion( + "you can use a raw identifier to stay compatible", + code = "{prefix}r#{kw}", + applicability = "machine-applicable" + )] + pub suggestion: Span, + pub prefix: &'static str, +} + +#[derive(Diagnostic)] +#[diag("outlives requirements can be inferred")] +pub(crate) struct BuiltinExplicitOutlives { + #[subdiagnostic] + pub suggestion: BuiltinExplicitOutlivesSuggestion, +} + +#[derive(Subdiagnostic)] +#[multipart_suggestion( + "remove {$count -> + [one] this bound + *[other] these bounds + }" +)] +pub(crate) struct BuiltinExplicitOutlivesSuggestion { + #[suggestion_part(code = "")] + pub spans: Vec, + #[applicability] + pub applicability: Applicability, + pub count: usize, +} + +#[derive(Diagnostic)] +#[diag( + "the feature `{$name}` is incomplete and may not be safe to use and/or cause compiler crashes" +)] +pub(crate) struct BuiltinIncompleteFeatures { + pub name: Symbol, + #[subdiagnostic] + pub note: Option, + #[subdiagnostic] + pub help: Option, +} + +#[derive(Diagnostic)] +#[diag("the feature `{$name}` is internal to the compiler or standard library")] +#[note("using it is strongly discouraged")] +pub(crate) struct BuiltinInternalFeatures { + pub name: Symbol, +} + +#[derive(Subdiagnostic)] +#[help("consider using `min_{$name}` instead, which is more stable and complete")] +pub(crate) struct BuiltinIncompleteFeaturesHelp { + pub name: Symbol, +} + +#[derive(Subdiagnostic)] +#[note("see issue #{$n} for more information")] +pub(crate) struct BuiltinFeatureIssueNote { + pub n: NonZero, +} + +pub(crate) struct BuiltinUnpermittedTypeInit<'a> { + pub msg: DiagMessage, + pub ty: Ty<'a>, + pub label: Span, + pub sub: BuiltinUnpermittedTypeInitSub, + pub tcx: TyCtxt<'a>, +} + +impl<'a> Diagnostic<'a, ()> for BuiltinUnpermittedTypeInit<'_> { + fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> { + let mut diag = Diag::new(dcx, level, self.msg) + .with_arg("ty", self.ty) + .with_span_label(self.label, msg!("this code causes undefined behavior when executed")); + if let InhabitedPredicate::True = self.ty.inhabited_predicate(self.tcx) { + // Only suggest late `MaybeUninit::assume_init` initialization if the type is inhabited. + diag.span_label( + self.label, + msg!("help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done"), + ); + } + self.sub.add_to_diag(&mut diag); + diag + } +} + +// FIXME(davidtwco): make translatable +pub(crate) struct BuiltinUnpermittedTypeInitSub { + pub err: InitError, +} + +impl Subdiagnostic for BuiltinUnpermittedTypeInitSub { + fn add_to_diag(self, diag: &mut Diag<'_, G>) { + let mut err = self.err; + loop { + if let Some(span) = err.span { + diag.span_note(span, err.message); + } else { + diag.note(err.message); + } + if let Some(e) = err.nested { + err = *e; + } else { + break; + } + } + } +} + +#[derive(Diagnostic)] +pub(crate) enum BuiltinClashingExtern<'a> { + #[diag("`{$this}` redeclared with a different signature")] + SameName { + this: Symbol, + orig: Symbol, + #[label("`{$orig}` previously declared here")] + previous_decl_label: Span, + #[label("this signature doesn't match the previous declaration")] + mismatch_label: Span, + #[subdiagnostic] + sub: BuiltinClashingExternSub<'a>, + }, + #[diag("`{$this}` redeclares `{$orig}` with a different signature")] + DiffName { + this: Symbol, + orig: Symbol, + #[label("`{$orig}` previously declared here")] + previous_decl_label: Span, + #[label("this signature doesn't match the previous declaration")] + mismatch_label: Span, + #[subdiagnostic] + sub: BuiltinClashingExternSub<'a>, + }, +} + +// FIXME(davidtwco): translatable expected/found +pub(crate) struct BuiltinClashingExternSub<'a> { + pub tcx: TyCtxt<'a>, + pub expected: Ty<'a>, + pub found: Ty<'a>, +} + +impl Subdiagnostic for BuiltinClashingExternSub<'_> { + fn add_to_diag(self, diag: &mut Diag<'_, G>) { + let mut expected_str = DiagStyledString::new(); + expected_str.push(self.expected.fn_sig(self.tcx).to_string(), false); + let mut found_str = DiagStyledString::new(); + found_str.push(self.found.fn_sig(self.tcx).to_string(), true); + diag.note_expected_found("", expected_str, "", found_str); + } +} + +#[derive(Diagnostic)] +#[diag("dereferencing a null pointer")] +pub(crate) struct BuiltinDerefNullptr { + #[label("this code causes undefined behavior when executed")] + pub label: Span, +} + +#[derive(Diagnostic)] +pub(crate) enum BuiltinSpecialModuleNameUsed { + #[diag("found module declaration for lib.rs")] + #[note("lib.rs is the root of this crate's library target")] + #[help("to refer to it from other targets, use the library's name as the path")] + Lib, + #[diag("found module declaration for main.rs")] + #[note("a binary crate cannot be used as library")] + Main, +} + +// c_void_return.rs +#[derive(Diagnostic)] +#[diag("`c_void` should not be used as a return type")] +#[help("returning `()` in Rust is equivalent to returning `void` in C")] +pub(crate) struct CVoidReturn { + #[suggestion( + "remove the return type to implicitly return `()`", + code = "", + applicability = "maybe-incorrect" + )] + pub suggestion: Span, +} + +// c_void_return.rs +#[derive(Diagnostic)] +#[diag("declarations returning `c_void` are not compatible with C functions returning `void`")] +#[help("returning `()` in Rust is equivalent to returning `void` in C")] +#[note("`c_void` is only used through raw pointers for compatibility with `void` pointers")] +pub(crate) struct ExternCVoidReturn { + #[suggestion( + "remove the return type to implicitly return `()`", + code = "", + applicability = "maybe-incorrect" + )] + pub suggestion: Span, +} + +// deref_into_dyn_supertrait.rs +#[derive(Diagnostic)] +#[diag("this `Deref` implementation is covered by an implicit supertrait coercion")] +pub(crate) struct SupertraitAsDerefTarget<'a> { + pub self_ty: Ty<'a>, + pub supertrait_principal: PolyExistentialTraitRef<'a>, + pub target_principal: PolyExistentialTraitRef<'a>, + #[label( + "`{$self_ty}` implements `Deref` which conflicts with supertrait `{$supertrait_principal}`" + )] + pub label: Span, + #[subdiagnostic] + pub label2: Option>, +} + +#[derive(Subdiagnostic)] +#[label("target type is a supertrait of `{$self_ty}`")] +pub(crate) struct SupertraitAsDerefTargetLabel<'a> { + #[primary_span] + pub label: Span, + pub self_ty: Ty<'a>, +} + +// enum_intrinsics_non_enums.rs +#[derive(Diagnostic)] +#[diag("the return value of `mem::discriminant` is unspecified when called with a non-enum type")] +pub(crate) struct EnumIntrinsicsMemDiscriminate<'a> { + pub ty_param: Ty<'a>, + #[note( + "the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `{$ty_param}`, which is not an enum" + )] + pub note: Span, +} + +#[derive(Diagnostic)] +#[diag("the return value of `mem::variant_count` is unspecified when called with a non-enum type")] +#[note( + "the type parameter of `variant_count` should be an enum, but it was instantiated with the type `{$ty_param}`, which is not an enum" +)] +pub(crate) struct EnumIntrinsicsMemVariant<'a> { + pub ty_param: Ty<'a>, +} + +// expect.rs +#[derive(Diagnostic)] +#[diag("this lint expectation is unfulfilled")] +pub(crate) struct Expectation { + #[subdiagnostic] + pub rationale: Option, + #[note( + "the `unfulfilled_lint_expectations` lint can't be expected and will always produce this message" + )] + pub note: bool, +} + +#[derive(Subdiagnostic)] +#[note("{$rationale}")] +pub(crate) struct ExpectationNote { + pub rationale: Symbol, +} + +// ptr_nulls.rs +#[derive(Diagnostic)] +pub(crate) enum UselessPtrNullChecksDiag<'a> { + #[diag( + "function pointers are not nullable, so checking them for null will always return false" + )] + #[help( + "wrap the function pointer inside an `Option` and use `Option::is_none` to check for null pointer value" + )] + FnPtr { + orig_ty: Ty<'a>, + #[label("expression has type `{$orig_ty}`")] + label: Span, + }, + #[diag("references are not nullable, so checking them for null will always return false")] + Ref { + orig_ty: Ty<'a>, + #[label("expression has type `{$orig_ty}`")] + label: Span, + }, + #[diag( + "returned pointer of `{$fn_name}` call is never null, so checking it for null will always return false" + )] + FnRet { fn_name: Ident }, +} + +#[derive(Diagnostic)] +pub(crate) enum InvalidNullArgumentsDiag { + #[diag( + "calling this function with a null pointer is undefined behavior, even if the result of the function is unused" + )] + #[help( + "for more information, visit and " + )] + NullPtrInline { + #[label("null pointer originates from here")] + null_span: Span, + }, + #[diag( + "calling this function with a null pointer is undefined behavior, even if the result of the function is unused" + )] + #[help( + "for more information, visit and " + )] + NullPtrThroughBinding { + #[note("null pointer originates from here")] + null_span: Span, + }, +} + +// for_loops_over_fallibles.rs +#[derive(Diagnostic)] +#[diag( + "for loop over {$article} `{$ref_prefix}{$ty}`. This is more readably written as an `if let` statement" +)] +pub(crate) struct ForLoopsOverFalliblesDiag<'a> { + pub article: &'static str, + pub ref_prefix: &'static str, + pub ty: &'static str, + #[subdiagnostic] + pub sub: ForLoopsOverFalliblesLoopSub<'a>, + #[subdiagnostic] + pub question_mark: Option, + #[subdiagnostic] + pub suggestion: ForLoopsOverFalliblesSuggestion<'a>, +} + +#[derive(Subdiagnostic)] +pub(crate) enum ForLoopsOverFalliblesLoopSub<'a> { + #[suggestion( + "to iterate over `{$recv_snip}` remove the call to `next`", + code = ".by_ref()", + applicability = "maybe-incorrect" + )] + RemoveNext { + #[primary_span] + suggestion: Span, + recv_snip: String, + }, + #[multipart_suggestion( + "to check pattern in a loop use `while let`", + applicability = "maybe-incorrect" + )] + UseWhileLet { + #[suggestion_part(code = "while let {var}(")] + start_span: Span, + #[suggestion_part(code = ") = ")] + end_span: Span, + var: &'a str, + }, +} + +#[derive(Subdiagnostic)] +#[suggestion( + "consider unwrapping the `Result` with `?` to iterate over its contents", + code = "?", + applicability = "maybe-incorrect" +)] +pub(crate) struct ForLoopsOverFalliblesQuestionMark { + #[primary_span] + pub suggestion: Span, +} + +#[derive(Subdiagnostic)] +#[multipart_suggestion( + "consider using `if let` to clear intent", + applicability = "maybe-incorrect" +)] +pub(crate) struct ForLoopsOverFalliblesSuggestion<'a> { + pub var: &'a str, + #[suggestion_part(code = "if let {var}(")] + pub start_span: Span, + #[suggestion_part(code = ") = ")] + pub end_span: Span, +} + +#[derive(Subdiagnostic)] +pub(crate) enum UseLetUnderscoreIgnoreSuggestion { + #[note("use `let _ = ...` to ignore the expression or result")] + Note, + #[multipart_suggestion( + "use `let _ = ...` to ignore the expression or result", + style = "verbose", + applicability = "maybe-incorrect" + )] + Suggestion { + #[suggestion_part(code = "let _ = ")] + start_span: Span, + #[suggestion_part(code = "")] + end_span: Span, + }, +} + +// runtime_symbols.rs +#[derive(Diagnostic)] +pub(crate) enum RedefiningRuntimeSymbolsDiag<'tcx> { + #[diag( + "invalid definition of the runtime `{$symbol_name}` symbol used by the standard library" + )] + #[note( + "expected `{$expected_fn_sig}` (for the current target) + found `{$found_fn_sig}`" + )] + #[help( + "either fix the signature or remove any attributes like `#[unsafe(no_mangle)]`, `#[unsafe(export_name = \"{$symbol_name}\")]`, or `#[link_name = \"{$symbol_name}\"]`" + )] + Invalid { symbol_name: String, expected_fn_sig: Ty<'tcx>, found_fn_sig: Ty<'tcx> }, + #[diag( + "suspicious definition of the runtime `{$symbol_name}` symbol used by the standard library" + )] + #[note( + "expected `{$expected_fn_sig}` (for the current target) + found `{$found_fn_sig}`" + )] + #[help( + "either fix the signature or remove any attributes like `#[unsafe(no_mangle)]`, `#[unsafe(export_name = \"{$symbol_name}\")]`, or `#[link_name = \"{$symbol_name}\"]`" + )] + #[help("allow this lint if the signature is compatible")] + Suspicious { symbol_name: String, expected_fn_sig: Ty<'tcx>, found_fn_sig: Ty<'tcx> }, +} + +// drop_forget_useless.rs +#[derive(Diagnostic)] +#[diag("calls to `std::mem::drop` with a reference instead of an owned value does nothing")] +pub(crate) struct DropRefDiag<'a> { + pub arg_ty: Ty<'a>, + #[label("argument has type `{$arg_ty}`")] + pub label: Span, + #[subdiagnostic] + pub sugg: UseLetUnderscoreIgnoreSuggestion, +} + +#[derive(Diagnostic)] +#[diag("calls to `std::mem::drop` with a value that implements `Copy` does nothing")] +pub(crate) struct DropCopyDiag<'a> { + pub arg_ty: Ty<'a>, + #[label("argument has type `{$arg_ty}`")] + pub label: Span, + #[subdiagnostic] + pub sugg: UseLetUnderscoreIgnoreSuggestion, +} + +#[derive(Diagnostic)] +#[diag("calls to `std::mem::forget` with a reference instead of an owned value does nothing")] +pub(crate) struct ForgetRefDiag<'a> { + pub arg_ty: Ty<'a>, + #[label("argument has type `{$arg_ty}`")] + pub label: Span, + #[subdiagnostic] + pub sugg: UseLetUnderscoreIgnoreSuggestion, +} + +#[derive(Diagnostic)] +#[diag("calls to `std::mem::forget` with a value that implements `Copy` does nothing")] +pub(crate) struct ForgetCopyDiag<'a> { + pub arg_ty: Ty<'a>, + #[label("argument has type `{$arg_ty}`")] + pub label: Span, + #[subdiagnostic] + pub sugg: UseLetUnderscoreIgnoreSuggestion, +} + +#[derive(Diagnostic)] +#[diag( + "calls to `std::mem::drop` with `std::mem::ManuallyDrop` instead of the inner value does nothing" +)] +pub(crate) struct UndroppedManuallyDropsDiag<'a> { + pub arg_ty: Ty<'a>, + #[label("argument has type `{$arg_ty}`")] + pub label: Span, + #[subdiagnostic] + pub suggestion: UndroppedManuallyDropsSuggestion, +} + +#[derive(Subdiagnostic)] +#[multipart_suggestion( + "use `std::mem::ManuallyDrop::into_inner` to get the inner value", + applicability = "machine-applicable" +)] +pub(crate) struct UndroppedManuallyDropsSuggestion { + #[suggestion_part(code = "std::mem::ManuallyDrop::into_inner(")] + pub start_span: Span, + #[suggestion_part(code = ")")] + pub end_span: Span, +} + +// invalid_from_utf8.rs +#[derive(Diagnostic)] +pub(crate) enum InvalidFromUtf8Diag { + #[diag("calls to `{$method}` with an invalid literal are undefined behavior")] + Unchecked { + method: String, + valid_up_to: usize, + #[label("the literal was valid UTF-8 up to the {$valid_up_to} bytes")] + label: Span, + }, + #[diag("calls to `{$method}` with an invalid literal always return an error")] + Checked { + method: String, + valid_up_to: usize, + #[label("the literal was valid UTF-8 up to the {$valid_up_to} bytes")] + label: Span, + }, +} + +// interior_mutable_consts.rs +#[derive(Diagnostic)] +#[diag("mutation of an interior mutable `const` item with call to `{$method_name}`")] +#[note("each usage of a `const` item creates a new temporary")] +#[note("only the temporaries and never the original `const {$const_name}` will be modified")] +#[help( + "for more details on interior mutability see " +)] +pub(crate) struct ConstItemInteriorMutationsDiag<'tcx> { + pub method_name: Ident, + pub const_name: Ident, + pub const_ty: Ty<'tcx>, + #[label("`{$const_name}` is a interior mutable `const` item of type `{$const_ty}`")] + pub receiver_span: Span, + #[subdiagnostic] + pub sugg_static: Option, +} + +#[derive(Subdiagnostic)] +pub(crate) enum ConstItemInteriorMutationsSuggestionStatic { + #[suggestion( + "for a shared instance of `{$const_name}`, consider making it a `static` item instead", + code = "{before}static ", + style = "verbose", + applicability = "maybe-incorrect" + )] + Spanful { + #[primary_span] + const_: Span, + before: &'static str, + const_name: Ident, + }, + #[help("for a shared instance of `{$const_name}`, consider making it a `static` item instead")] + Spanless { const_name: Ident }, +} + +// reference_casting.rs +#[derive(Diagnostic)] +pub(crate) enum InvalidReferenceCastingDiag<'tcx> { + #[diag( + "casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell`" + )] + #[note( + "for more information, visit " + )] + BorrowAsMut { + #[label("casting happened here")] + orig_cast: Option, + }, + #[diag("assigning to `&T` is undefined behavior, consider using an `UnsafeCell`")] + #[note( + "for more information, visit " + )] + AssignToRef { + #[label("casting happened here")] + orig_cast: Option, + }, + #[diag( + "casting references to a bigger memory layout than the backing allocation is undefined behavior, even if the reference is unused" + )] + #[note("casting from `{$from_ty}` ({$from_size} bytes) to `{$to_ty}` ({$to_size} bytes)")] + BiggerLayout { + #[label("casting happened here")] + orig_cast: Option, + #[label("backing allocation comes from here")] + alloc: Span, + from_ty: Ty<'tcx>, + from_size: u64, + to_ty: Ty<'tcx>, + to_size: u64, + }, +} + +// map_unit_fn.rs +#[derive(Diagnostic)] +#[diag("`Iterator::map` call that discard the iterator's values")] +#[note( + "`Iterator::map`, like many of the methods on `Iterator`, gets executed lazily, meaning that its effects won't be visible until it is iterated" +)] +pub(crate) struct MappingToUnit { + #[label("this function returns `()`, which is likely not what you wanted")] + pub function_label: Span, + #[label("called `Iterator::map` with callable that returns `()`")] + pub argument_label: Span, + #[label( + "after this call to map, the resulting iterator is `impl Iterator`, which means the only information carried by the iterator is the number of items" + )] + pub map_label: Span, + #[suggestion( + "you might have meant to use `Iterator::for_each`", + style = "verbose", + code = "for_each", + applicability = "maybe-incorrect" + )] + pub suggestion: Span, +} + +// internal.rs +#[derive(Diagnostic)] +#[diag("prefer `{$preferred}` over `{$used}`, it has better performance")] +#[note("a `use rustc_data_structures::fx::{$preferred}` may be necessary")] +pub(crate) struct DefaultHashTypesDiag<'a> { + pub preferred: &'a str, + pub used: Symbol, +} + +#[derive(Diagnostic)] +#[diag("using `{$query}` can result in unstable query results")] +#[note( + "if you believe this case to be fine, allow this lint and add a comment explaining your rationale" +)] +pub(crate) struct QueryInstability { + pub query: Symbol, +} + +#[derive(Diagnostic)] +#[diag("`{$method}` accesses information that is not tracked by the query system")] +#[note( + "if you believe this case to be fine, allow this lint and add a comment explaining your rationale" +)] +pub(crate) struct QueryUntracked { + pub method: Symbol, +} + +#[derive(Diagnostic)] +#[diag("use `.eq_ctxt()` instead of `.ctxt() == .ctxt()`")] +pub(crate) struct SpanUseEqCtxtDiag; + +#[derive(Diagnostic)] +#[diag("using `Symbol::intern` on a string literal")] +#[help("consider adding the symbol to `compiler/rustc_span/src/symbol.rs`")] +pub(crate) struct SymbolInternStringLiteralDiag; + +#[derive(Diagnostic)] +#[diag("usage of `ty::TyKind::`")] +pub(crate) struct TykindKind { + #[suggestion( + "try using `ty::` directly", + code = "ty", + applicability = "maybe-incorrect" + )] + pub suggestion: Span, +} + +#[derive(Diagnostic)] +#[diag("usage of `ty::TyKind`")] +#[help("try using `Ty` instead")] +pub(crate) struct TykindDiag; + +#[derive(Diagnostic)] +#[diag("usage of qualified `ty::{$ty}`")] +pub(crate) struct TyQualified { + pub ty: String, + #[suggestion( + "try importing it and using it unqualified", + code = "{ty}", + applicability = "maybe-incorrect" + )] + pub suggestion: Span, +} + +#[derive(Diagnostic)] +#[diag("do not use `rustc_type_ir::inherent` unless you're inside of the trait solver")] +#[note( + "the method or struct you're looking for is likely defined somewhere else downstream in the compiler" +)] +pub(crate) struct TypeIrInherentUsage; + +#[derive(Diagnostic)] +#[diag( + "do not use `rustc_type_ir::Interner` or `rustc_type_ir::InferCtxtLike` unless you're inside of the trait solver" +)] +#[note( + "the method or struct you're looking for is likely defined somewhere else downstream in the compiler" +)] +pub(crate) struct TypeIrTraitUsage; + +#[derive(Diagnostic)] +#[diag("do not use `rustc_type_ir` unless you are implementing type system internals")] +#[note("use `rustc_middle::ty` instead")] +pub(crate) struct TypeIrDirectUse; + +#[derive(Diagnostic)] +#[diag("non-glob import of `rustc_type_ir::inherent`")] +pub(crate) struct NonGlobImportTypeIrInherent { + #[suggestion( + "try using a glob import instead", + code = "{snippet}", + applicability = "maybe-incorrect" + )] + pub suggestion: Option, + pub snippet: &'static str, +} + +#[derive(Diagnostic)] +#[diag("implementing `LintPass` by hand")] +#[help("try using `declare_lint_pass!` or `impl_lint_pass!` instead")] +pub(crate) struct LintPassByHand; + +#[derive(Diagnostic)] +#[diag("{$msg}")] +pub(crate) struct BadOptAccessDiag<'a> { + pub msg: &'a str, +} + +#[derive(Diagnostic)] +#[diag( + "dangerous use of `extern crate {$name}` which is not guaranteed to exist exactly once in the sysroot" +)] +#[help( + "try using a cargo dependency or using a re-export of the dependency provided by a rustc_* crate" +)] +pub(crate) struct ImplicitSysrootCrateImportDiag<'a> { + pub name: &'a str, +} + +#[derive(Diagnostic)] +#[diag("use of `AttributeKind` in `find_attr!(...)` invocation")] +#[note("`find_attr!(...)` already imports `AttributeKind::*`")] +#[help("remove `AttributeKind`")] +pub(crate) struct AttributeKindInFindAttr; + +#[derive(Diagnostic)] +#[diag("match is not exhaustive")] +#[help("explicitly list all variants of the enum in a `match`")] +pub(crate) struct RustcMustMatchExhaustivelyNotExhaustive { + #[label("required because of this attribute")] + pub attr_span: Span, + + #[note("{$message}")] + pub pat_span: Span, + pub message: &'static str, +} + +// let_underscore.rs +#[derive(Diagnostic)] +pub(crate) enum NonBindingLet { + #[diag("non-binding let on a synchronization lock")] + SyncLock { + #[label("this lock is not assigned to a binding and is immediately dropped")] + pat: Span, + #[subdiagnostic] + sub: NonBindingLetSub, + }, + #[diag("non-binding let on a type that has a destructor")] + DropType { + #[subdiagnostic] + sub: NonBindingLetSub, + }, +} + +pub(crate) struct NonBindingLetSub { + pub suggestion: Span, + pub drop_fn_start_end: Option<(Span, Span)>, + pub is_assign_desugar: bool, +} + +impl Subdiagnostic for NonBindingLetSub { + fn add_to_diag(self, diag: &mut Diag<'_, G>) { + let can_suggest_binding = self.drop_fn_start_end.is_some() || !self.is_assign_desugar; + + if can_suggest_binding { + let prefix = if self.is_assign_desugar { "let " } else { "" }; + diag.span_suggestion_verbose( + self.suggestion, + msg!( + "consider binding to an unused variable to avoid immediately dropping the value" + ), + format!("{prefix}_unused"), + Applicability::MachineApplicable, + ); + } else { + diag.span_help( + self.suggestion, + msg!( + "consider binding to an unused variable to avoid immediately dropping the value" + ), + ); + } + if let Some(drop_fn_start_end) = self.drop_fn_start_end { + diag.multipart_suggestion( + msg!("consider immediately dropping the value"), + vec![ + (drop_fn_start_end.0, "drop(".to_string()), + (drop_fn_start_end.1, ")".to_string()), + ], + Applicability::MachineApplicable, + ); + } else { + diag.help(msg!( + "consider immediately dropping the value using `drop(..)` after the `let` statement" + )); + } + } +} + +// levels.rs +#[derive(Diagnostic)] +#[diag("{$lint_level}({$lint_source}) incompatible with previous forbid")] +pub(crate) struct OverruledAttributeLint<'a> { + #[label("overruled by previous forbid")] + pub overruled: Span, + pub lint_level: &'a str, + pub lint_source: Symbol, + #[subdiagnostic] + pub sub: OverruledAttributeSub, +} + +#[derive(Diagnostic)] +#[diag("lint name `{$name}` is deprecated and may not have an effect in the future")] +pub(crate) struct DeprecatedLintName<'a> { + pub name: String, + #[suggestion("change it to", code = "{replace}", applicability = "machine-applicable")] + pub suggestion: Span, + pub replace: &'a str, +} + +#[derive(Diagnostic)] +#[diag("lint name `{$name}` is deprecated and may not have an effect in the future")] +#[help("change it to {$replace}")] +pub(crate) struct DeprecatedLintNameFromCommandLine<'a> { + pub name: String, + pub replace: &'a str, + #[subdiagnostic] + pub requested_level: RequestedLevel<'a>, +} + +#[derive(Diagnostic)] +#[diag("lint `{$name}` has been renamed to `{$replace}`")] +pub(crate) struct RenamedLint<'a> { + pub name: &'a str, + pub replace: &'a str, + #[subdiagnostic] + pub suggestion: RenamedLintSuggestion<'a>, +} + +#[derive(Subdiagnostic)] +pub(crate) enum RenamedLintSuggestion<'a> { + #[suggestion("use the new name", code = "{replace}", applicability = "machine-applicable")] + WithSpan { + #[primary_span] + suggestion: Span, + replace: &'a str, + }, + #[help("use the new name `{$replace}`")] + WithoutSpan { replace: &'a str }, +} + +#[derive(Diagnostic)] +#[diag("lint `{$name}` has been renamed to `{$replace}`")] +pub(crate) struct RenamedLintFromCommandLine<'a> { + pub name: &'a str, + pub replace: &'a str, + #[subdiagnostic] + pub suggestion: RenamedLintSuggestion<'a>, + #[subdiagnostic] + pub requested_level: RequestedLevel<'a>, +} + +#[derive(Diagnostic)] +#[diag("lint `{$name}` has been removed: {$reason}")] +pub(crate) struct RemovedLint<'a> { + pub name: &'a str, + pub reason: &'a str, +} + +#[derive(Diagnostic)] +#[diag("lint `{$name}` has been removed: {$reason}")] +pub(crate) struct RemovedLintFromCommandLine<'a> { + pub name: &'a str, + pub reason: &'a str, + #[subdiagnostic] + pub requested_level: RequestedLevel<'a>, +} + +#[derive(Diagnostic)] +#[diag("unknown lint: `{$name}`")] +pub(crate) struct UnknownLint { + pub name: String, + #[subdiagnostic] + pub suggestion: Option, +} + +#[derive(Subdiagnostic)] +pub(crate) enum UnknownLintSuggestion { + #[suggestion( + "{$from_rustc -> + [true] a lint with a similar name exists in `rustc` lints + *[false] did you mean + }", + code = "{replace}", + applicability = "maybe-incorrect" + )] + WithSpan { + #[primary_span] + suggestion: Span, + replace: Symbol, + from_rustc: bool, + }, + #[help( + "{$from_rustc -> + [true] a lint with a similar name exists in `rustc` lints: `{$replace}` + *[false] did you mean: `{$replace}` + }" + )] + WithoutSpan { replace: Symbol, from_rustc: bool }, +} + +#[derive(Diagnostic)] +#[diag("unknown lint: `{$name}`", code = E0602)] +pub(crate) struct UnknownLintFromCommandLine<'a> { + pub name: String, + #[subdiagnostic] + pub suggestion: Option, + #[subdiagnostic] + pub requested_level: RequestedLevel<'a>, +} + +#[derive(Diagnostic)] +#[diag("{$level}({$name}) is ignored unless specified at crate level")] +pub(crate) struct IgnoredUnlessCrateSpecified<'a> { + pub level: &'a str, + pub name: Symbol, +} + +// dangling.rs +#[derive(Diagnostic)] +#[diag("this creates a dangling pointer because temporary `{$ty}` is dropped at end of statement")] +#[help("bind the `{$ty}` to a variable such that it outlives the pointer returned by `{$callee}`")] +#[note("a dangling pointer is safe, but dereferencing one is undefined behavior")] +#[note("returning a pointer to a local variable will always result in a dangling pointer")] +#[note("for more information, see ")] +// FIXME: put #[primary_span] on `ptr_span` once it does not cause conflicts +pub(crate) struct DanglingPointersFromTemporaries<'tcx> { + pub callee: Ident, + pub ty: Ty<'tcx>, + #[label("pointer created here")] + pub ptr_span: Span, + #[label("this `{$ty}` is dropped at end of statement")] + pub temporary_span: Span, +} + +#[derive(Diagnostic)] +#[diag("{$fn_kind} returns a dangling pointer to dropped local variable `{$local_var_name}`")] +#[note("a dangling pointer is safe, but dereferencing one is undefined behavior")] +#[note("for more information, see ")] +pub(crate) struct DanglingPointersFromLocals<'tcx> { + pub ret_ty: Ty<'tcx>, + #[label("return type is `{$ret_ty}`")] + pub ret_ty_span: Span, + pub fn_kind: &'static str, + #[label("local variable `{$local_var_name}` is dropped at the end of the {$fn_kind}")] + pub local_var: Span, + pub local_var_name: Ident, + pub local_var_ty: Ty<'tcx>, + #[label("dangling pointer created here")] + pub created_at: Option, +} + +// multiple_supertrait_upcastable.rs +#[derive(Diagnostic)] +#[diag("`{$ident}` is dyn-compatible and has multiple supertraits")] +pub(crate) struct MultipleSupertraitUpcastable { + pub ident: Ident, +} + +// non_ascii_idents.rs +#[derive(Diagnostic)] +#[diag("identifier contains non-ASCII characters")] +pub(crate) struct IdentifierNonAsciiChar; + +#[derive(Diagnostic)] +#[diag( + "identifier contains {$codepoints_len -> + [one] { $identifier_type -> + [Exclusion] a character from an archaic script + [Technical] a character that is for non-linguistic, specialized usage + [Limited_Use] a character from a script in limited use + [Not_NFKC] a non normalized (NFKC) character + *[other] an uncommon character + } + *[other] { $identifier_type -> + [Exclusion] {$codepoints_len} characters from archaic scripts + [Technical] {$codepoints_len} characters that are for non-linguistic, specialized usage + [Limited_Use] {$codepoints_len} characters from scripts in limited use + [Not_NFKC] {$codepoints_len} non normalized (NFKC) characters + *[other] uncommon characters + } + }: {$codepoints}" +)] +#[note( + r#"{$codepoints_len -> + [one] this character is + *[other] these characters are + } included in the{$identifier_type -> + [Restricted] {""} + *[other] {" "}{$identifier_type} + } Unicode general security profile"# +)] +pub(crate) struct IdentifierUncommonCodepoints { + pub codepoints: Vec, + pub codepoints_len: usize, + pub identifier_type: &'static str, +} + +#[derive(Diagnostic)] +#[diag("found both `{$existing_sym}` and `{$sym}` as identifiers, which look alike")] +pub(crate) struct ConfusableIdentifierPair { + pub existing_sym: Symbol, + pub sym: Symbol, + #[label("other identifier used here")] + pub label: Span, + #[label("this identifier can be confused with `{$existing_sym}`")] + pub main_label: Span, +} + +#[derive(Diagnostic)] +#[diag( + "the usage of Script Group `{$set}` in this crate consists solely of mixed script confusables" +)] +#[note("the usage includes {$includes}")] +#[note("please recheck to make sure their usages are indeed what you want")] +pub(crate) struct MixedScriptConfusables { + pub set: String, + pub includes: String, +} + +// non_fmt_panic.rs +pub(crate) struct NonFmtPanicUnused { + pub count: usize, + pub suggestion: Option, +} + +// Used because of two suggestions based on one Option +impl<'a> Diagnostic<'a, ()> for NonFmtPanicUnused { + fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> { + let mut diag = Diag::new(dcx, level, msg!( + "panic message contains {$count -> + [one] an unused + *[other] unused + } formatting {$count -> + [one] placeholder + *[other] placeholders + }" + )) + .with_arg("count", self.count) + .with_note(msg!("this message is not used as a format string when given without arguments, but will be in Rust 2021")); + if let Some(span) = self.suggestion { + diag.span_suggestion( + span.shrink_to_hi(), + msg!( + "add the missing {$count -> + [one] argument + *[other] arguments + }" + ), + ", ...", + Applicability::HasPlaceholders, + ); + diag.span_suggestion( + span.shrink_to_lo(), + msg!(r#"or add a "{"{"}{"}"}" format string to use the message literally"#), + "\"{}\", ", + Applicability::MachineApplicable, + ); + } + diag + } +} + +#[derive(Diagnostic)] +#[diag( + "panic message contains {$count -> + [one] a brace + *[other] braces + }" +)] +#[note("this message is not used as a format string, but will be in Rust 2021")] +pub(crate) struct NonFmtPanicBraces { + pub count: usize, + #[suggestion( + "add a \"{\"{\"}{\"}\"}\" format string to use the message literally", + code = "\"{{}}\", ", + applicability = "machine-applicable" + )] + pub suggestion: Option, +} + +// nonstandard_style.rs +#[derive(Diagnostic)] +#[diag("{$sort} `{$name}` should have an upper camel case name")] +pub(crate) struct NonCamelCaseType<'a> { + pub sort: &'a str, + pub name: &'a str, + #[subdiagnostic] + pub sub: NonCamelCaseTypeSub, +} + +#[derive(Subdiagnostic)] +pub(crate) enum NonCamelCaseTypeSub { + #[label("should have an UpperCamelCase name")] + Label { + #[primary_span] + span: Span, + }, + #[suggestion( + "convert the identifier to upper camel case", + code = "{replace}", + applicability = "maybe-incorrect" + )] + Suggestion { + #[primary_span] + span: Span, + replace: String, + }, +} + +#[derive(Diagnostic)] +#[diag("{$sort} `{$name}` should have a snake case name")] +pub(crate) struct NonSnakeCaseDiag<'a> { + pub sort: &'a str, + pub name: &'a str, + #[subdiagnostic] + pub sub: NonSnakeCaseDiagSub, +} + +pub(crate) enum NonSnakeCaseDiagSub { + Label { span: Span }, + Help { sc: String }, + RenameOrConvertSuggestion { span: Span, suggestion: Ident }, + ConvertSuggestion { span: Span, suggestion: String }, + SuggestionAndNote { sc: String, span: Span }, +} + +impl Subdiagnostic for NonSnakeCaseDiagSub { + fn add_to_diag(self, diag: &mut Diag<'_, G>) { + match self { + NonSnakeCaseDiagSub::Label { span } => { + diag.span_label(span, msg!("should have a snake_case name")); + } + NonSnakeCaseDiagSub::Help { sc } => { + diag.arg("sc", sc); + diag.help(msg!("convert the identifier to snake case: `{$sc}`")); + } + NonSnakeCaseDiagSub::ConvertSuggestion { span, suggestion } => { + diag.span_suggestion( + span, + msg!("convert the identifier to snake case"), + suggestion, + Applicability::MaybeIncorrect, + ); + } + NonSnakeCaseDiagSub::RenameOrConvertSuggestion { span, suggestion } => { + diag.span_suggestion( + span, + msg!("rename the identifier or convert it to a snake case raw identifier"), + suggestion, + Applicability::MaybeIncorrect, + ); + } + NonSnakeCaseDiagSub::SuggestionAndNote { sc, span } => { + diag.arg("sc", sc); + diag.note(msg!("`{$sc}` cannot be used as a raw identifier")); + diag.span_suggestion( + span, + msg!("rename the identifier"), + "", + Applicability::MaybeIncorrect, + ); + } + } + } +} + +#[derive(Diagnostic)] +#[diag("{$sort} `{$name}` should have an upper case name")] +pub(crate) struct NonUpperCaseGlobal<'a> { + pub sort: &'a str, + pub name: &'a str, + #[subdiagnostic] + pub sub: NonUpperCaseGlobalSub, + #[subdiagnostic] + pub usages: Vec, +} + +#[derive(Subdiagnostic)] +pub(crate) enum NonUpperCaseGlobalSub { + #[label("should have an UPPER_CASE name")] + Label { + #[primary_span] + span: Span, + }, + #[suggestion("convert the identifier to upper case", code = "{replace}")] + Suggestion { + #[primary_span] + span: Span, + #[applicability] + applicability: Applicability, + replace: String, + }, +} + +#[derive(Subdiagnostic)] +#[suggestion( + "convert the identifier to upper case", + code = "{replace}", + applicability = "machine-applicable", + style = "tool-only" +)] +pub(crate) struct NonUpperCaseGlobalSubTool { + #[primary_span] + pub(crate) span: Span, + pub(crate) replace: String, +} + +// noop_method_call.rs +#[derive(Diagnostic)] +#[diag("call to `.{$method}()` on a reference in this situation does nothing")] +#[note( + "the type `{$orig_ty}` does not implement `{$trait_}`, so calling `{$method}` on `&{$orig_ty}` copies the reference, which does not do anything and can be removed" +)] +pub(crate) struct NoopMethodCallDiag<'a> { + pub method: Ident, + pub orig_ty: Ty<'a>, + pub trait_: Symbol, + #[suggestion("remove this redundant call", code = "", applicability = "machine-applicable")] + pub label: Span, + #[suggestion( + "if you meant to clone `{$orig_ty}`, implement `Clone` for it", + code = "#[derive(Clone)]\n", + applicability = "maybe-incorrect" + )] + pub suggest_derive: Option, +} + +#[derive(Diagnostic)] +#[diag( + "using `.deref()` on a double reference, which returns `{$ty}` instead of dereferencing the inner type" +)] +pub(crate) struct SuspiciousDoubleRefDerefDiag<'a> { + pub ty: Ty<'a>, +} + +#[derive(Diagnostic)] +#[diag( + "using `.clone()` on a double reference, which returns `{$ty}` instead of cloning the inner type" +)] +pub(crate) struct SuspiciousDoubleRefCloneDiag<'a> { + pub ty: Ty<'a>, +} + +// non_local_defs.rs +pub(crate) enum NonLocalDefinitionsDiag { + Impl { + depth: u32, + body_kind_descr: &'static str, + body_name: String, + cargo_update: Option, + const_anon: Option>, + doctest: bool, + macro_to_change: Option<(String, &'static str)>, + }, + MacroRules { + depth: u32, + body_kind_descr: &'static str, + body_name: String, + doctest: bool, + cargo_update: Option, + }, +} + +impl<'a> Diagnostic<'a, ()> for NonLocalDefinitionsDiag { + fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> { + let mut diag = Diag::new(dcx, level, ""); + match self { + NonLocalDefinitionsDiag::Impl { + depth, + body_kind_descr, + body_name, + cargo_update, + const_anon, + doctest, + macro_to_change, + } => { + diag.primary_message(msg!("non-local `impl` definition, `impl` blocks should be written at the same level as their item")); + diag.arg("depth", depth); + diag.arg("body_kind_descr", body_kind_descr); + diag.arg("body_name", body_name); + + if let Some((macro_to_change, macro_kind)) = macro_to_change { + diag.arg("macro_to_change", macro_to_change); + diag.arg("macro_kind", macro_kind); + diag.note(msg!("the {$macro_kind} `{$macro_to_change}` defines the non-local `impl`, and may need to be changed")); + } + if let Some(cargo_update) = cargo_update { + diag.subdiagnostic(cargo_update); + } + + diag.note(msg!("an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl`")); + + if doctest { + diag.help(msg!("make this doc-test a standalone test with its own `fn main() {\"{\"} ... {\"}\"}`")); + } + + if let Some(const_anon) = const_anon { + diag.note(msg!("items in an anonymous const item (`const _: () = {\"{\"} ... {\"}\"}`) are treated as in the same scope as the anonymous const's declaration for the purpose of this lint")); + if let Some(const_anon) = const_anon { + diag.span_suggestion( + const_anon, + msg!("use a const-anon item to suppress this lint"), + "_", + Applicability::MachineApplicable, + ); + } + } + } + NonLocalDefinitionsDiag::MacroRules { + depth, + body_kind_descr, + body_name, + doctest, + cargo_update, + } => { + diag.primary_message(msg!("non-local `macro_rules!` definition, `#[macro_export]` macro should be written at top level module")); + diag.arg("depth", depth); + diag.arg("body_kind_descr", body_kind_descr); + diag.arg("body_name", body_name); + + if doctest { + diag.help(msg!(r#"remove the `#[macro_export]` or make this doc-test a standalone test with its own `fn main() {"{"} ... {"}"}`"#)); + } else { + diag.help(msg!( + "remove the `#[macro_export]` or move this `macro_rules!` outside the of the current {$body_kind_descr} {$depth -> + [one] `{$body_name}` + *[other] `{$body_name}` and up {$depth} bodies + }" + )); + } + + diag.note(msg!("a `macro_rules!` definition is non-local if it is nested inside an item and has a `#[macro_export]` attribute")); + + if let Some(cargo_update) = cargo_update { + diag.subdiagnostic(cargo_update); + } + } + } + diag + } +} + +#[derive(Subdiagnostic)] +#[note( + "the {$macro_kind} `{$macro_name}` may come from an old version of the `{$crate_name}` crate, try updating your dependency with `cargo update -p {$crate_name}`" +)] +pub(crate) struct NonLocalDefinitionsCargoUpdateNote { + pub macro_kind: &'static str, + pub macro_name: Symbol, + pub crate_name: Symbol, +} + +// precedence.rs +#[derive(Diagnostic)] +#[diag("`-` has lower precedence than method calls, which might be unexpected")] +#[note("e.g. `-4.abs()` equals `-4`; while `(-4).abs()` equals `4`")] +pub(crate) struct AmbiguousNegativeLiteralsDiag { + #[subdiagnostic] + pub negative_literal: AmbiguousNegativeLiteralsNegativeLiteralSuggestion, + #[subdiagnostic] + pub current_behavior: AmbiguousNegativeLiteralsCurrentBehaviorSuggestion, +} + +#[derive(Subdiagnostic)] +#[multipart_suggestion( + "add parentheses around the `-` and the literal to call the method on a negative literal", + applicability = "maybe-incorrect" +)] +pub(crate) struct AmbiguousNegativeLiteralsNegativeLiteralSuggestion { + #[suggestion_part(code = "(")] + pub start_span: Span, + #[suggestion_part(code = ")")] + pub end_span: Span, +} + +#[derive(Subdiagnostic)] +#[multipart_suggestion( + "add parentheses around the literal and the method call to keep the current behavior", + applicability = "maybe-incorrect" +)] +pub(crate) struct AmbiguousNegativeLiteralsCurrentBehaviorSuggestion { + #[suggestion_part(code = "(")] + pub start_span: Span, + #[suggestion_part(code = ")")] + pub end_span: Span, +} + +// disallowed_pass_by_ref.rs +#[derive(Diagnostic)] +#[diag("passing `{$ty}` by reference")] +pub(crate) struct DisallowedPassByRefDiag { + pub ty: String, + #[suggestion("try passing by value", code = "{ty}", applicability = "maybe-incorrect")] + pub suggestion: Span, +} + +// redundant_semicolon.rs +#[derive(Diagnostic)] +#[diag( + "unnecessary trailing {$multiple -> + [true] semicolons + *[false] semicolon + }" +)] +pub(crate) struct RedundantSemicolonsDiag { + pub multiple: bool, + #[subdiagnostic] + pub suggestion: Option, +} + +#[derive(Subdiagnostic)] +#[suggestion( + "remove {$multiple_semicolons -> + [true] these semicolons + *[false] this semicolon + }", + code = "", + applicability = "maybe-incorrect" +)] +pub(crate) struct RedundantSemicolonsSuggestion { + pub multiple_semicolons: bool, + #[primary_span] + pub span: Span, +} + +// traits.rs +pub(crate) struct DropTraitConstraintsDiag<'a> { + pub clause: Clause<'a>, + pub tcx: TyCtxt<'a>, + pub def_id: DefId, +} + +// Needed for def_path_str +impl<'a> Diagnostic<'a, ()> for DropTraitConstraintsDiag<'_> { + fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> { + Diag::new(dcx, level, msg!("bounds on `{$clause}` are most likely incorrect, consider instead using `{$needs_drop}` to detect whether a type can be trivially dropped")) + .with_arg("clause", self.clause) + .with_arg("needs_drop", self.tcx.def_path_str(self.def_id)) + } +} + +pub(crate) struct DropGlue<'a> { + pub tcx: TyCtxt<'a>, + pub def_id: DefId, +} + +// Needed for def_path_str +impl<'a> Diagnostic<'a, ()> for DropGlue<'_> { + fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> { + Diag::new(dcx, level, msg!("types that do not implement `Drop` can still have drop glue, consider instead using `{$needs_drop}` to detect whether a type is trivially dropped")) + .with_arg("needs_drop", self.tcx.def_path_str(self.def_id)) + } +} + +// transmute.rs +#[derive(Diagnostic)] +#[diag("transmuting an integer to a pointer creates a pointer without provenance")] +#[note("this is dangerous because dereferencing the resulting pointer is undefined behavior")] +#[note( + "exposed provenance semantics can be used to create a pointer based on some previously exposed provenance" +)] +#[help( + "if you truly mean to create a pointer without provenance, use `std::ptr::without_provenance_mut`" +)] +#[help( + "for more information about transmute, see " +)] +#[help( + "for more information about exposed provenance, see " +)] +pub(crate) struct IntegerToPtrTransmutes<'tcx> { + #[subdiagnostic] + pub suggestion: Option>, +} + +#[derive(Subdiagnostic)] +pub(crate) enum IntegerToPtrTransmutesSuggestion<'tcx> { + #[multipart_suggestion( + "use `std::ptr::with_exposed_provenance{$suffix}` instead to use a previously exposed provenance", + applicability = "machine-applicable", + style = "verbose" + )] + ToPtr { + dst: Ty<'tcx>, + suffix: &'static str, + #[suggestion_part(code = "std::ptr::with_exposed_provenance{suffix}::<{dst}>(")] + start_call: Span, + }, + #[multipart_suggestion( + "use `std::ptr::with_exposed_provenance{$suffix}` instead to use a previously exposed provenance", + applicability = "machine-applicable", + style = "verbose" + )] + ToRef { + dst: Ty<'tcx>, + suffix: &'static str, + ref_mutbl: &'static str, + #[suggestion_part( + code = "&{ref_mutbl}*std::ptr::with_exposed_provenance{suffix}::<{dst}>(" + )] + start_call: Span, + }, +} + +// types.rs +#[derive(Diagnostic)] +#[diag("range endpoint is out of range for `{$ty}`")] +pub(crate) struct RangeEndpointOutOfRange<'a> { + pub ty: &'a str, + #[subdiagnostic] + pub sub: UseInclusiveRange<'a>, +} + +#[derive(Subdiagnostic)] +pub(crate) enum UseInclusiveRange<'a> { + #[suggestion( + "use an inclusive range instead", + code = "{start}..={literal}{suffix}", + applicability = "machine-applicable" + )] + WithoutParen { + #[primary_span] + sugg: Span, + start: String, + literal: u128, + suffix: &'a str, + }, + #[multipart_suggestion("use an inclusive range instead", applicability = "machine-applicable")] + WithParen { + #[suggestion_part(code = "=")] + eq_sugg: Span, + #[suggestion_part(code = "{literal}{suffix}")] + lit_sugg: Span, + literal: u128, + suffix: &'a str, + }, +} + +#[derive(Diagnostic)] +#[diag("literal out of range for `{$ty}`")] +pub(crate) struct OverflowingBinHex<'a> { + pub ty: &'a str, + #[subdiagnostic] + pub sign: OverflowingBinHexSign<'a>, + #[subdiagnostic] + pub sub: Option>, + #[subdiagnostic] + pub sign_bit_sub: Option>, +} + +#[derive(Subdiagnostic)] +pub(crate) enum OverflowingBinHexSign<'a> { + #[note( + "the literal `{$lit}` (decimal `{$dec}`) does not fit into the type `{$ty}` and will become `{$actually}{$ty}`" + )] + Positive { lit: String, ty: &'a str, actually: String, dec: u128 }, + #[note("the literal `{$lit}` (decimal `{$dec}`) does not fit into the type `{$ty}`")] + #[note("and the value `-{$lit}` will become `{$actually}{$ty}`")] + Negative { lit: String, ty: &'a str, actually: String, dec: u128 }, +} + +#[derive(Subdiagnostic)] +pub(crate) enum OverflowingBinHexSub<'a> { + #[suggestion( + "consider using the type `{$suggestion_ty}` instead", + code = "{sans_suffix}{suggestion_ty}", + applicability = "machine-applicable" + )] + Suggestion { + #[primary_span] + span: Span, + suggestion_ty: &'a str, + sans_suffix: &'a str, + }, + #[help("consider using the type `{$suggestion_ty}` instead")] + Help { suggestion_ty: &'a str }, +} + +#[derive(Subdiagnostic)] +pub(crate) enum OverflowingBinHexSignBitSub<'a> { + #[suggestion( + "to use as a negative number (decimal `{$negative_val}`), consider using the type `{$uint_ty}` for the literal and cast it to `{$int_ty}`", + code = "{lit_no_suffix}{uint_ty}.cast_signed()", + applicability = "maybe-incorrect" + )] + CastSigned { + #[primary_span] + span: Span, + lit_no_suffix: &'a str, + negative_val: String, + uint_ty: &'a str, + int_ty: &'a str, + }, + #[suggestion( + "to use as a negative number (decimal `{$negative_val}`), consider using the type `{$uint_ty}` for the literal and cast it to `{$int_ty}`", + code = "{lit_no_suffix}{uint_ty} as {int_ty}", + applicability = "maybe-incorrect" + )] + AsCast { + #[primary_span] + span: Span, + lit_no_suffix: &'a str, + negative_val: String, + uint_ty: &'a str, + int_ty: &'a str, + }, +} + +#[derive(Diagnostic)] +#[diag("literal out of range for `{$ty}`")] +#[note("the literal `{$lit}` does not fit into the type `{$ty}` whose range is `{$min}..={$max}`")] +pub(crate) struct OverflowingInt<'a> { + pub ty: &'a str, + pub lit: String, + pub min: i128, + pub max: u128, + #[subdiagnostic] + pub help: Option>, +} + +#[derive(Subdiagnostic)] +#[help("consider using the type `{$suggestion_ty}` instead")] +pub(crate) struct OverflowingIntHelp<'a> { + pub suggestion_ty: &'a str, +} + +#[derive(Diagnostic)] +#[diag("only `u8` can be cast into `char`")] +pub(crate) struct OnlyCastu8ToChar { + #[suggestion( + "use a `char` literal instead", + code = "'\\u{{{literal:X}}}'", + applicability = "machine-applicable" + )] + pub span: Span, + pub literal: u128, +} + +#[derive(Diagnostic)] +#[diag("literal out of range for `{$ty}`")] +#[note("the literal `{$lit}` does not fit into the type `{$ty}` whose range is `{$min}..={$max}`")] +pub(crate) struct OverflowingUInt<'a> { + pub ty: &'a str, + pub lit: String, + pub min: u128, + pub max: u128, +} + +#[derive(Diagnostic)] +#[diag("literal out of range for `{$ty}`")] +#[note( + "the literal `{$lit}` does not fit into the type `{$ty}` and will be converted to `{$ty}::INFINITY`" +)] +pub(crate) struct OverflowingLiteral<'a> { + pub ty: &'a str, + pub lit: String, +} + +#[derive(Diagnostic)] +#[diag("surrogate values are not valid for `char`")] +#[note("`0xD800..=0xDFFF` are reserved for Unicode surrogates and are not valid `char` values")] +pub(crate) struct SurrogateCharCast { + pub literal: u128, +} + +#[derive(Diagnostic)] +#[diag("value exceeds maximum `char` value")] +#[note("maximum valid `char` value is `0x10FFFF`")] +pub(crate) struct TooLargeCharCast { + pub literal: u128, +} + +#[derive(Diagnostic)] +#[diag( + "repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type" +)] +pub(crate) struct UsesPowerAlignment; + +#[derive(Diagnostic)] +#[diag("comparison is useless due to type limits")] +pub(crate) struct UnusedComparisons; + +#[derive(Diagnostic)] +pub(crate) enum InvalidNanComparisons { + #[diag("incorrect NaN comparison, NaN cannot be directly compared to itself")] + EqNe { + #[subdiagnostic] + suggestion: InvalidNanComparisonsSuggestion, + }, + #[diag("incorrect NaN comparison, NaN is not orderable")] + LtLeGtGe, +} + +#[derive(Subdiagnostic)] +pub(crate) enum InvalidNanComparisonsSuggestion { + #[multipart_suggestion( + "use `f32::is_nan()` or `f64::is_nan()` instead", + style = "verbose", + applicability = "machine-applicable" + )] + Spanful { + #[suggestion_part(code = "!")] + neg: Option, + #[suggestion_part(code = ".is_nan()")] + float: Span, + #[suggestion_part(code = "")] + nan_plus_binop: Span, + }, + #[help("use `f32::is_nan()` or `f64::is_nan()` instead")] + Spanless, +} + +#[derive(Diagnostic)] +pub(crate) enum AmbiguousWidePointerComparisons<'a> { + #[diag( + "ambiguous wide pointer comparison, the comparison includes metadata which may not be expected" + )] + SpanfulEq { + #[subdiagnostic] + addr_suggestion: AmbiguousWidePointerComparisonsAddrSuggestion<'a>, + #[subdiagnostic] + addr_metadata_suggestion: Option>, + }, + #[diag( + "ambiguous wide pointer comparison, the comparison includes metadata which may not be expected" + )] + SpanfulCmp { + #[subdiagnostic] + cast_suggestion: AmbiguousWidePointerComparisonsCastSuggestion<'a>, + #[subdiagnostic] + expect_suggestion: AmbiguousWidePointerComparisonsExpectSuggestion<'a>, + }, + #[diag( + "ambiguous wide pointer comparison, the comparison includes metadata which may not be expected" + )] + #[help("use explicit `std::ptr::eq` method to compare metadata and addresses")] + #[help("use `std::ptr::addr_eq` or untyped pointers to only compare their addresses")] + Spanless, +} + +#[derive(Subdiagnostic)] +#[multipart_suggestion( + "use explicit `std::ptr::eq` method to compare metadata and addresses", + style = "verbose", + // FIXME(#53934): make machine-applicable again + applicability = "maybe-incorrect" +)] +pub(crate) struct AmbiguousWidePointerComparisonsAddrMetadataSuggestion<'a> { + pub ne: &'a str, + pub deref_left: &'a str, + pub deref_right: &'a str, + pub l_modifiers: &'a str, + pub r_modifiers: &'a str, + #[suggestion_part(code = "{ne}std::ptr::eq({deref_left}")] + pub left: Span, + #[suggestion_part(code = "{l_modifiers}, {deref_right}")] + pub middle: Span, + #[suggestion_part(code = "{r_modifiers})")] + pub right: Span, +} + +#[derive(Subdiagnostic)] +#[multipart_suggestion( + "use `std::ptr::addr_eq` or untyped pointers to only compare their addresses", + style = "verbose", + // FIXME(#53934): make machine-applicable again + applicability = "maybe-incorrect" +)] +pub(crate) struct AmbiguousWidePointerComparisonsAddrSuggestion<'a> { + pub(crate) ne: &'a str, + pub(crate) deref_left: &'a str, + pub(crate) deref_right: &'a str, + pub(crate) l_modifiers: &'a str, + pub(crate) r_modifiers: &'a str, + #[suggestion_part(code = "{ne}std::ptr::addr_eq({deref_left}")] + pub(crate) left: Span, + #[suggestion_part(code = "{l_modifiers}, {deref_right}")] + pub(crate) middle: Span, + #[suggestion_part(code = "{r_modifiers})")] + pub(crate) right: Span, +} + +#[derive(Subdiagnostic)] +#[multipart_suggestion( + "use untyped pointers to only compare their addresses", + style = "verbose", + // FIXME(#53934): make machine-applicable again + applicability = "maybe-incorrect" +)] +pub(crate) struct AmbiguousWidePointerComparisonsCastSuggestion<'a> { + pub(crate) deref_left: &'a str, + pub(crate) deref_right: &'a str, + pub(crate) paren_left: &'a str, + pub(crate) paren_right: &'a str, + pub(crate) l_modifiers: &'a str, + pub(crate) r_modifiers: &'a str, + #[suggestion_part(code = "({deref_left}")] + pub(crate) left_before: Option, + #[suggestion_part(code = "{l_modifiers}{paren_left}.cast::<()>()")] + pub(crate) left_after: Span, + #[suggestion_part(code = "({deref_right}")] + pub(crate) right_before: Option, + #[suggestion_part(code = "{r_modifiers}{paren_right}.cast::<()>()")] + pub(crate) right_after: Span, +} + +#[derive(Subdiagnostic)] +#[multipart_suggestion( + "or expect the lint to compare the pointers metadata and addresses", + style = "verbose", + // FIXME(#53934): make machine-applicable again + applicability = "maybe-incorrect" +)] +pub(crate) struct AmbiguousWidePointerComparisonsExpectSuggestion<'a> { + pub(crate) paren_left: &'a str, + pub(crate) paren_right: &'a str, + // FIXME(#127436): Adjust once resolved + #[suggestion_part( + code = r#"{{ #[expect(ambiguous_wide_pointer_comparisons, reason = "...")] {paren_left}"# + )] + pub(crate) before: Span, + #[suggestion_part(code = "{paren_right} }}")] + pub(crate) after: Span, +} + +#[derive(Diagnostic)] +pub(crate) enum UnpredictableFunctionPointerComparisons<'a, 'tcx> { + #[diag( + "function pointer comparisons do not produce meaningful results since their addresses are not guaranteed to be unique" + )] + #[note("the address of the same function can vary between different codegen units")] + #[note( + "furthermore, different functions could have the same address after being merged together" + )] + #[note( + "for more information visit " + )] + Suggestion { + #[subdiagnostic] + sugg: UnpredictableFunctionPointerComparisonsSuggestion<'a, 'tcx>, + }, + #[diag( + "function pointer comparisons do not produce meaningful results since their addresses are not guaranteed to be unique" + )] + #[note("the address of the same function can vary between different codegen units")] + #[note( + "furthermore, different functions could have the same address after being merged together" + )] + #[note( + "for more information visit " + )] + Warn, +} + +#[derive(Subdiagnostic)] +pub(crate) enum UnpredictableFunctionPointerComparisonsSuggestion<'a, 'tcx> { + #[multipart_suggestion( + "refactor your code, or use `std::ptr::fn_addr_eq` to suppress the lint", + style = "verbose", + applicability = "maybe-incorrect" + )] + FnAddrEq { + ne: &'a str, + deref_left: &'a str, + deref_right: &'a str, + #[suggestion_part(code = "{ne}std::ptr::fn_addr_eq({deref_left}")] + left: Span, + #[suggestion_part(code = ", {deref_right}")] + middle: Span, + #[suggestion_part(code = ")")] + right: Span, + }, + #[multipart_suggestion( + "refactor your code, or use `std::ptr::fn_addr_eq` to suppress the lint", + style = "verbose", + applicability = "maybe-incorrect" + )] + FnAddrEqWithCast { + ne: &'a str, + deref_left: &'a str, + deref_right: &'a str, + fn_sig: rustc_middle::ty::PolyFnSig<'tcx>, + #[suggestion_part(code = "{ne}std::ptr::fn_addr_eq({deref_left}")] + left: Span, + #[suggestion_part(code = ", {deref_right}")] + middle: Span, + #[suggestion_part(code = " as {fn_sig})")] + right: Span, + }, +} + +pub(crate) struct ImproperCTypes<'a> { + pub ty: Ty<'a>, + pub desc: &'a str, + pub label: Span, + pub help: Option, + pub note: DiagMessage, + pub span_note: Option, +} + +// Used because of the complexity of Option, DiagMessage, and Option +impl<'a> Diagnostic<'a, ()> for ImproperCTypes<'_> { + fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> { + let mut diag = Diag::new( + dcx, + level, + msg!("`extern` {$desc} uses type `{$ty}`, which is not FFI-safe"), + ) + .with_arg("ty", self.ty) + .with_arg("desc", self.desc) + .with_span_label(self.label, msg!("not FFI-safe")); + if let Some(help) = self.help { + diag.help(help); + } + diag.note(self.note); + if let Some(note) = self.span_note { + diag.span_note(note, msg!("the type is defined here")); + } + diag + } +} + +#[derive(Diagnostic)] +#[diag("passing type `{$ty}` to a function with \"gpu-kernel\" ABI may have unexpected behavior")] +#[help("use primitive types and raw pointers to get reliable behavior")] +pub(crate) struct ImproperGpuKernelArg<'a> { + pub ty: Ty<'a>, +} + +#[derive(Diagnostic)] +#[diag("function with the \"gpu-kernel\" ABI has a mangled name")] +#[help("use `unsafe(no_mangle)` or `unsafe(export_name = \"\")`")] +#[note("mangled names make it hard to find the kernel, this is usually not intended")] +pub(crate) struct MissingGpuKernelExportName; + +#[derive(Diagnostic)] +#[diag("enum variant is more than three times larger ({$largest} bytes) than the next largest")] +pub(crate) struct VariantSizeDifferencesDiag { + pub largest: u64, +} + +#[derive(Diagnostic)] +#[diag("atomic loads cannot have `Release` or `AcqRel` ordering")] +#[help("consider using ordering modes `Acquire`, `SeqCst` or `Relaxed`")] +pub(crate) struct AtomicOrderingLoad; + +#[derive(Diagnostic)] +#[diag("atomic stores cannot have `Acquire` or `AcqRel` ordering")] +#[help("consider using ordering modes `Release`, `SeqCst` or `Relaxed`")] +pub(crate) struct AtomicOrderingStore; + +#[derive(Diagnostic)] +#[diag("memory fences cannot have `Relaxed` ordering")] +#[help("consider using ordering modes `Acquire`, `Release`, `AcqRel` or `SeqCst`")] +pub(crate) struct AtomicOrderingFence; + +#[derive(Diagnostic)] +#[diag( + "`{$method}`'s failure ordering may not be `Release` or `AcqRel`, since a failed `{$method}` does not result in a write" +)] +#[help("consider using `Acquire` or `Relaxed` failure ordering instead")] +pub(crate) struct InvalidAtomicOrderingDiag { + pub method: Symbol, + #[label("invalid failure ordering")] + pub fail_order_arg_span: Span, +} + +// unused.rs +#[derive(Diagnostic)] +#[diag("unused {$op} that must be used")] +pub(crate) struct UnusedOp<'a> { + pub op: &'a str, + #[label("the {$op} produces a value")] + pub label: Span, + #[subdiagnostic] + pub suggestion: UnusedOpSuggestion, +} + +#[derive(Subdiagnostic)] +pub(crate) enum UnusedOpSuggestion { + #[suggestion( + "use `let _ = ...` to ignore the resulting value", + style = "verbose", + code = "let _ = ", + applicability = "maybe-incorrect" + )] + NormalExpr { + #[primary_span] + span: Span, + }, + #[multipart_suggestion( + "use `let _ = ...` to ignore the resulting value", + style = "verbose", + applicability = "maybe-incorrect" + )] + BlockTailExpr { + #[suggestion_part(code = "let _ = ")] + before_span: Span, + #[suggestion_part(code = ";")] + after_span: Span, + }, +} + +#[derive(Diagnostic)] +#[diag("unused result of type `{$ty}`")] +pub(crate) struct UnusedResult<'a> { + pub ty: Ty<'a>, +} + +// FIXME(davidtwco): this isn't properly translatable because of the +// pre/post strings +#[derive(Diagnostic)] +#[diag( + "unused {$pre}{$count -> + [one] closure + *[other] closures + }{$post} that must be used" +)] +#[note("closures are lazy and do nothing unless called")] +pub(crate) struct UnusedClosure<'a> { + pub count: usize, + pub pre: &'a str, + pub post: &'a str, +} + +// FIXME(davidtwco): this isn't properly translatable because of the +// pre/post strings +#[derive(Diagnostic)] +#[diag( + "unused {$pre}{$count -> + [one] coroutine + *[other] coroutine + }{$post} that must be used" +)] +#[note("coroutines are lazy and do nothing unless resumed")] +pub(crate) struct UnusedCoroutine<'a> { + pub count: usize, + pub pre: &'a str, + pub post: &'a str, +} + +// FIXME(davidtwco): this isn't properly translatable because of the pre/post +// strings +pub(crate) struct UnusedDef<'a, 'b> { + pub pre: &'a str, + pub post: &'a str, + pub cx: &'a LateContext<'b>, + pub def_id: DefId, + pub note: Option, + pub suggestion: Option, +} + +#[derive(Subdiagnostic)] +pub(crate) enum UnusedDefSuggestion { + #[suggestion( + "use `let _ = ...` to ignore the resulting value", + style = "verbose", + code = "let _ = ", + applicability = "maybe-incorrect" + )] + NormalExpr { + #[primary_span] + span: Span, + }, + #[multipart_suggestion( + "use `let _ = ...` to ignore the resulting value", + style = "verbose", + applicability = "maybe-incorrect" + )] + BlockTailExpr { + #[suggestion_part(code = "let _ = ")] + before_span: Span, + #[suggestion_part(code = ";")] + after_span: Span, + }, +} + +// Needed because of def_path_str +impl<'a> Diagnostic<'a, ()> for UnusedDef<'_, '_> { + fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> { + let mut diag = + Diag::new(dcx, level, msg!("unused {$pre}`{$def}`{$post} that must be used")) + .with_arg("pre", self.pre) + .with_arg("post", self.post) + .with_arg("def", self.cx.tcx.def_path_str(self.def_id)); + // check for #[must_use = "..."] + if let Some(note) = self.note { + diag.note(note.to_string()); + } + if let Some(sugg) = self.suggestion { + diag.subdiagnostic(sugg); + } + diag + } +} + +#[derive(Diagnostic)] +#[diag("path statement drops value")] +pub(crate) struct PathStatementDrop { + #[subdiagnostic] + pub sub: PathStatementDropSub, +} + +#[derive(Subdiagnostic)] +pub(crate) enum PathStatementDropSub { + #[suggestion( + "use `drop` to clarify the intent", + code = "drop({snippet});", + applicability = "machine-applicable" + )] + Suggestion { + #[primary_span] + span: Span, + snippet: String, + }, + #[help("use `drop` to clarify the intent")] + Help { + #[primary_span] + span: Span, + }, +} + +#[derive(Diagnostic)] +#[diag("path statement with no effect")] +pub(crate) struct PathStatementNoEffect; + +#[derive(Diagnostic)] +#[diag("unnecessary {$delim} around {$item}")] +pub(crate) struct UnusedDelim<'a> { + pub delim: &'static str, + pub item: &'a str, + #[subdiagnostic] + pub suggestion: Option, +} + +#[derive(Subdiagnostic)] +#[multipart_suggestion("remove these {$delim}", applicability = "machine-applicable")] +pub(crate) struct UnusedDelimSuggestion { + #[suggestion_part(code = "{start_replace}")] + pub start_span: Span, + pub start_replace: &'static str, + #[suggestion_part(code = "{end_replace}")] + pub end_span: Span, + pub end_replace: &'static str, + pub delim: &'static str, +} + +#[derive(Diagnostic)] +#[diag("braces around {$node} is unnecessary")] +pub(crate) struct UnusedImportBracesDiag { + pub node: Symbol, +} + +#[derive(Diagnostic)] +#[diag("unnecessary allocation, use `&` instead")] +pub(crate) struct UnusedAllocationDiag; + +#[derive(Diagnostic)] +#[diag("unnecessary allocation, use `&mut` instead")] +pub(crate) struct UnusedAllocationMutDiag; + +pub(crate) struct AsyncFnInTraitDiag { + pub sugg: Option>, +} + +impl<'a> Diagnostic<'a, ()> for AsyncFnInTraitDiag { + fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> { + let mut diag = Diag::new( + dcx, + level, + "use of `async fn` in public traits is discouraged as auto trait bounds cannot be specified", + ); + diag.note("you can suppress this lint if you plan to use the trait only in your own code, or do not care about auto traits like `Send` on the `Future`"); + if let Some(sugg) = self.sugg { + diag.multipart_suggestion("you can alternatively desugar to a normal `fn` that returns `impl Future` and add any desired bounds such as `Send`, but these cannot be relaxed without a breaking API change", sugg, Applicability::MaybeIncorrect); + } + diag + } +} + +#[derive(Diagnostic)] +#[diag("binding has unit type `()`")] +pub(crate) struct UnitBindingsDiag { + #[label("this pattern is inferred to be the unit type `()`")] + pub label: Span, +} + +#[derive(Diagnostic)] +pub(crate) enum InvalidAsmLabel { + #[diag("avoid using named labels in inline assembly")] + #[help("only local labels of the form `:` should be used in inline asm")] + #[note( + "see the asm section of Rust By Example for more information" + )] + Named { + #[note("the label may be declared in the expansion of a macro")] + missing_precise_span: bool, + }, + #[diag("avoid using named labels in inline assembly")] + #[help("only local labels of the form `:` should be used in inline asm")] + #[note("format arguments may expand to a non-numeric value")] + #[note( + "see the asm section of Rust By Example for more information" + )] + FormatArg { + #[note("the label may be declared in the expansion of a macro")] + missing_precise_span: bool, + }, + #[diag("avoid using labels containing only the digits `0` and `1` in inline assembly")] + #[help("start numbering with `2` instead")] + #[note("an LLVM bug makes these labels ambiguous with a binary literal number on x86")] + #[note("see for more information")] + Binary { + #[note("the label may be declared in the expansion of a macro")] + missing_precise_span: bool, + // hack to get a label on the whole span, must match the emitted span + #[label("use a different label that doesn't start with `0` or `1`")] + span: Span, + }, +} + +#[derive(Diagnostic)] +#[diag("creating a {$shared_label}reference to mutable static")] +pub(crate) struct RefOfMutStatic<'a> { + #[label("{$shared_label}reference to mutable static")] + pub span: Span, + #[subdiagnostic] + pub sugg: Option, + pub shared_label: &'a str, + #[note( + "shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives" + )] + pub shared_note: bool, + #[note( + "mutable references to mutable statics are dangerous; it's undefined behavior if any other pointer to the static is used or if any other reference is created for the static while the mutable reference lives" + )] + pub mut_note: bool, + #[help( + "use a type that relies on \"interior mutability\" instead; to read more on this, visit " + )] + pub interior_mutability_help: bool, + #[subdiagnostic] + pub interior_mutability_sugg: Option, +} + +#[derive(Subdiagnostic)] +pub(crate) enum MutRefSugg { + #[multipart_suggestion( + "use `&raw const` instead to create a raw pointer", + style = "verbose", + applicability = "maybe-incorrect" + )] + Shared { + #[suggestion_part(code = "&raw const ")] + span: Span, + }, + #[multipart_suggestion( + "use `&raw mut` instead to create a raw pointer", + style = "verbose", + applicability = "maybe-incorrect" + )] + Mut { + #[suggestion_part(code = "&raw mut ")] + span: Span, + }, +} + +#[derive(Subdiagnostic)] +#[suggestion( + "this type already provides \"interior mutability\", so its binding doesn't need to be declared as mutable when borrowed with a shared reference", + style = "verbose", + applicability = "maybe-incorrect", + code = "" +)] +pub(crate) struct StaticMutRefsInteriorMutabilitySugg { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag("`use` of a local item without leading `self::`, `super::`, or `crate::`")] +pub(crate) struct UnqualifiedLocalImportsDiag; + +#[derive(Diagnostic)] +#[diag("direct cast of function item into an integer")] +pub(crate) struct FunctionCastsAsIntegerDiag<'tcx> { + #[subdiagnostic] + pub(crate) sugg: FunctionCastsAsIntegerSugg<'tcx>, +} + +#[derive(Subdiagnostic)] +#[suggestion( + "first cast to a pointer `as *const ()`", + code = " as *const ()", + applicability = "machine-applicable", + style = "verbose" +)] +pub(crate) struct FunctionCastsAsIntegerSugg<'tcx> { + #[primary_span] + pub suggestion: Span, + pub cast_to_ty: Ty<'tcx>, +} + +#[derive(Debug)] +pub(crate) struct MismatchedLifetimeSyntaxes { + pub inputs: LifetimeSyntaxCategories>, + pub outputs: LifetimeSyntaxCategories>, + + pub suggestions: Vec, +} + +impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for MismatchedLifetimeSyntaxes { + fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, G> { + let counts = self.inputs.len() + self.outputs.len(); + let message = match counts { + LifetimeSyntaxCategories { hidden: 0, elided: 0, named: 0 } => { + panic!("No lifetime mismatch detected") + } + + LifetimeSyntaxCategories { hidden: _, elided: _, named: 0 } => { + msg!("hiding a lifetime that's elided elsewhere is confusing") + } + + LifetimeSyntaxCategories { hidden: _, elided: 0, named: _ } => { + msg!("hiding a lifetime that's named elsewhere is confusing") + } + + LifetimeSyntaxCategories { hidden: 0, elided: _, named: _ } => { + msg!("eliding a lifetime that's named elsewhere is confusing") + } + + LifetimeSyntaxCategories { hidden: _, elided: _, named: _ } => { + msg!("hiding or eliding a lifetime that's named elsewhere is confusing") + } + }; + let mut diag = Diag::new(dcx, level, message); + + for s in self.inputs.hidden { + diag.span_label(s, msg!("the lifetime is hidden here")); + } + for s in self.inputs.elided { + diag.span_label(s, msg!("the lifetime is elided here")); + } + for s in self.inputs.named { + diag.span_label(s, msg!("the lifetime is named here")); + } + + let mut hidden_output_counts: FxIndexMap = FxIndexMap::default(); + for s in self.outputs.hidden { + *hidden_output_counts.entry(s).or_insert(0) += 1; + } + for (span, count) in hidden_output_counts { + let label = msg!( + "the same {$count -> + [one] lifetime + *[other] lifetimes + } {$count -> + [one] is + *[other] are + } hidden here" + ) + .arg("count", count) + .format(); + diag.span_label(span, label); + } + for s in self.outputs.elided { + diag.span_label(s, msg!("the same lifetime is elided here")); + } + for s in self.outputs.named { + diag.span_label(s, msg!("the same lifetime is named here")); + } + + diag.help(msg!( + "the same lifetime is referred to in inconsistent ways, making the signature confusing" + )); + + let mut suggestions = self.suggestions.into_iter(); + if let Some(s) = suggestions.next() { + diag.subdiagnostic(s); + + for mut s in suggestions { + s.make_optional_alternative(); + diag.subdiagnostic(s); + } + } + diag + } +} + +#[derive(Debug)] +pub(crate) enum MismatchedLifetimeSyntaxesSuggestion { + Implicit { + suggestions: Vec, + optional_alternative: bool, + }, + + Mixed { + implicit_suggestions: Vec, + explicit_anonymous_suggestions: Vec<(Span, String)>, + optional_alternative: bool, + }, + + Explicit { + lifetime_name: String, + suggestions: Vec<(Span, String)>, + optional_alternative: bool, + }, +} + +impl MismatchedLifetimeSyntaxesSuggestion { + fn make_optional_alternative(&mut self) { + use MismatchedLifetimeSyntaxesSuggestion::*; + + let optional_alternative = match self { + Implicit { optional_alternative, .. } + | Mixed { optional_alternative, .. } + | Explicit { optional_alternative, .. } => optional_alternative, + }; + + *optional_alternative = true; + } +} + +impl Subdiagnostic for MismatchedLifetimeSyntaxesSuggestion { + fn add_to_diag(self, diag: &mut Diag<'_, G>) { + use MismatchedLifetimeSyntaxesSuggestion::*; + + let style = |optional_alternative| { + if optional_alternative { + SuggestionStyle::CompletelyHidden + } else { + SuggestionStyle::ShowAlways + } + }; + + let applicability = |optional_alternative| { + // `cargo fix` can't handle more than one fix for the same issue, + // so hide alternative suggestions from it by marking them as maybe-incorrect + if optional_alternative { + Applicability::MaybeIncorrect + } else { + Applicability::MachineApplicable + } + }; + + match self { + Implicit { suggestions, optional_alternative } => { + let suggestions = suggestions.into_iter().map(|s| (s, String::new())).collect(); + diag.multipart_suggestion_with_style( + msg!("remove the lifetime name from references"), + suggestions, + applicability(optional_alternative), + style(optional_alternative), + ); + } + + Mixed { + implicit_suggestions, + explicit_anonymous_suggestions, + optional_alternative, + } => { + let message = if implicit_suggestions.is_empty() { + msg!("use `'_` for type paths") + } else { + msg!("remove the lifetime name from references and use `'_` for type paths") + }; + + let implicit_suggestions = + implicit_suggestions.into_iter().map(|s| (s, String::new())); + + let suggestions = + implicit_suggestions.chain(explicit_anonymous_suggestions).collect(); + + diag.multipart_suggestion_with_style( + message, + suggestions, + applicability(optional_alternative), + style(optional_alternative), + ); + } + + Explicit { lifetime_name, suggestions, optional_alternative } => { + let msg = msg!("consistently use `{$lifetime_name}`") + .arg("lifetime_name", lifetime_name) + .format(); + diag.multipart_suggestion_with_style( + msg, + suggestions, + applicability(optional_alternative), + style(optional_alternative), + ); + } + } + } +} + +#[derive(Diagnostic)] +#[diag("`Eq::assert_receiver_is_total_eq` should never be implemented by hand")] +#[note("this method was used to add checks to the `Eq` derive macro")] +pub(crate) struct EqInternalMethodImplemented; + +#[derive(Diagnostic)] +#[diag("cast from `{$expr_ty}` to `{$cast_ty}` implicitly relies on exposed provenance")] +#[help( + "if conforming to strict provenance is not possible, use `std::ptr::with_exposed_provenance()`" +)] +#[note("for more information, visit ")] +pub(crate) struct ImplicitProvenanceCastsInt2Ptr<'tcx> { + pub expr_ty: Ty<'tcx>, + pub cast_ty: Ty<'tcx>, + #[subdiagnostic] + pub sugg: Option, +} + +#[derive(Subdiagnostic)] +#[multipart_suggestion( + "use `.with_addr()` to adjust the address of a valid pointer in the same allocation", + applicability = "has-placeholders" +)] +pub(crate) struct Int2PtrSuggestion { + #[suggestion_part(code = "(...).with_addr(")] + pub lo: Span, + #[suggestion_part(code = ")")] + pub hi: Span, +} + +#[derive(Diagnostic)] +#[diag("cast from `{$cast_from_ty}` to `{$cast_to_ty}` implicitly exposes pointer provenance")] +#[help("if conforming to strict provenance is not possible, use `.expose_provenance()`")] +#[note("for more information, visit ")] +pub(crate) struct ImplicitProvenanceCastsPtr2Int<'tcx> { + pub cast_from_ty: Ty<'tcx>, + pub cast_to_ty: Ty<'tcx>, + #[subdiagnostic] + pub sugg: Option>, +} + +#[derive(Subdiagnostic)] +pub(crate) enum Ptr2IntSuggestion<'tcx> { + #[multipart_suggestion( + "use `.addr()` to obtain the address of a pointer", + applicability = "maybe-incorrect" + )] + NeedsParensCast { + #[suggestion_part(code = "(")] + expr_span: Span, + #[suggestion_part(code = ").addr() as {cast_to_ty}")] + cast_span: Span, + cast_to_ty: Ty<'tcx>, + }, + #[multipart_suggestion( + "use `.addr()` to obtain the address of a pointer", + applicability = "maybe-incorrect" + )] + NeedsParens { + #[suggestion_part(code = "(")] + expr_span: Span, + #[suggestion_part(code = ").addr()")] + cast_span: Span, + }, + #[suggestion( + "use `.addr()` to obtain the address of a pointer", + code = ".addr() as {cast_to_ty}", + applicability = "maybe-incorrect" + )] + NeedsCast { + #[primary_span] + cast_span: Span, + cast_to_ty: Ty<'tcx>, + }, + #[suggestion( + "use `.addr()` to obtain the address of a pointer", + code = ".addr()", + applicability = "maybe-incorrect" + )] + Other { + #[primary_span] + cast_span: Span, + }, +} + +#[derive(Diagnostic)] +#[diag( + "creating an intermediate reference implies aliasing requirements even when immediately cast to a raw pointers" +)] +pub(crate) struct RawBorrowViaReference<'a> { + #[subdiagnostic] + pub suggestion: RawBorrowViaReferenceSuggestion<'a>, +} + +#[derive(Subdiagnostic)] +pub(crate) enum RawBorrowViaReferenceSuggestion<'a> { + #[multipart_suggestion( + "consider using `&raw {$mutbl}` for a safer and more explicit raw pointer", + applicability = "machine-applicable" + )] + Spanful { + #[suggestion_part(code = "&raw {mutbl} ")] + left: Span, + #[suggestion_part(code = "")] + right: Span, + mutbl: &'a str, + }, + #[help("consider using `&raw {$mutbl}` for a safer and more explicit raw pointer")] + Spanless { mutbl: &'a str }, +} diff --git a/compiler/rustc_lint/src/disallowed_pass_by_ref.rs b/compiler/rustc_lint/src/disallowed_pass_by_ref.rs index ccd817da38faf..2ce6035a652c7 100644 --- a/compiler/rustc_lint/src/disallowed_pass_by_ref.rs +++ b/compiler/rustc_lint/src/disallowed_pass_by_ref.rs @@ -3,7 +3,7 @@ use rustc_hir::{self as hir, AmbigArg, GenericArg, PathSegment, QPath, TyKind, f use rustc_middle::ty; use rustc_session::{declare_lint_pass, declare_tool_lint}; -use crate::lints::DisallowedPassByRefDiag; +use crate::diagnostics::DisallowedPassByRefDiag; use crate::{LateContext, LateLintPass, LintContext}; declare_tool_lint! { diff --git a/compiler/rustc_lint/src/drop_forget_useless.rs b/compiler/rustc_lint/src/drop_forget_useless.rs index c2d137986ce4d..2768a54f0207e 100644 --- a/compiler/rustc_lint/src/drop_forget_useless.rs +++ b/compiler/rustc_lint/src/drop_forget_useless.rs @@ -3,7 +3,7 @@ use rustc_middle::ty; use rustc_session::{declare_lint, declare_lint_pass}; use rustc_span::sym; -use crate::lints::{ +use crate::diagnostics::{ DropCopyDiag, DropRefDiag, ForgetCopyDiag, ForgetRefDiag, UndroppedManuallyDropsDiag, UndroppedManuallyDropsSuggestion, UseLetUnderscoreIgnoreSuggestion, }; diff --git a/compiler/rustc_lint/src/enum_intrinsics_non_enums.rs b/compiler/rustc_lint/src/enum_intrinsics_non_enums.rs index 179f2bcf07f59..4c7c561f66f44 100644 --- a/compiler/rustc_lint/src/enum_intrinsics_non_enums.rs +++ b/compiler/rustc_lint/src/enum_intrinsics_non_enums.rs @@ -4,7 +4,7 @@ use rustc_session::{declare_lint, declare_lint_pass}; use rustc_span::{Span, sym}; use crate::context::LintContext; -use crate::lints::{EnumIntrinsicsMemDiscriminate, EnumIntrinsicsMemVariant}; +use crate::diagnostics::{EnumIntrinsicsMemDiscriminate, EnumIntrinsicsMemVariant}; use crate::{LateContext, LateLintPass}; declare_lint! { diff --git a/compiler/rustc_lint/src/expect.rs b/compiler/rustc_lint/src/expect.rs index 2f257bb092ae8..cfc6b00abcc68 100644 --- a/compiler/rustc_lint/src/expect.rs +++ b/compiler/rustc_lint/src/expect.rs @@ -6,7 +6,7 @@ use rustc_session::lint::builtin::UNFULFILLED_LINT_EXPECTATIONS; use rustc_session::lint::{LintExpectationId, StableLintExpectationId}; use rustc_span::Symbol; -use crate::lints::{Expectation, ExpectationNote}; +use crate::diagnostics::{Expectation, ExpectationNote}; pub(crate) fn provide(providers: &mut Providers) { *providers = Providers { lint_expectations, check_expectations, ..*providers }; diff --git a/compiler/rustc_lint/src/for_loops_over_fallibles.rs b/compiler/rustc_lint/src/for_loops_over_fallibles.rs index 25fc52540d4f9..24f6be087fefa 100644 --- a/compiler/rustc_lint/src/for_loops_over_fallibles.rs +++ b/compiler/rustc_lint/src/for_loops_over_fallibles.rs @@ -7,7 +7,7 @@ use rustc_session::{declare_lint, declare_lint_pass}; use rustc_span::{Span, sym}; use rustc_trait_selection::traits::ObligationCtxt; -use crate::lints::{ +use crate::diagnostics::{ ForLoopsOverFalliblesDiag, ForLoopsOverFalliblesLoopSub, ForLoopsOverFalliblesQuestionMark, ForLoopsOverFalliblesSuggestion, }; diff --git a/compiler/rustc_lint/src/foreign_modules.rs b/compiler/rustc_lint/src/foreign_modules.rs index 3010eadb61057..7827253c0bb22 100644 --- a/compiler/rustc_lint/src/foreign_modules.rs +++ b/compiler/rustc_lint/src/foreign_modules.rs @@ -10,7 +10,7 @@ use rustc_session::declare_lint; use rustc_span::{Span, Symbol}; use tracing::{debug, instrument}; -use crate::lints::{BuiltinClashingExtern, BuiltinClashingExternSub}; +use crate::diagnostics::{BuiltinClashingExtern, BuiltinClashingExternSub}; use crate::{LintVec, types}; pub(crate) fn provide(providers: &mut Providers) { diff --git a/compiler/rustc_lint/src/function_cast_as_integer.rs b/compiler/rustc_lint/src/function_cast_as_integer.rs index 2a4ff1f63db52..a42f70806655a 100644 --- a/compiler/rustc_lint/src/function_cast_as_integer.rs +++ b/compiler/rustc_lint/src/function_cast_as_integer.rs @@ -3,7 +3,7 @@ use rustc_middle::ty; use rustc_session::{declare_lint, declare_lint_pass}; use rustc_span::BytePos; -use crate::lints::{FunctionCastsAsIntegerDiag, FunctionCastsAsIntegerSugg}; +use crate::diagnostics::{FunctionCastsAsIntegerDiag, FunctionCastsAsIntegerSugg}; use crate::{LateContext, LateLintPass}; declare_lint! { diff --git a/compiler/rustc_lint/src/gpukernel_abi.rs b/compiler/rustc_lint/src/gpukernel_abi.rs index e09687bc49114..41f1551bbb0f5 100644 --- a/compiler/rustc_lint/src/gpukernel_abi.rs +++ b/compiler/rustc_lint/src/gpukernel_abi.rs @@ -7,7 +7,7 @@ use rustc_session::{declare_lint, declare_lint_pass}; use rustc_span::Span; use rustc_span::def_id::LocalDefId; -use crate::lints::{ImproperGpuKernelArg, MissingGpuKernelExportName}; +use crate::diagnostics::{ImproperGpuKernelArg, MissingGpuKernelExportName}; use crate::{LateContext, LateLintPass, LintContext}; declare_lint! { diff --git a/compiler/rustc_lint/src/implicit_provenance_casts.rs b/compiler/rustc_lint/src/implicit_provenance_casts.rs index c77ecbe273387..af05c615ee4b8 100644 --- a/compiler/rustc_lint/src/implicit_provenance_casts.rs +++ b/compiler/rustc_lint/src/implicit_provenance_casts.rs @@ -3,7 +3,7 @@ use rustc_hir as hir; use rustc_middle::ty::Ty; use rustc_session::{declare_lint, declare_lint_pass}; -use crate::lints::{ +use crate::diagnostics::{ ImplicitProvenanceCastsInt2Ptr, ImplicitProvenanceCastsPtr2Int, Int2PtrSuggestion, Ptr2IntSuggestion, }; diff --git a/compiler/rustc_lint/src/interior_mutable_consts.rs b/compiler/rustc_lint/src/interior_mutable_consts.rs index 27b2a0b03c577..d2064628d1591 100644 --- a/compiler/rustc_lint/src/interior_mutable_consts.rs +++ b/compiler/rustc_lint/src/interior_mutable_consts.rs @@ -3,7 +3,9 @@ use rustc_hir::{Expr, ExprKind, ItemKind, Node, find_attr}; use rustc_middle::ty::adjustment::Adjust; use rustc_session::{declare_lint, declare_lint_pass}; -use crate::lints::{ConstItemInteriorMutationsDiag, ConstItemInteriorMutationsSuggestionStatic}; +use crate::diagnostics::{ + ConstItemInteriorMutationsDiag, ConstItemInteriorMutationsSuggestionStatic, +}; use crate::{LateContext, LateLintPass, LintContext}; declare_lint! { diff --git a/compiler/rustc_lint/src/internal.rs b/compiler/rustc_lint/src/internal.rs index b2c063922e90e..454e99f2d29e0 100644 --- a/compiler/rustc_lint/src/internal.rs +++ b/compiler/rustc_lint/src/internal.rs @@ -12,7 +12,7 @@ use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::hygiene::{ExpnKind, MacroKind}; use rustc_span::{Span, sym}; -use crate::lints::{ +use crate::diagnostics::{ AttributeKindInFindAttr, BadOptAccessDiag, DefaultHashTypesDiag, ImplicitSysrootCrateImportDiag, LintPassByHand, NonGlobImportTypeIrInherent, QueryInstability, QueryUntracked, RustcMustMatchExhaustivelyNotExhaustive, SpanUseEqCtxtDiag, diff --git a/compiler/rustc_lint/src/invalid_from_utf8.rs b/compiler/rustc_lint/src/invalid_from_utf8.rs index f095d0a6a2f40..69b6d3ca7785d 100644 --- a/compiler/rustc_lint/src/invalid_from_utf8.rs +++ b/compiler/rustc_lint/src/invalid_from_utf8.rs @@ -5,7 +5,7 @@ use rustc_hir::{Expr, ExprKind}; use rustc_session::{declare_lint, declare_lint_pass}; use rustc_span::{Spanned, sym}; -use crate::lints::InvalidFromUtf8Diag; +use crate::diagnostics::InvalidFromUtf8Diag; use crate::{LateContext, LateLintPass, LintContext}; declare_lint! { diff --git a/compiler/rustc_lint/src/let_underscore.rs b/compiler/rustc_lint/src/let_underscore.rs index d061a56c93461..c87c890f32f3a 100644 --- a/compiler/rustc_lint/src/let_underscore.rs +++ b/compiler/rustc_lint/src/let_underscore.rs @@ -4,7 +4,7 @@ use rustc_middle::ty; use rustc_session::{declare_lint, declare_lint_pass}; use rustc_span::{Symbol, sym}; -use crate::lints::{NonBindingLet, NonBindingLetSub}; +use crate::diagnostics::{NonBindingLet, NonBindingLetSub}; use crate::{LateContext, LateLintPass, LintContext}; declare_lint! { diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs index 5671e86283f9b..113af3015efaf 100644 --- a/compiler/rustc_lint/src/levels.rs +++ b/compiler/rustc_lint/src/levels.rs @@ -32,16 +32,13 @@ use tracing::{debug, instrument}; use crate::builtin::MISSING_DOCS; use crate::context::{CheckLintNameResult, LintStore}; use crate::diagnostics::{ - CheckNameUnknownTool, MalformedAttribute, MalformedAttributeSub, OverruledAttribute, - OverruledAttributeSub, RequestedLevel, UnknownToolInScopedLint, UnsupportedGroup, + CheckNameUnknownTool, DeprecatedLintName, DeprecatedLintNameFromCommandLine, + IgnoredUnlessCrateSpecified, MalformedAttribute, MalformedAttributeSub, OverruledAttribute, + OverruledAttributeLint, OverruledAttributeSub, RemovedLint, RemovedLintFromCommandLine, + RenamedLint, RenamedLintFromCommandLine, RenamedLintSuggestion, RequestedLevel, UnknownLint, + UnknownLintFromCommandLine, UnknownLintSuggestion, UnknownToolInScopedLint, UnsupportedGroup, }; use crate::late::unerased_lint_store; -use crate::lints::{ - DeprecatedLintName, DeprecatedLintNameFromCommandLine, IgnoredUnlessCrateSpecified, - OverruledAttributeLint, RemovedLint, RemovedLintFromCommandLine, RenamedLint, - RenamedLintFromCommandLine, RenamedLintSuggestion, UnknownLint, UnknownLintFromCommandLine, - UnknownLintSuggestion, -}; /// Collection of lint levels for the whole crate. /// This is used by AST-based lints, which do not diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index fb7d5b6a3133d..223e2e4a598c6 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -58,7 +58,6 @@ mod late; mod let_underscore; mod levels; pub mod lifetime_syntax; -mod lints; mod macro_expr_fragment_specifier_2024_migration; mod map_unit_fn; mod multiple_supertrait_upcastable; diff --git a/compiler/rustc_lint/src/lifetime_syntax.rs b/compiler/rustc_lint/src/lifetime_syntax.rs index 1f3ecb03ebfc6..d273ed505e6e7 100644 --- a/compiler/rustc_lint/src/lifetime_syntax.rs +++ b/compiler/rustc_lint/src/lifetime_syntax.rs @@ -6,7 +6,7 @@ use rustc_span::Span; use rustc_span::def_id::LocalDefId; use tracing::instrument; -use crate::{LateContext, LateLintPass, LintContext, lints}; +use crate::{LateContext, LateLintPass, LintContext, diagnostics}; declare_lint! { /// The `mismatched_lifetime_syntaxes` lint detects when the same @@ -397,7 +397,7 @@ fn emit_mismatch_diagnostic<'tcx>( &suggest_change_to_mixed_explicit_anonymous, ); - lints::MismatchedLifetimeSyntaxesSuggestion::Mixed { + diagnostics::MismatchedLifetimeSyntaxesSuggestion::Mixed { implicit_suggestions, explicit_anonymous_suggestions, optional_alternative: false, @@ -421,7 +421,7 @@ fn emit_mismatch_diagnostic<'tcx>( let implicit_suggestion = should_suggest_implicit.then(|| { let suggestions = make_implicit_suggestions(&suggest_change_to_implicit); - lints::MismatchedLifetimeSyntaxesSuggestion::Implicit { + diagnostics::MismatchedLifetimeSyntaxesSuggestion::Implicit { suggestions, optional_alternative: false, } @@ -464,19 +464,19 @@ fn emit_mismatch_diagnostic<'tcx>( cx.emit_span_lint( MISMATCHED_LIFETIME_SYNTAXES, inputs.iter_unnamed().chain(outputs.iter_unnamed()).copied().collect::>(), - lints::MismatchedLifetimeSyntaxes { inputs, outputs, suggestions }, + diagnostics::MismatchedLifetimeSyntaxes { inputs, outputs, suggestions }, ); } fn build_mismatch_suggestion( lifetime_name: &str, infos: &[&Info<'_>], -) -> lints::MismatchedLifetimeSyntaxesSuggestion { +) -> diagnostics::MismatchedLifetimeSyntaxesSuggestion { let lifetime_name = lifetime_name.to_owned(); let suggestions = build_mismatch_suggestions_for_lifetime(&lifetime_name, infos); - lints::MismatchedLifetimeSyntaxesSuggestion::Explicit { + diagnostics::MismatchedLifetimeSyntaxesSuggestion::Explicit { lifetime_name, suggestions, optional_alternative: false, diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs deleted file mode 100644 index a652ea753e421..0000000000000 --- a/compiler/rustc_lint/src/lints.rs +++ /dev/null @@ -1,3045 +0,0 @@ -// ignore-tidy-file-filelength - -use std::num::NonZero; - -use rustc_data_structures::fx::FxIndexMap; -use rustc_errors::codes::*; -use rustc_errors::formatting::DiagMessageAddArg; -use rustc_errors::{ - Applicability, Diag, DiagCtxtHandle, DiagMessage, DiagStyledString, Diagnostic, - EmissionGuarantee, Level, Subdiagnostic, SuggestionStyle, msg, -}; -use rustc_hir as hir; -use rustc_hir::def_id::DefId; -use rustc_hir::intravisit::VisitorExt; -use rustc_macros::{Diagnostic, Subdiagnostic}; -use rustc_middle::ty::inhabitedness::InhabitedPredicate; -use rustc_middle::ty::{Clause, PolyExistentialTraitRef, Ty, TyCtxt}; -use rustc_session::Session; -use rustc_span::edition::Edition; -use rustc_span::{Ident, Span, Symbol, sym}; - -use crate::LateContext; -use crate::builtin::{InitError, ShorthandAssocTyCollector, TypeAliasBounds}; -use crate::diagnostics::{OverruledAttributeSub, RequestedLevel}; -use crate::lifetime_syntax::LifetimeSyntaxCategories; - -// array_into_iter.rs -#[derive(Diagnostic)] -#[diag( - "this method call resolves to `<&{$target} as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to `<{$target} as IntoIterator>::into_iter` in Rust {$edition}" -)] -pub(crate) struct ShadowedIntoIterDiag { - pub target: &'static str, - pub edition: &'static str, - #[suggestion( - "use `.iter()` instead of `.into_iter()` to avoid ambiguity", - code = "iter", - applicability = "machine-applicable" - )] - pub suggestion: Span, - #[subdiagnostic] - pub sub: Option, -} - -#[derive(Subdiagnostic)] -pub(crate) enum ShadowedIntoIterDiagSub { - #[suggestion( - "or remove `.into_iter()` to iterate by value", - code = "", - applicability = "maybe-incorrect" - )] - RemoveIntoIter { - #[primary_span] - span: Span, - }, - #[multipart_suggestion( - "or use `IntoIterator::into_iter(..)` instead of `.into_iter()` to explicitly iterate by value", - applicability = "maybe-incorrect" - )] - UseExplicitIntoIter { - #[suggestion_part(code = "IntoIterator::into_iter(")] - start_span: Span, - #[suggestion_part(code = ")")] - end_span: Span, - }, -} - -// autorefs.rs -#[derive(Diagnostic)] -#[diag("implicit autoref creates a reference to the dereference of a raw pointer")] -#[note( - "creating a reference requires the pointer target to be valid and imposes aliasing requirements" -)] -pub(crate) struct ImplicitUnsafeAutorefsDiag<'a> { - #[label("this raw pointer has type `{$raw_ptr_ty}`")] - pub raw_ptr_span: Span, - pub raw_ptr_ty: Ty<'a>, - #[subdiagnostic] - pub origin: ImplicitUnsafeAutorefsOrigin<'a>, - #[subdiagnostic] - pub method: Option, - #[subdiagnostic] - pub suggestion: ImplicitUnsafeAutorefsSuggestion, -} - -#[derive(Subdiagnostic)] -pub(crate) enum ImplicitUnsafeAutorefsOrigin<'a> { - #[note("autoref is being applied to this expression, resulting in: `{$autoref_ty}`")] - Autoref { - #[primary_span] - autoref_span: Span, - autoref_ty: Ty<'a>, - }, - #[note( - "references are created through calls to explicit `Deref(Mut)::deref(_mut)` implementations" - )] - OverloadedDeref, -} - -#[derive(Subdiagnostic)] -#[note("method calls to `{$method_name}` require a reference")] -pub(crate) struct ImplicitUnsafeAutorefsMethodNote { - #[primary_span] - pub def_span: Span, - pub method_name: Symbol, -} - -#[derive(Subdiagnostic)] -#[multipart_suggestion( - "try using a raw pointer method instead; or if this reference is intentional, make it explicit", - applicability = "maybe-incorrect" -)] -pub(crate) struct ImplicitUnsafeAutorefsSuggestion { - pub mutbl: &'static str, - pub deref: &'static str, - #[suggestion_part(code = "({mutbl}{deref}")] - pub start_span: Span, - #[suggestion_part(code = ")")] - pub end_span: Span, -} - -// builtin.rs -#[derive(Diagnostic)] -#[diag("denote infinite loops with `loop {\"{\"} ... {\"}\"}`")] -pub(crate) struct BuiltinWhileTrue { - #[suggestion( - "use `loop`", - style = "short", - code = "{replace}", - applicability = "machine-applicable" - )] - pub suggestion: Span, - pub replace: String, -} - -#[derive(Diagnostic)] -#[diag("the `{$ident}:` in this pattern is redundant")] -pub(crate) struct BuiltinNonShorthandFieldPatterns { - pub ident: Ident, - #[suggestion( - "use shorthand field pattern", - code = "{prefix}{ident}", - applicability = "machine-applicable" - )] - pub suggestion: Span, - pub prefix: &'static str, -} - -#[derive(Diagnostic)] -pub(crate) enum BuiltinUnsafe { - #[diag( - "`allow_internal_unsafe` allows defining macros using unsafe without triggering the `unsafe_code` lint at their call site" - )] - AllowInternalUnsafe, - #[diag("usage of an `unsafe` block")] - UnsafeBlock, - #[diag("usage of an `unsafe extern` block")] - UnsafeExternBlock, - #[diag("declaration of an `unsafe` trait")] - UnsafeTrait, - #[diag("implementation of an `unsafe` trait")] - UnsafeImpl, - #[diag("declaration of an `unsafe` function")] - DeclUnsafeFn, - #[diag("declaration of an `unsafe` method")] - DeclUnsafeMethod, - #[diag("implementation of an `unsafe` method")] - ImplUnsafeMethod, - #[diag("usage of `core::arch::global_asm`")] - #[note("using this macro is unsafe even though it does not need an `unsafe` block")] - GlobalAsm, -} - -#[derive(Diagnostic)] -#[diag("missing documentation for {$article} {$desc}")] -pub(crate) struct BuiltinMissingDoc<'a> { - pub article: &'a str, - pub desc: &'a str, -} - -#[derive(Diagnostic)] -#[diag("type could implement `Copy`; consider adding `impl Copy`")] -pub(crate) struct BuiltinMissingCopyImpl; - -pub(crate) struct BuiltinMissingDebugImpl<'a> { - pub tcx: TyCtxt<'a>, - pub def_id: DefId, -} - -// Needed for def_path_str -impl<'a> Diagnostic<'a, ()> for BuiltinMissingDebugImpl<'_> { - fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> { - let Self { tcx, def_id } = self; - Diag::new( - dcx, - level, - msg!("type does not implement `{$debug}`; consider adding `#[derive(Debug)]` or a manual implementation"), - ).with_arg("debug", tcx.def_path_str(def_id)) - } -} - -#[derive(Diagnostic)] -#[diag("anonymous parameters are deprecated and will be removed in the next edition")] -pub(crate) struct BuiltinAnonymousParams<'a> { - #[suggestion("try naming the parameter or explicitly ignoring it", code = "_: {ty_snip}")] - pub suggestion: (Span, Applicability), - pub ty_snip: &'a str, -} - -#[derive(Diagnostic)] -#[diag("unused doc comment")] -pub(crate) struct BuiltinUnusedDocComment<'a> { - pub kind: &'a str, - #[label("rustdoc does not generate documentation for {$kind}")] - pub label: Span, - #[subdiagnostic] - pub sub: BuiltinUnusedDocCommentSub, -} - -#[derive(Subdiagnostic)] -pub(crate) enum BuiltinUnusedDocCommentSub { - #[help("use `//` for a plain comment")] - PlainHelp, - #[help("use `/* */` for a plain comment")] - BlockHelp, -} - -#[derive(Diagnostic)] -#[diag("const items should never be `#[no_mangle]`")] -pub(crate) struct BuiltinConstNoMangle { - #[suggestion("try a static value", code = "pub static ", applicability = "machine-applicable")] - pub suggestion: Option, -} - -#[derive(Diagnostic)] -#[diag( - "transmuting &T to &mut T is undefined behavior, even if the reference is unused, consider instead using an UnsafeCell" -)] -pub(crate) struct BuiltinMutablesTransmutes; - -#[derive(Diagnostic)] -#[diag("use of an unstable feature")] -pub(crate) struct BuiltinUnstableFeatures; - -// lint_ungated_async_fn_track_caller -pub(crate) struct BuiltinUngatedAsyncFnTrackCaller<'a> { - pub label: Span, - pub session: &'a Session, -} - -impl<'a> Diagnostic<'a, ()> for BuiltinUngatedAsyncFnTrackCaller<'_> { - fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> { - let mut diag = Diag::new(dcx, level, "`#[track_caller]` on async functions is a no-op") - .with_span_label(self.label, "this function will not propagate the caller location"); - rustc_session::diagnostics::add_feature_diagnostics( - &mut diag, - self.session, - sym::async_fn_track_caller, - ); - diag - } -} - -#[derive(Diagnostic)] -#[diag("unreachable `pub` {$what}")] -pub(crate) struct BuiltinUnreachablePub<'a> { - pub what: &'a str, - pub new_vis: &'a str, - #[suggestion("consider restricting its visibility", code = "{new_vis}")] - pub suggestion: (Span, Applicability), - #[help("or consider exporting it for use by other crates")] - pub help: bool, -} - -#[derive(Diagnostic)] -#[diag("the `expr` fragment specifier will accept more expressions in the 2024 edition")] -pub(crate) struct MacroExprFragment2024 { - #[suggestion( - "to keep the existing behavior, use the `expr_2021` fragment specifier", - code = "expr_2021", - applicability = "machine-applicable" - )] - pub suggestion: Span, -} - -pub(crate) struct BuiltinTypeAliasBounds<'hir> { - pub in_where_clause: bool, - pub label: Span, - pub enable_feat_help: bool, - pub suggestions: Vec<(Span, String)>, - pub preds: &'hir [hir::WherePredicate<'hir>], - pub ty: Option<&'hir hir::Ty<'hir>>, -} - -impl<'a> Diagnostic<'a, ()> for BuiltinTypeAliasBounds<'_> { - fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> { - let mut diag = Diag::new(dcx, level, if self.in_where_clause { - msg!("where clauses on type aliases are not enforced") - } else { - msg!("bounds on generic parameters in type aliases are not enforced") - }) - .with_span_label(self.label, msg!("will not be checked at usage sites of the type alias")) - .with_note(msg!( - "this is a known limitation of the type checker that may be lifted in a future edition. - see issue #112792 for more information" - )); - if self.enable_feat_help { - diag.help(msg!("add `#![feature(checked_type_aliases)]` to the crate attributes to enable the desired semantics")); - } - - // We perform the walk in here instead of in `` to - // avoid doing throwaway work in case the lint ends up getting suppressed. - let mut collector = ShorthandAssocTyCollector { qselves: Vec::new() }; - if let Some(ty) = self.ty { - collector.visit_ty_unambig(ty); - } - - let affect_object_lifetime_defaults = self - .preds - .iter() - .filter(|pred| pred.kind.in_where_clause() == self.in_where_clause) - .any(|pred| TypeAliasBounds::affects_object_lifetime_defaults(pred)); - - // If there are any shorthand assoc tys, then the bounds can't be removed automatically. - // The user first needs to fully qualify the assoc tys. - let applicability = if !collector.qselves.is_empty() || affect_object_lifetime_defaults { - Applicability::MaybeIncorrect - } else { - Applicability::MachineApplicable - }; - - diag.arg("count", self.suggestions.len()); - diag.multipart_suggestion( - if self.in_where_clause { - msg!("remove this where clause") - } else { - msg!( - "remove {$count -> - [one] this bound - *[other] these bounds - }" - ) - }, - self.suggestions, - applicability, - ); - - // Suggest fully qualifying paths of the form `T::Assoc` with `T` type param via - // `::Assoc` to remove their reliance on any type param bounds. - // - // Instead of attempting to figure out the necessary trait ref, just use a - // placeholder. Since we don't record type-dependent resolutions for non-body - // items like type aliases, we can't simply deduce the corresp. trait from - // the HIR path alone without rerunning parts of HIR ty lowering here - // (namely `probe_single_ty_param_bound_for_assoc_ty`) which is infeasible. - // - // (We could employ some simple heuristics but that's likely not worth it). - for qself in collector.qselves { - diag.multipart_suggestion( - msg!("fully qualify this associated type"), - vec![ - (qself.shrink_to_lo(), "<".into()), - (qself.shrink_to_hi(), " as /* Trait */>".into()), - ], - Applicability::HasPlaceholders, - ); - } - diag - } -} - -#[derive(Diagnostic)] -#[diag("{$clause_kind_name} bound {$clause} does not depend on any type or lifetime parameters")] -pub(crate) struct BuiltinTrivialBounds<'a> { - pub clause_kind_name: &'a str, - pub clause: Clause<'a>, -} - -#[derive(Diagnostic)] -#[diag("use of a double negation")] -#[note( - "the prefix `--` could be misinterpreted as a decrement operator which exists in other languages" -)] -#[note("use `-= 1` if you meant to decrement the value")] -pub(crate) struct BuiltinDoubleNegations { - #[subdiagnostic] - pub add_parens: BuiltinDoubleNegationsAddParens, -} - -#[derive(Subdiagnostic)] -#[multipart_suggestion("add parentheses for clarity", applicability = "maybe-incorrect")] -pub(crate) struct BuiltinDoubleNegationsAddParens { - #[suggestion_part(code = "(")] - pub start_span: Span, - #[suggestion_part(code = ")")] - pub end_span: Span, -} - -#[derive(Diagnostic)] -pub(crate) enum BuiltinEllipsisInclusiveRangePatternsLint { - #[diag("`...` range patterns are deprecated")] - Parenthesise { - #[suggestion( - "use `..=` for an inclusive range", - code = "{replace}", - applicability = "machine-applicable" - )] - suggestion: Span, - replace: String, - }, - #[diag("`...` range patterns are deprecated")] - NonParenthesise { - #[suggestion( - "use `..=` for an inclusive range", - style = "short", - code = "..=", - applicability = "machine-applicable" - )] - suggestion: Span, - }, -} - -#[derive(Diagnostic)] -#[diag("`{$kw}` is a keyword in the {$next} edition")] -pub(crate) struct BuiltinKeywordIdents { - pub kw: Ident, - pub next: Edition, - #[suggestion( - "you can use a raw identifier to stay compatible", - code = "{prefix}r#{kw}", - applicability = "machine-applicable" - )] - pub suggestion: Span, - pub prefix: &'static str, -} - -#[derive(Diagnostic)] -#[diag("outlives requirements can be inferred")] -pub(crate) struct BuiltinExplicitOutlives { - #[subdiagnostic] - pub suggestion: BuiltinExplicitOutlivesSuggestion, -} - -#[derive(Subdiagnostic)] -#[multipart_suggestion( - "remove {$count -> - [one] this bound - *[other] these bounds - }" -)] -pub(crate) struct BuiltinExplicitOutlivesSuggestion { - #[suggestion_part(code = "")] - pub spans: Vec, - #[applicability] - pub applicability: Applicability, - pub count: usize, -} - -#[derive(Diagnostic)] -#[diag( - "the feature `{$name}` is incomplete and may not be safe to use and/or cause compiler crashes" -)] -pub(crate) struct BuiltinIncompleteFeatures { - pub name: Symbol, - #[subdiagnostic] - pub note: Option, - #[subdiagnostic] - pub help: Option, -} - -#[derive(Diagnostic)] -#[diag("the feature `{$name}` is internal to the compiler or standard library")] -#[note("using it is strongly discouraged")] -pub(crate) struct BuiltinInternalFeatures { - pub name: Symbol, -} - -#[derive(Subdiagnostic)] -#[help("consider using `min_{$name}` instead, which is more stable and complete")] -pub(crate) struct BuiltinIncompleteFeaturesHelp { - pub name: Symbol, -} - -#[derive(Subdiagnostic)] -#[note("see issue #{$n} for more information")] -pub(crate) struct BuiltinFeatureIssueNote { - pub n: NonZero, -} - -pub(crate) struct BuiltinUnpermittedTypeInit<'a> { - pub msg: DiagMessage, - pub ty: Ty<'a>, - pub label: Span, - pub sub: BuiltinUnpermittedTypeInitSub, - pub tcx: TyCtxt<'a>, -} - -impl<'a> Diagnostic<'a, ()> for BuiltinUnpermittedTypeInit<'_> { - fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> { - let mut diag = Diag::new(dcx, level, self.msg) - .with_arg("ty", self.ty) - .with_span_label(self.label, msg!("this code causes undefined behavior when executed")); - if let InhabitedPredicate::True = self.ty.inhabited_predicate(self.tcx) { - // Only suggest late `MaybeUninit::assume_init` initialization if the type is inhabited. - diag.span_label( - self.label, - msg!("help: use `MaybeUninit` instead, and only call `assume_init` after initialization is done"), - ); - } - self.sub.add_to_diag(&mut diag); - diag - } -} - -// FIXME(davidtwco): make translatable -pub(crate) struct BuiltinUnpermittedTypeInitSub { - pub err: InitError, -} - -impl Subdiagnostic for BuiltinUnpermittedTypeInitSub { - fn add_to_diag(self, diag: &mut Diag<'_, G>) { - let mut err = self.err; - loop { - if let Some(span) = err.span { - diag.span_note(span, err.message); - } else { - diag.note(err.message); - } - if let Some(e) = err.nested { - err = *e; - } else { - break; - } - } - } -} - -#[derive(Diagnostic)] -pub(crate) enum BuiltinClashingExtern<'a> { - #[diag("`{$this}` redeclared with a different signature")] - SameName { - this: Symbol, - orig: Symbol, - #[label("`{$orig}` previously declared here")] - previous_decl_label: Span, - #[label("this signature doesn't match the previous declaration")] - mismatch_label: Span, - #[subdiagnostic] - sub: BuiltinClashingExternSub<'a>, - }, - #[diag("`{$this}` redeclares `{$orig}` with a different signature")] - DiffName { - this: Symbol, - orig: Symbol, - #[label("`{$orig}` previously declared here")] - previous_decl_label: Span, - #[label("this signature doesn't match the previous declaration")] - mismatch_label: Span, - #[subdiagnostic] - sub: BuiltinClashingExternSub<'a>, - }, -} - -// FIXME(davidtwco): translatable expected/found -pub(crate) struct BuiltinClashingExternSub<'a> { - pub tcx: TyCtxt<'a>, - pub expected: Ty<'a>, - pub found: Ty<'a>, -} - -impl Subdiagnostic for BuiltinClashingExternSub<'_> { - fn add_to_diag(self, diag: &mut Diag<'_, G>) { - let mut expected_str = DiagStyledString::new(); - expected_str.push(self.expected.fn_sig(self.tcx).to_string(), false); - let mut found_str = DiagStyledString::new(); - found_str.push(self.found.fn_sig(self.tcx).to_string(), true); - diag.note_expected_found("", expected_str, "", found_str); - } -} - -#[derive(Diagnostic)] -#[diag("dereferencing a null pointer")] -pub(crate) struct BuiltinDerefNullptr { - #[label("this code causes undefined behavior when executed")] - pub label: Span, -} - -#[derive(Diagnostic)] -pub(crate) enum BuiltinSpecialModuleNameUsed { - #[diag("found module declaration for lib.rs")] - #[note("lib.rs is the root of this crate's library target")] - #[help("to refer to it from other targets, use the library's name as the path")] - Lib, - #[diag("found module declaration for main.rs")] - #[note("a binary crate cannot be used as library")] - Main, -} - -// c_void_return.rs -#[derive(Diagnostic)] -#[diag("`c_void` should not be used as a return type")] -#[help("returning `()` in Rust is equivalent to returning `void` in C")] -pub(crate) struct CVoidReturn { - #[suggestion( - "remove the return type to implicitly return `()`", - code = "", - applicability = "maybe-incorrect" - )] - pub suggestion: Span, -} - -// c_void_return.rs -#[derive(Diagnostic)] -#[diag("declarations returning `c_void` are not compatible with C functions returning `void`")] -#[help("returning `()` in Rust is equivalent to returning `void` in C")] -#[note("`c_void` is only used through raw pointers for compatibility with `void` pointers")] -pub(crate) struct ExternCVoidReturn { - #[suggestion( - "remove the return type to implicitly return `()`", - code = "", - applicability = "maybe-incorrect" - )] - pub suggestion: Span, -} - -// deref_into_dyn_supertrait.rs -#[derive(Diagnostic)] -#[diag("this `Deref` implementation is covered by an implicit supertrait coercion")] -pub(crate) struct SupertraitAsDerefTarget<'a> { - pub self_ty: Ty<'a>, - pub supertrait_principal: PolyExistentialTraitRef<'a>, - pub target_principal: PolyExistentialTraitRef<'a>, - #[label( - "`{$self_ty}` implements `Deref` which conflicts with supertrait `{$supertrait_principal}`" - )] - pub label: Span, - #[subdiagnostic] - pub label2: Option>, -} - -#[derive(Subdiagnostic)] -#[label("target type is a supertrait of `{$self_ty}`")] -pub(crate) struct SupertraitAsDerefTargetLabel<'a> { - #[primary_span] - pub label: Span, - pub self_ty: Ty<'a>, -} - -// enum_intrinsics_non_enums.rs -#[derive(Diagnostic)] -#[diag("the return value of `mem::discriminant` is unspecified when called with a non-enum type")] -pub(crate) struct EnumIntrinsicsMemDiscriminate<'a> { - pub ty_param: Ty<'a>, - #[note( - "the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `{$ty_param}`, which is not an enum" - )] - pub note: Span, -} - -#[derive(Diagnostic)] -#[diag("the return value of `mem::variant_count` is unspecified when called with a non-enum type")] -#[note( - "the type parameter of `variant_count` should be an enum, but it was instantiated with the type `{$ty_param}`, which is not an enum" -)] -pub(crate) struct EnumIntrinsicsMemVariant<'a> { - pub ty_param: Ty<'a>, -} - -// expect.rs -#[derive(Diagnostic)] -#[diag("this lint expectation is unfulfilled")] -pub(crate) struct Expectation { - #[subdiagnostic] - pub rationale: Option, - #[note( - "the `unfulfilled_lint_expectations` lint can't be expected and will always produce this message" - )] - pub note: bool, -} - -#[derive(Subdiagnostic)] -#[note("{$rationale}")] -pub(crate) struct ExpectationNote { - pub rationale: Symbol, -} - -// ptr_nulls.rs -#[derive(Diagnostic)] -pub(crate) enum UselessPtrNullChecksDiag<'a> { - #[diag( - "function pointers are not nullable, so checking them for null will always return false" - )] - #[help( - "wrap the function pointer inside an `Option` and use `Option::is_none` to check for null pointer value" - )] - FnPtr { - orig_ty: Ty<'a>, - #[label("expression has type `{$orig_ty}`")] - label: Span, - }, - #[diag("references are not nullable, so checking them for null will always return false")] - Ref { - orig_ty: Ty<'a>, - #[label("expression has type `{$orig_ty}`")] - label: Span, - }, - #[diag( - "returned pointer of `{$fn_name}` call is never null, so checking it for null will always return false" - )] - FnRet { fn_name: Ident }, -} - -#[derive(Diagnostic)] -pub(crate) enum InvalidNullArgumentsDiag { - #[diag( - "calling this function with a null pointer is undefined behavior, even if the result of the function is unused" - )] - #[help( - "for more information, visit and " - )] - NullPtrInline { - #[label("null pointer originates from here")] - null_span: Span, - }, - #[diag( - "calling this function with a null pointer is undefined behavior, even if the result of the function is unused" - )] - #[help( - "for more information, visit and " - )] - NullPtrThroughBinding { - #[note("null pointer originates from here")] - null_span: Span, - }, -} - -// for_loops_over_fallibles.rs -#[derive(Diagnostic)] -#[diag( - "for loop over {$article} `{$ref_prefix}{$ty}`. This is more readably written as an `if let` statement" -)] -pub(crate) struct ForLoopsOverFalliblesDiag<'a> { - pub article: &'static str, - pub ref_prefix: &'static str, - pub ty: &'static str, - #[subdiagnostic] - pub sub: ForLoopsOverFalliblesLoopSub<'a>, - #[subdiagnostic] - pub question_mark: Option, - #[subdiagnostic] - pub suggestion: ForLoopsOverFalliblesSuggestion<'a>, -} - -#[derive(Subdiagnostic)] -pub(crate) enum ForLoopsOverFalliblesLoopSub<'a> { - #[suggestion( - "to iterate over `{$recv_snip}` remove the call to `next`", - code = ".by_ref()", - applicability = "maybe-incorrect" - )] - RemoveNext { - #[primary_span] - suggestion: Span, - recv_snip: String, - }, - #[multipart_suggestion( - "to check pattern in a loop use `while let`", - applicability = "maybe-incorrect" - )] - UseWhileLet { - #[suggestion_part(code = "while let {var}(")] - start_span: Span, - #[suggestion_part(code = ") = ")] - end_span: Span, - var: &'a str, - }, -} - -#[derive(Subdiagnostic)] -#[suggestion( - "consider unwrapping the `Result` with `?` to iterate over its contents", - code = "?", - applicability = "maybe-incorrect" -)] -pub(crate) struct ForLoopsOverFalliblesQuestionMark { - #[primary_span] - pub suggestion: Span, -} - -#[derive(Subdiagnostic)] -#[multipart_suggestion( - "consider using `if let` to clear intent", - applicability = "maybe-incorrect" -)] -pub(crate) struct ForLoopsOverFalliblesSuggestion<'a> { - pub var: &'a str, - #[suggestion_part(code = "if let {var}(")] - pub start_span: Span, - #[suggestion_part(code = ") = ")] - pub end_span: Span, -} - -#[derive(Subdiagnostic)] -pub(crate) enum UseLetUnderscoreIgnoreSuggestion { - #[note("use `let _ = ...` to ignore the expression or result")] - Note, - #[multipart_suggestion( - "use `let _ = ...` to ignore the expression or result", - style = "verbose", - applicability = "maybe-incorrect" - )] - Suggestion { - #[suggestion_part(code = "let _ = ")] - start_span: Span, - #[suggestion_part(code = "")] - end_span: Span, - }, -} - -// runtime_symbols.rs -#[derive(Diagnostic)] -pub(crate) enum RedefiningRuntimeSymbolsDiag<'tcx> { - #[diag( - "invalid definition of the runtime `{$symbol_name}` symbol used by the standard library" - )] - #[note( - "expected `{$expected_fn_sig}` (for the current target) - found `{$found_fn_sig}`" - )] - #[help( - "either fix the signature or remove any attributes like `#[unsafe(no_mangle)]`, `#[unsafe(export_name = \"{$symbol_name}\")]`, or `#[link_name = \"{$symbol_name}\"]`" - )] - Invalid { symbol_name: String, expected_fn_sig: Ty<'tcx>, found_fn_sig: Ty<'tcx> }, - #[diag( - "suspicious definition of the runtime `{$symbol_name}` symbol used by the standard library" - )] - #[note( - "expected `{$expected_fn_sig}` (for the current target) - found `{$found_fn_sig}`" - )] - #[help( - "either fix the signature or remove any attributes like `#[unsafe(no_mangle)]`, `#[unsafe(export_name = \"{$symbol_name}\")]`, or `#[link_name = \"{$symbol_name}\"]`" - )] - #[help("allow this lint if the signature is compatible")] - Suspicious { symbol_name: String, expected_fn_sig: Ty<'tcx>, found_fn_sig: Ty<'tcx> }, -} - -// drop_forget_useless.rs -#[derive(Diagnostic)] -#[diag("calls to `std::mem::drop` with a reference instead of an owned value does nothing")] -pub(crate) struct DropRefDiag<'a> { - pub arg_ty: Ty<'a>, - #[label("argument has type `{$arg_ty}`")] - pub label: Span, - #[subdiagnostic] - pub sugg: UseLetUnderscoreIgnoreSuggestion, -} - -#[derive(Diagnostic)] -#[diag("calls to `std::mem::drop` with a value that implements `Copy` does nothing")] -pub(crate) struct DropCopyDiag<'a> { - pub arg_ty: Ty<'a>, - #[label("argument has type `{$arg_ty}`")] - pub label: Span, - #[subdiagnostic] - pub sugg: UseLetUnderscoreIgnoreSuggestion, -} - -#[derive(Diagnostic)] -#[diag("calls to `std::mem::forget` with a reference instead of an owned value does nothing")] -pub(crate) struct ForgetRefDiag<'a> { - pub arg_ty: Ty<'a>, - #[label("argument has type `{$arg_ty}`")] - pub label: Span, - #[subdiagnostic] - pub sugg: UseLetUnderscoreIgnoreSuggestion, -} - -#[derive(Diagnostic)] -#[diag("calls to `std::mem::forget` with a value that implements `Copy` does nothing")] -pub(crate) struct ForgetCopyDiag<'a> { - pub arg_ty: Ty<'a>, - #[label("argument has type `{$arg_ty}`")] - pub label: Span, - #[subdiagnostic] - pub sugg: UseLetUnderscoreIgnoreSuggestion, -} - -#[derive(Diagnostic)] -#[diag( - "calls to `std::mem::drop` with `std::mem::ManuallyDrop` instead of the inner value does nothing" -)] -pub(crate) struct UndroppedManuallyDropsDiag<'a> { - pub arg_ty: Ty<'a>, - #[label("argument has type `{$arg_ty}`")] - pub label: Span, - #[subdiagnostic] - pub suggestion: UndroppedManuallyDropsSuggestion, -} - -#[derive(Subdiagnostic)] -#[multipart_suggestion( - "use `std::mem::ManuallyDrop::into_inner` to get the inner value", - applicability = "machine-applicable" -)] -pub(crate) struct UndroppedManuallyDropsSuggestion { - #[suggestion_part(code = "std::mem::ManuallyDrop::into_inner(")] - pub start_span: Span, - #[suggestion_part(code = ")")] - pub end_span: Span, -} - -// invalid_from_utf8.rs -#[derive(Diagnostic)] -pub(crate) enum InvalidFromUtf8Diag { - #[diag("calls to `{$method}` with an invalid literal are undefined behavior")] - Unchecked { - method: String, - valid_up_to: usize, - #[label("the literal was valid UTF-8 up to the {$valid_up_to} bytes")] - label: Span, - }, - #[diag("calls to `{$method}` with an invalid literal always return an error")] - Checked { - method: String, - valid_up_to: usize, - #[label("the literal was valid UTF-8 up to the {$valid_up_to} bytes")] - label: Span, - }, -} - -// interior_mutable_consts.rs -#[derive(Diagnostic)] -#[diag("mutation of an interior mutable `const` item with call to `{$method_name}`")] -#[note("each usage of a `const` item creates a new temporary")] -#[note("only the temporaries and never the original `const {$const_name}` will be modified")] -#[help( - "for more details on interior mutability see " -)] -pub(crate) struct ConstItemInteriorMutationsDiag<'tcx> { - pub method_name: Ident, - pub const_name: Ident, - pub const_ty: Ty<'tcx>, - #[label("`{$const_name}` is a interior mutable `const` item of type `{$const_ty}`")] - pub receiver_span: Span, - #[subdiagnostic] - pub sugg_static: Option, -} - -#[derive(Subdiagnostic)] -pub(crate) enum ConstItemInteriorMutationsSuggestionStatic { - #[suggestion( - "for a shared instance of `{$const_name}`, consider making it a `static` item instead", - code = "{before}static ", - style = "verbose", - applicability = "maybe-incorrect" - )] - Spanful { - #[primary_span] - const_: Span, - before: &'static str, - const_name: Ident, - }, - #[help("for a shared instance of `{$const_name}`, consider making it a `static` item instead")] - Spanless { const_name: Ident }, -} - -// reference_casting.rs -#[derive(Diagnostic)] -pub(crate) enum InvalidReferenceCastingDiag<'tcx> { - #[diag( - "casting `&T` to `&mut T` is undefined behavior, even if the reference is unused, consider instead using an `UnsafeCell`" - )] - #[note( - "for more information, visit " - )] - BorrowAsMut { - #[label("casting happened here")] - orig_cast: Option, - }, - #[diag("assigning to `&T` is undefined behavior, consider using an `UnsafeCell`")] - #[note( - "for more information, visit " - )] - AssignToRef { - #[label("casting happened here")] - orig_cast: Option, - }, - #[diag( - "casting references to a bigger memory layout than the backing allocation is undefined behavior, even if the reference is unused" - )] - #[note("casting from `{$from_ty}` ({$from_size} bytes) to `{$to_ty}` ({$to_size} bytes)")] - BiggerLayout { - #[label("casting happened here")] - orig_cast: Option, - #[label("backing allocation comes from here")] - alloc: Span, - from_ty: Ty<'tcx>, - from_size: u64, - to_ty: Ty<'tcx>, - to_size: u64, - }, -} - -// map_unit_fn.rs -#[derive(Diagnostic)] -#[diag("`Iterator::map` call that discard the iterator's values")] -#[note( - "`Iterator::map`, like many of the methods on `Iterator`, gets executed lazily, meaning that its effects won't be visible until it is iterated" -)] -pub(crate) struct MappingToUnit { - #[label("this function returns `()`, which is likely not what you wanted")] - pub function_label: Span, - #[label("called `Iterator::map` with callable that returns `()`")] - pub argument_label: Span, - #[label( - "after this call to map, the resulting iterator is `impl Iterator`, which means the only information carried by the iterator is the number of items" - )] - pub map_label: Span, - #[suggestion( - "you might have meant to use `Iterator::for_each`", - style = "verbose", - code = "for_each", - applicability = "maybe-incorrect" - )] - pub suggestion: Span, -} - -// internal.rs -#[derive(Diagnostic)] -#[diag("prefer `{$preferred}` over `{$used}`, it has better performance")] -#[note("a `use rustc_data_structures::fx::{$preferred}` may be necessary")] -pub(crate) struct DefaultHashTypesDiag<'a> { - pub preferred: &'a str, - pub used: Symbol, -} - -#[derive(Diagnostic)] -#[diag("using `{$query}` can result in unstable query results")] -#[note( - "if you believe this case to be fine, allow this lint and add a comment explaining your rationale" -)] -pub(crate) struct QueryInstability { - pub query: Symbol, -} - -#[derive(Diagnostic)] -#[diag("`{$method}` accesses information that is not tracked by the query system")] -#[note( - "if you believe this case to be fine, allow this lint and add a comment explaining your rationale" -)] -pub(crate) struct QueryUntracked { - pub method: Symbol, -} - -#[derive(Diagnostic)] -#[diag("use `.eq_ctxt()` instead of `.ctxt() == .ctxt()`")] -pub(crate) struct SpanUseEqCtxtDiag; - -#[derive(Diagnostic)] -#[diag("using `Symbol::intern` on a string literal")] -#[help("consider adding the symbol to `compiler/rustc_span/src/symbol.rs`")] -pub(crate) struct SymbolInternStringLiteralDiag; - -#[derive(Diagnostic)] -#[diag("usage of `ty::TyKind::`")] -pub(crate) struct TykindKind { - #[suggestion( - "try using `ty::` directly", - code = "ty", - applicability = "maybe-incorrect" - )] - pub suggestion: Span, -} - -#[derive(Diagnostic)] -#[diag("usage of `ty::TyKind`")] -#[help("try using `Ty` instead")] -pub(crate) struct TykindDiag; - -#[derive(Diagnostic)] -#[diag("usage of qualified `ty::{$ty}`")] -pub(crate) struct TyQualified { - pub ty: String, - #[suggestion( - "try importing it and using it unqualified", - code = "{ty}", - applicability = "maybe-incorrect" - )] - pub suggestion: Span, -} - -#[derive(Diagnostic)] -#[diag("do not use `rustc_type_ir::inherent` unless you're inside of the trait solver")] -#[note( - "the method or struct you're looking for is likely defined somewhere else downstream in the compiler" -)] -pub(crate) struct TypeIrInherentUsage; - -#[derive(Diagnostic)] -#[diag( - "do not use `rustc_type_ir::Interner` or `rustc_type_ir::InferCtxtLike` unless you're inside of the trait solver" -)] -#[note( - "the method or struct you're looking for is likely defined somewhere else downstream in the compiler" -)] -pub(crate) struct TypeIrTraitUsage; - -#[derive(Diagnostic)] -#[diag("do not use `rustc_type_ir` unless you are implementing type system internals")] -#[note("use `rustc_middle::ty` instead")] -pub(crate) struct TypeIrDirectUse; - -#[derive(Diagnostic)] -#[diag("non-glob import of `rustc_type_ir::inherent`")] -pub(crate) struct NonGlobImportTypeIrInherent { - #[suggestion( - "try using a glob import instead", - code = "{snippet}", - applicability = "maybe-incorrect" - )] - pub suggestion: Option, - pub snippet: &'static str, -} - -#[derive(Diagnostic)] -#[diag("implementing `LintPass` by hand")] -#[help("try using `declare_lint_pass!` or `impl_lint_pass!` instead")] -pub(crate) struct LintPassByHand; - -#[derive(Diagnostic)] -#[diag("{$msg}")] -pub(crate) struct BadOptAccessDiag<'a> { - pub msg: &'a str, -} - -#[derive(Diagnostic)] -#[diag( - "dangerous use of `extern crate {$name}` which is not guaranteed to exist exactly once in the sysroot" -)] -#[help( - "try using a cargo dependency or using a re-export of the dependency provided by a rustc_* crate" -)] -pub(crate) struct ImplicitSysrootCrateImportDiag<'a> { - pub name: &'a str, -} - -#[derive(Diagnostic)] -#[diag("use of `AttributeKind` in `find_attr!(...)` invocation")] -#[note("`find_attr!(...)` already imports `AttributeKind::*`")] -#[help("remove `AttributeKind`")] -pub(crate) struct AttributeKindInFindAttr; - -#[derive(Diagnostic)] -#[diag("match is not exhaustive")] -#[help("explicitly list all variants of the enum in a `match`")] -pub(crate) struct RustcMustMatchExhaustivelyNotExhaustive { - #[label("required because of this attribute")] - pub attr_span: Span, - - #[note("{$message}")] - pub pat_span: Span, - pub message: &'static str, -} - -// let_underscore.rs -#[derive(Diagnostic)] -pub(crate) enum NonBindingLet { - #[diag("non-binding let on a synchronization lock")] - SyncLock { - #[label("this lock is not assigned to a binding and is immediately dropped")] - pat: Span, - #[subdiagnostic] - sub: NonBindingLetSub, - }, - #[diag("non-binding let on a type that has a destructor")] - DropType { - #[subdiagnostic] - sub: NonBindingLetSub, - }, -} - -pub(crate) struct NonBindingLetSub { - pub suggestion: Span, - pub drop_fn_start_end: Option<(Span, Span)>, - pub is_assign_desugar: bool, -} - -impl Subdiagnostic for NonBindingLetSub { - fn add_to_diag(self, diag: &mut Diag<'_, G>) { - let can_suggest_binding = self.drop_fn_start_end.is_some() || !self.is_assign_desugar; - - if can_suggest_binding { - let prefix = if self.is_assign_desugar { "let " } else { "" }; - diag.span_suggestion_verbose( - self.suggestion, - msg!( - "consider binding to an unused variable to avoid immediately dropping the value" - ), - format!("{prefix}_unused"), - Applicability::MachineApplicable, - ); - } else { - diag.span_help( - self.suggestion, - msg!( - "consider binding to an unused variable to avoid immediately dropping the value" - ), - ); - } - if let Some(drop_fn_start_end) = self.drop_fn_start_end { - diag.multipart_suggestion( - msg!("consider immediately dropping the value"), - vec![ - (drop_fn_start_end.0, "drop(".to_string()), - (drop_fn_start_end.1, ")".to_string()), - ], - Applicability::MachineApplicable, - ); - } else { - diag.help(msg!( - "consider immediately dropping the value using `drop(..)` after the `let` statement" - )); - } - } -} - -// levels.rs -#[derive(Diagnostic)] -#[diag("{$lint_level}({$lint_source}) incompatible with previous forbid")] -pub(crate) struct OverruledAttributeLint<'a> { - #[label("overruled by previous forbid")] - pub overruled: Span, - pub lint_level: &'a str, - pub lint_source: Symbol, - #[subdiagnostic] - pub sub: OverruledAttributeSub, -} - -#[derive(Diagnostic)] -#[diag("lint name `{$name}` is deprecated and may not have an effect in the future")] -pub(crate) struct DeprecatedLintName<'a> { - pub name: String, - #[suggestion("change it to", code = "{replace}", applicability = "machine-applicable")] - pub suggestion: Span, - pub replace: &'a str, -} - -#[derive(Diagnostic)] -#[diag("lint name `{$name}` is deprecated and may not have an effect in the future")] -#[help("change it to {$replace}")] -pub(crate) struct DeprecatedLintNameFromCommandLine<'a> { - pub name: String, - pub replace: &'a str, - #[subdiagnostic] - pub requested_level: RequestedLevel<'a>, -} - -#[derive(Diagnostic)] -#[diag("lint `{$name}` has been renamed to `{$replace}`")] -pub(crate) struct RenamedLint<'a> { - pub name: &'a str, - pub replace: &'a str, - #[subdiagnostic] - pub suggestion: RenamedLintSuggestion<'a>, -} - -#[derive(Subdiagnostic)] -pub(crate) enum RenamedLintSuggestion<'a> { - #[suggestion("use the new name", code = "{replace}", applicability = "machine-applicable")] - WithSpan { - #[primary_span] - suggestion: Span, - replace: &'a str, - }, - #[help("use the new name `{$replace}`")] - WithoutSpan { replace: &'a str }, -} - -#[derive(Diagnostic)] -#[diag("lint `{$name}` has been renamed to `{$replace}`")] -pub(crate) struct RenamedLintFromCommandLine<'a> { - pub name: &'a str, - pub replace: &'a str, - #[subdiagnostic] - pub suggestion: RenamedLintSuggestion<'a>, - #[subdiagnostic] - pub requested_level: RequestedLevel<'a>, -} - -#[derive(Diagnostic)] -#[diag("lint `{$name}` has been removed: {$reason}")] -pub(crate) struct RemovedLint<'a> { - pub name: &'a str, - pub reason: &'a str, -} - -#[derive(Diagnostic)] -#[diag("lint `{$name}` has been removed: {$reason}")] -pub(crate) struct RemovedLintFromCommandLine<'a> { - pub name: &'a str, - pub reason: &'a str, - #[subdiagnostic] - pub requested_level: RequestedLevel<'a>, -} - -#[derive(Diagnostic)] -#[diag("unknown lint: `{$name}`")] -pub(crate) struct UnknownLint { - pub name: String, - #[subdiagnostic] - pub suggestion: Option, -} - -#[derive(Subdiagnostic)] -pub(crate) enum UnknownLintSuggestion { - #[suggestion( - "{$from_rustc -> - [true] a lint with a similar name exists in `rustc` lints - *[false] did you mean - }", - code = "{replace}", - applicability = "maybe-incorrect" - )] - WithSpan { - #[primary_span] - suggestion: Span, - replace: Symbol, - from_rustc: bool, - }, - #[help( - "{$from_rustc -> - [true] a lint with a similar name exists in `rustc` lints: `{$replace}` - *[false] did you mean: `{$replace}` - }" - )] - WithoutSpan { replace: Symbol, from_rustc: bool }, -} - -#[derive(Diagnostic)] -#[diag("unknown lint: `{$name}`", code = E0602)] -pub(crate) struct UnknownLintFromCommandLine<'a> { - pub name: String, - #[subdiagnostic] - pub suggestion: Option, - #[subdiagnostic] - pub requested_level: RequestedLevel<'a>, -} - -#[derive(Diagnostic)] -#[diag("{$level}({$name}) is ignored unless specified at crate level")] -pub(crate) struct IgnoredUnlessCrateSpecified<'a> { - pub level: &'a str, - pub name: Symbol, -} - -// dangling.rs -#[derive(Diagnostic)] -#[diag("this creates a dangling pointer because temporary `{$ty}` is dropped at end of statement")] -#[help("bind the `{$ty}` to a variable such that it outlives the pointer returned by `{$callee}`")] -#[note("a dangling pointer is safe, but dereferencing one is undefined behavior")] -#[note("returning a pointer to a local variable will always result in a dangling pointer")] -#[note("for more information, see ")] -// FIXME: put #[primary_span] on `ptr_span` once it does not cause conflicts -pub(crate) struct DanglingPointersFromTemporaries<'tcx> { - pub callee: Ident, - pub ty: Ty<'tcx>, - #[label("pointer created here")] - pub ptr_span: Span, - #[label("this `{$ty}` is dropped at end of statement")] - pub temporary_span: Span, -} - -#[derive(Diagnostic)] -#[diag("{$fn_kind} returns a dangling pointer to dropped local variable `{$local_var_name}`")] -#[note("a dangling pointer is safe, but dereferencing one is undefined behavior")] -#[note("for more information, see ")] -pub(crate) struct DanglingPointersFromLocals<'tcx> { - pub ret_ty: Ty<'tcx>, - #[label("return type is `{$ret_ty}`")] - pub ret_ty_span: Span, - pub fn_kind: &'static str, - #[label("local variable `{$local_var_name}` is dropped at the end of the {$fn_kind}")] - pub local_var: Span, - pub local_var_name: Ident, - pub local_var_ty: Ty<'tcx>, - #[label("dangling pointer created here")] - pub created_at: Option, -} - -// multiple_supertrait_upcastable.rs -#[derive(Diagnostic)] -#[diag("`{$ident}` is dyn-compatible and has multiple supertraits")] -pub(crate) struct MultipleSupertraitUpcastable { - pub ident: Ident, -} - -// non_ascii_idents.rs -#[derive(Diagnostic)] -#[diag("identifier contains non-ASCII characters")] -pub(crate) struct IdentifierNonAsciiChar; - -#[derive(Diagnostic)] -#[diag( - "identifier contains {$codepoints_len -> - [one] { $identifier_type -> - [Exclusion] a character from an archaic script - [Technical] a character that is for non-linguistic, specialized usage - [Limited_Use] a character from a script in limited use - [Not_NFKC] a non normalized (NFKC) character - *[other] an uncommon character - } - *[other] { $identifier_type -> - [Exclusion] {$codepoints_len} characters from archaic scripts - [Technical] {$codepoints_len} characters that are for non-linguistic, specialized usage - [Limited_Use] {$codepoints_len} characters from scripts in limited use - [Not_NFKC] {$codepoints_len} non normalized (NFKC) characters - *[other] uncommon characters - } - }: {$codepoints}" -)] -#[note( - r#"{$codepoints_len -> - [one] this character is - *[other] these characters are - } included in the{$identifier_type -> - [Restricted] {""} - *[other] {" "}{$identifier_type} - } Unicode general security profile"# -)] -pub(crate) struct IdentifierUncommonCodepoints { - pub codepoints: Vec, - pub codepoints_len: usize, - pub identifier_type: &'static str, -} - -#[derive(Diagnostic)] -#[diag("found both `{$existing_sym}` and `{$sym}` as identifiers, which look alike")] -pub(crate) struct ConfusableIdentifierPair { - pub existing_sym: Symbol, - pub sym: Symbol, - #[label("other identifier used here")] - pub label: Span, - #[label("this identifier can be confused with `{$existing_sym}`")] - pub main_label: Span, -} - -#[derive(Diagnostic)] -#[diag( - "the usage of Script Group `{$set}` in this crate consists solely of mixed script confusables" -)] -#[note("the usage includes {$includes}")] -#[note("please recheck to make sure their usages are indeed what you want")] -pub(crate) struct MixedScriptConfusables { - pub set: String, - pub includes: String, -} - -// non_fmt_panic.rs -pub(crate) struct NonFmtPanicUnused { - pub count: usize, - pub suggestion: Option, -} - -// Used because of two suggestions based on one Option -impl<'a> Diagnostic<'a, ()> for NonFmtPanicUnused { - fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> { - let mut diag = Diag::new(dcx, level, msg!( - "panic message contains {$count -> - [one] an unused - *[other] unused - } formatting {$count -> - [one] placeholder - *[other] placeholders - }" - )) - .with_arg("count", self.count) - .with_note(msg!("this message is not used as a format string when given without arguments, but will be in Rust 2021")); - if let Some(span) = self.suggestion { - diag.span_suggestion( - span.shrink_to_hi(), - msg!( - "add the missing {$count -> - [one] argument - *[other] arguments - }" - ), - ", ...", - Applicability::HasPlaceholders, - ); - diag.span_suggestion( - span.shrink_to_lo(), - msg!(r#"or add a "{"{"}{"}"}" format string to use the message literally"#), - "\"{}\", ", - Applicability::MachineApplicable, - ); - } - diag - } -} - -#[derive(Diagnostic)] -#[diag( - "panic message contains {$count -> - [one] a brace - *[other] braces - }" -)] -#[note("this message is not used as a format string, but will be in Rust 2021")] -pub(crate) struct NonFmtPanicBraces { - pub count: usize, - #[suggestion( - "add a \"{\"{\"}{\"}\"}\" format string to use the message literally", - code = "\"{{}}\", ", - applicability = "machine-applicable" - )] - pub suggestion: Option, -} - -// nonstandard_style.rs -#[derive(Diagnostic)] -#[diag("{$sort} `{$name}` should have an upper camel case name")] -pub(crate) struct NonCamelCaseType<'a> { - pub sort: &'a str, - pub name: &'a str, - #[subdiagnostic] - pub sub: NonCamelCaseTypeSub, -} - -#[derive(Subdiagnostic)] -pub(crate) enum NonCamelCaseTypeSub { - #[label("should have an UpperCamelCase name")] - Label { - #[primary_span] - span: Span, - }, - #[suggestion( - "convert the identifier to upper camel case", - code = "{replace}", - applicability = "maybe-incorrect" - )] - Suggestion { - #[primary_span] - span: Span, - replace: String, - }, -} - -#[derive(Diagnostic)] -#[diag("{$sort} `{$name}` should have a snake case name")] -pub(crate) struct NonSnakeCaseDiag<'a> { - pub sort: &'a str, - pub name: &'a str, - #[subdiagnostic] - pub sub: NonSnakeCaseDiagSub, -} - -pub(crate) enum NonSnakeCaseDiagSub { - Label { span: Span }, - Help { sc: String }, - RenameOrConvertSuggestion { span: Span, suggestion: Ident }, - ConvertSuggestion { span: Span, suggestion: String }, - SuggestionAndNote { sc: String, span: Span }, -} - -impl Subdiagnostic for NonSnakeCaseDiagSub { - fn add_to_diag(self, diag: &mut Diag<'_, G>) { - match self { - NonSnakeCaseDiagSub::Label { span } => { - diag.span_label(span, msg!("should have a snake_case name")); - } - NonSnakeCaseDiagSub::Help { sc } => { - diag.arg("sc", sc); - diag.help(msg!("convert the identifier to snake case: `{$sc}`")); - } - NonSnakeCaseDiagSub::ConvertSuggestion { span, suggestion } => { - diag.span_suggestion( - span, - msg!("convert the identifier to snake case"), - suggestion, - Applicability::MaybeIncorrect, - ); - } - NonSnakeCaseDiagSub::RenameOrConvertSuggestion { span, suggestion } => { - diag.span_suggestion( - span, - msg!("rename the identifier or convert it to a snake case raw identifier"), - suggestion, - Applicability::MaybeIncorrect, - ); - } - NonSnakeCaseDiagSub::SuggestionAndNote { sc, span } => { - diag.arg("sc", sc); - diag.note(msg!("`{$sc}` cannot be used as a raw identifier")); - diag.span_suggestion( - span, - msg!("rename the identifier"), - "", - Applicability::MaybeIncorrect, - ); - } - } - } -} - -#[derive(Diagnostic)] -#[diag("{$sort} `{$name}` should have an upper case name")] -pub(crate) struct NonUpperCaseGlobal<'a> { - pub sort: &'a str, - pub name: &'a str, - #[subdiagnostic] - pub sub: NonUpperCaseGlobalSub, - #[subdiagnostic] - pub usages: Vec, -} - -#[derive(Subdiagnostic)] -pub(crate) enum NonUpperCaseGlobalSub { - #[label("should have an UPPER_CASE name")] - Label { - #[primary_span] - span: Span, - }, - #[suggestion("convert the identifier to upper case", code = "{replace}")] - Suggestion { - #[primary_span] - span: Span, - #[applicability] - applicability: Applicability, - replace: String, - }, -} - -#[derive(Subdiagnostic)] -#[suggestion( - "convert the identifier to upper case", - code = "{replace}", - applicability = "machine-applicable", - style = "tool-only" -)] -pub(crate) struct NonUpperCaseGlobalSubTool { - #[primary_span] - pub(crate) span: Span, - pub(crate) replace: String, -} - -// noop_method_call.rs -#[derive(Diagnostic)] -#[diag("call to `.{$method}()` on a reference in this situation does nothing")] -#[note( - "the type `{$orig_ty}` does not implement `{$trait_}`, so calling `{$method}` on `&{$orig_ty}` copies the reference, which does not do anything and can be removed" -)] -pub(crate) struct NoopMethodCallDiag<'a> { - pub method: Ident, - pub orig_ty: Ty<'a>, - pub trait_: Symbol, - #[suggestion("remove this redundant call", code = "", applicability = "machine-applicable")] - pub label: Span, - #[suggestion( - "if you meant to clone `{$orig_ty}`, implement `Clone` for it", - code = "#[derive(Clone)]\n", - applicability = "maybe-incorrect" - )] - pub suggest_derive: Option, -} - -#[derive(Diagnostic)] -#[diag( - "using `.deref()` on a double reference, which returns `{$ty}` instead of dereferencing the inner type" -)] -pub(crate) struct SuspiciousDoubleRefDerefDiag<'a> { - pub ty: Ty<'a>, -} - -#[derive(Diagnostic)] -#[diag( - "using `.clone()` on a double reference, which returns `{$ty}` instead of cloning the inner type" -)] -pub(crate) struct SuspiciousDoubleRefCloneDiag<'a> { - pub ty: Ty<'a>, -} - -// non_local_defs.rs -pub(crate) enum NonLocalDefinitionsDiag { - Impl { - depth: u32, - body_kind_descr: &'static str, - body_name: String, - cargo_update: Option, - const_anon: Option>, - doctest: bool, - macro_to_change: Option<(String, &'static str)>, - }, - MacroRules { - depth: u32, - body_kind_descr: &'static str, - body_name: String, - doctest: bool, - cargo_update: Option, - }, -} - -impl<'a> Diagnostic<'a, ()> for NonLocalDefinitionsDiag { - fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> { - let mut diag = Diag::new(dcx, level, ""); - match self { - NonLocalDefinitionsDiag::Impl { - depth, - body_kind_descr, - body_name, - cargo_update, - const_anon, - doctest, - macro_to_change, - } => { - diag.primary_message(msg!("non-local `impl` definition, `impl` blocks should be written at the same level as their item")); - diag.arg("depth", depth); - diag.arg("body_kind_descr", body_kind_descr); - diag.arg("body_name", body_name); - - if let Some((macro_to_change, macro_kind)) = macro_to_change { - diag.arg("macro_to_change", macro_to_change); - diag.arg("macro_kind", macro_kind); - diag.note(msg!("the {$macro_kind} `{$macro_to_change}` defines the non-local `impl`, and may need to be changed")); - } - if let Some(cargo_update) = cargo_update { - diag.subdiagnostic(cargo_update); - } - - diag.note(msg!("an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl`")); - - if doctest { - diag.help(msg!("make this doc-test a standalone test with its own `fn main() {\"{\"} ... {\"}\"}`")); - } - - if let Some(const_anon) = const_anon { - diag.note(msg!("items in an anonymous const item (`const _: () = {\"{\"} ... {\"}\"}`) are treated as in the same scope as the anonymous const's declaration for the purpose of this lint")); - if let Some(const_anon) = const_anon { - diag.span_suggestion( - const_anon, - msg!("use a const-anon item to suppress this lint"), - "_", - Applicability::MachineApplicable, - ); - } - } - } - NonLocalDefinitionsDiag::MacroRules { - depth, - body_kind_descr, - body_name, - doctest, - cargo_update, - } => { - diag.primary_message(msg!("non-local `macro_rules!` definition, `#[macro_export]` macro should be written at top level module")); - diag.arg("depth", depth); - diag.arg("body_kind_descr", body_kind_descr); - diag.arg("body_name", body_name); - - if doctest { - diag.help(msg!(r#"remove the `#[macro_export]` or make this doc-test a standalone test with its own `fn main() {"{"} ... {"}"}`"#)); - } else { - diag.help(msg!( - "remove the `#[macro_export]` or move this `macro_rules!` outside the of the current {$body_kind_descr} {$depth -> - [one] `{$body_name}` - *[other] `{$body_name}` and up {$depth} bodies - }" - )); - } - - diag.note(msg!("a `macro_rules!` definition is non-local if it is nested inside an item and has a `#[macro_export]` attribute")); - - if let Some(cargo_update) = cargo_update { - diag.subdiagnostic(cargo_update); - } - } - } - diag - } -} - -#[derive(Subdiagnostic)] -#[note( - "the {$macro_kind} `{$macro_name}` may come from an old version of the `{$crate_name}` crate, try updating your dependency with `cargo update -p {$crate_name}`" -)] -pub(crate) struct NonLocalDefinitionsCargoUpdateNote { - pub macro_kind: &'static str, - pub macro_name: Symbol, - pub crate_name: Symbol, -} - -// precedence.rs -#[derive(Diagnostic)] -#[diag("`-` has lower precedence than method calls, which might be unexpected")] -#[note("e.g. `-4.abs()` equals `-4`; while `(-4).abs()` equals `4`")] -pub(crate) struct AmbiguousNegativeLiteralsDiag { - #[subdiagnostic] - pub negative_literal: AmbiguousNegativeLiteralsNegativeLiteralSuggestion, - #[subdiagnostic] - pub current_behavior: AmbiguousNegativeLiteralsCurrentBehaviorSuggestion, -} - -#[derive(Subdiagnostic)] -#[multipart_suggestion( - "add parentheses around the `-` and the literal to call the method on a negative literal", - applicability = "maybe-incorrect" -)] -pub(crate) struct AmbiguousNegativeLiteralsNegativeLiteralSuggestion { - #[suggestion_part(code = "(")] - pub start_span: Span, - #[suggestion_part(code = ")")] - pub end_span: Span, -} - -#[derive(Subdiagnostic)] -#[multipart_suggestion( - "add parentheses around the literal and the method call to keep the current behavior", - applicability = "maybe-incorrect" -)] -pub(crate) struct AmbiguousNegativeLiteralsCurrentBehaviorSuggestion { - #[suggestion_part(code = "(")] - pub start_span: Span, - #[suggestion_part(code = ")")] - pub end_span: Span, -} - -// disallowed_pass_by_ref.rs -#[derive(Diagnostic)] -#[diag("passing `{$ty}` by reference")] -pub(crate) struct DisallowedPassByRefDiag { - pub ty: String, - #[suggestion("try passing by value", code = "{ty}", applicability = "maybe-incorrect")] - pub suggestion: Span, -} - -// redundant_semicolon.rs -#[derive(Diagnostic)] -#[diag( - "unnecessary trailing {$multiple -> - [true] semicolons - *[false] semicolon - }" -)] -pub(crate) struct RedundantSemicolonsDiag { - pub multiple: bool, - #[subdiagnostic] - pub suggestion: Option, -} - -#[derive(Subdiagnostic)] -#[suggestion( - "remove {$multiple_semicolons -> - [true] these semicolons - *[false] this semicolon - }", - code = "", - applicability = "maybe-incorrect" -)] -pub(crate) struct RedundantSemicolonsSuggestion { - pub multiple_semicolons: bool, - #[primary_span] - pub span: Span, -} - -// traits.rs -pub(crate) struct DropTraitConstraintsDiag<'a> { - pub clause: Clause<'a>, - pub tcx: TyCtxt<'a>, - pub def_id: DefId, -} - -// Needed for def_path_str -impl<'a> Diagnostic<'a, ()> for DropTraitConstraintsDiag<'_> { - fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> { - Diag::new(dcx, level, msg!("bounds on `{$clause}` are most likely incorrect, consider instead using `{$needs_drop}` to detect whether a type can be trivially dropped")) - .with_arg("clause", self.clause) - .with_arg("needs_drop", self.tcx.def_path_str(self.def_id)) - } -} - -pub(crate) struct DropGlue<'a> { - pub tcx: TyCtxt<'a>, - pub def_id: DefId, -} - -// Needed for def_path_str -impl<'a> Diagnostic<'a, ()> for DropGlue<'_> { - fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> { - Diag::new(dcx, level, msg!("types that do not implement `Drop` can still have drop glue, consider instead using `{$needs_drop}` to detect whether a type is trivially dropped")) - .with_arg("needs_drop", self.tcx.def_path_str(self.def_id)) - } -} - -// transmute.rs -#[derive(Diagnostic)] -#[diag("transmuting an integer to a pointer creates a pointer without provenance")] -#[note("this is dangerous because dereferencing the resulting pointer is undefined behavior")] -#[note( - "exposed provenance semantics can be used to create a pointer based on some previously exposed provenance" -)] -#[help( - "if you truly mean to create a pointer without provenance, use `std::ptr::without_provenance_mut`" -)] -#[help( - "for more information about transmute, see " -)] -#[help( - "for more information about exposed provenance, see " -)] -pub(crate) struct IntegerToPtrTransmutes<'tcx> { - #[subdiagnostic] - pub suggestion: Option>, -} - -#[derive(Subdiagnostic)] -pub(crate) enum IntegerToPtrTransmutesSuggestion<'tcx> { - #[multipart_suggestion( - "use `std::ptr::with_exposed_provenance{$suffix}` instead to use a previously exposed provenance", - applicability = "machine-applicable", - style = "verbose" - )] - ToPtr { - dst: Ty<'tcx>, - suffix: &'static str, - #[suggestion_part(code = "std::ptr::with_exposed_provenance{suffix}::<{dst}>(")] - start_call: Span, - }, - #[multipart_suggestion( - "use `std::ptr::with_exposed_provenance{$suffix}` instead to use a previously exposed provenance", - applicability = "machine-applicable", - style = "verbose" - )] - ToRef { - dst: Ty<'tcx>, - suffix: &'static str, - ref_mutbl: &'static str, - #[suggestion_part( - code = "&{ref_mutbl}*std::ptr::with_exposed_provenance{suffix}::<{dst}>(" - )] - start_call: Span, - }, -} - -// types.rs -#[derive(Diagnostic)] -#[diag("range endpoint is out of range for `{$ty}`")] -pub(crate) struct RangeEndpointOutOfRange<'a> { - pub ty: &'a str, - #[subdiagnostic] - pub sub: UseInclusiveRange<'a>, -} - -#[derive(Subdiagnostic)] -pub(crate) enum UseInclusiveRange<'a> { - #[suggestion( - "use an inclusive range instead", - code = "{start}..={literal}{suffix}", - applicability = "machine-applicable" - )] - WithoutParen { - #[primary_span] - sugg: Span, - start: String, - literal: u128, - suffix: &'a str, - }, - #[multipart_suggestion("use an inclusive range instead", applicability = "machine-applicable")] - WithParen { - #[suggestion_part(code = "=")] - eq_sugg: Span, - #[suggestion_part(code = "{literal}{suffix}")] - lit_sugg: Span, - literal: u128, - suffix: &'a str, - }, -} - -#[derive(Diagnostic)] -#[diag("literal out of range for `{$ty}`")] -pub(crate) struct OverflowingBinHex<'a> { - pub ty: &'a str, - #[subdiagnostic] - pub sign: OverflowingBinHexSign<'a>, - #[subdiagnostic] - pub sub: Option>, - #[subdiagnostic] - pub sign_bit_sub: Option>, -} - -#[derive(Subdiagnostic)] -pub(crate) enum OverflowingBinHexSign<'a> { - #[note( - "the literal `{$lit}` (decimal `{$dec}`) does not fit into the type `{$ty}` and will become `{$actually}{$ty}`" - )] - Positive { lit: String, ty: &'a str, actually: String, dec: u128 }, - #[note("the literal `{$lit}` (decimal `{$dec}`) does not fit into the type `{$ty}`")] - #[note("and the value `-{$lit}` will become `{$actually}{$ty}`")] - Negative { lit: String, ty: &'a str, actually: String, dec: u128 }, -} - -#[derive(Subdiagnostic)] -pub(crate) enum OverflowingBinHexSub<'a> { - #[suggestion( - "consider using the type `{$suggestion_ty}` instead", - code = "{sans_suffix}{suggestion_ty}", - applicability = "machine-applicable" - )] - Suggestion { - #[primary_span] - span: Span, - suggestion_ty: &'a str, - sans_suffix: &'a str, - }, - #[help("consider using the type `{$suggestion_ty}` instead")] - Help { suggestion_ty: &'a str }, -} - -#[derive(Subdiagnostic)] -pub(crate) enum OverflowingBinHexSignBitSub<'a> { - #[suggestion( - "to use as a negative number (decimal `{$negative_val}`), consider using the type `{$uint_ty}` for the literal and cast it to `{$int_ty}`", - code = "{lit_no_suffix}{uint_ty}.cast_signed()", - applicability = "maybe-incorrect" - )] - CastSigned { - #[primary_span] - span: Span, - lit_no_suffix: &'a str, - negative_val: String, - uint_ty: &'a str, - int_ty: &'a str, - }, - #[suggestion( - "to use as a negative number (decimal `{$negative_val}`), consider using the type `{$uint_ty}` for the literal and cast it to `{$int_ty}`", - code = "{lit_no_suffix}{uint_ty} as {int_ty}", - applicability = "maybe-incorrect" - )] - AsCast { - #[primary_span] - span: Span, - lit_no_suffix: &'a str, - negative_val: String, - uint_ty: &'a str, - int_ty: &'a str, - }, -} - -#[derive(Diagnostic)] -#[diag("literal out of range for `{$ty}`")] -#[note("the literal `{$lit}` does not fit into the type `{$ty}` whose range is `{$min}..={$max}`")] -pub(crate) struct OverflowingInt<'a> { - pub ty: &'a str, - pub lit: String, - pub min: i128, - pub max: u128, - #[subdiagnostic] - pub help: Option>, -} - -#[derive(Subdiagnostic)] -#[help("consider using the type `{$suggestion_ty}` instead")] -pub(crate) struct OverflowingIntHelp<'a> { - pub suggestion_ty: &'a str, -} - -#[derive(Diagnostic)] -#[diag("only `u8` can be cast into `char`")] -pub(crate) struct OnlyCastu8ToChar { - #[suggestion( - "use a `char` literal instead", - code = "'\\u{{{literal:X}}}'", - applicability = "machine-applicable" - )] - pub span: Span, - pub literal: u128, -} - -#[derive(Diagnostic)] -#[diag("literal out of range for `{$ty}`")] -#[note("the literal `{$lit}` does not fit into the type `{$ty}` whose range is `{$min}..={$max}`")] -pub(crate) struct OverflowingUInt<'a> { - pub ty: &'a str, - pub lit: String, - pub min: u128, - pub max: u128, -} - -#[derive(Diagnostic)] -#[diag("literal out of range for `{$ty}`")] -#[note( - "the literal `{$lit}` does not fit into the type `{$ty}` and will be converted to `{$ty}::INFINITY`" -)] -pub(crate) struct OverflowingLiteral<'a> { - pub ty: &'a str, - pub lit: String, -} - -#[derive(Diagnostic)] -#[diag("surrogate values are not valid for `char`")] -#[note("`0xD800..=0xDFFF` are reserved for Unicode surrogates and are not valid `char` values")] -pub(crate) struct SurrogateCharCast { - pub literal: u128, -} - -#[derive(Diagnostic)] -#[diag("value exceeds maximum `char` value")] -#[note("maximum valid `char` value is `0x10FFFF`")] -pub(crate) struct TooLargeCharCast { - pub literal: u128, -} - -#[derive(Diagnostic)] -#[diag( - "repr(C) does not follow the power alignment rule. This may affect platform C ABI compatibility for this type" -)] -pub(crate) struct UsesPowerAlignment; - -#[derive(Diagnostic)] -#[diag("comparison is useless due to type limits")] -pub(crate) struct UnusedComparisons; - -#[derive(Diagnostic)] -pub(crate) enum InvalidNanComparisons { - #[diag("incorrect NaN comparison, NaN cannot be directly compared to itself")] - EqNe { - #[subdiagnostic] - suggestion: InvalidNanComparisonsSuggestion, - }, - #[diag("incorrect NaN comparison, NaN is not orderable")] - LtLeGtGe, -} - -#[derive(Subdiagnostic)] -pub(crate) enum InvalidNanComparisonsSuggestion { - #[multipart_suggestion( - "use `f32::is_nan()` or `f64::is_nan()` instead", - style = "verbose", - applicability = "machine-applicable" - )] - Spanful { - #[suggestion_part(code = "!")] - neg: Option, - #[suggestion_part(code = ".is_nan()")] - float: Span, - #[suggestion_part(code = "")] - nan_plus_binop: Span, - }, - #[help("use `f32::is_nan()` or `f64::is_nan()` instead")] - Spanless, -} - -#[derive(Diagnostic)] -pub(crate) enum AmbiguousWidePointerComparisons<'a> { - #[diag( - "ambiguous wide pointer comparison, the comparison includes metadata which may not be expected" - )] - SpanfulEq { - #[subdiagnostic] - addr_suggestion: AmbiguousWidePointerComparisonsAddrSuggestion<'a>, - #[subdiagnostic] - addr_metadata_suggestion: Option>, - }, - #[diag( - "ambiguous wide pointer comparison, the comparison includes metadata which may not be expected" - )] - SpanfulCmp { - #[subdiagnostic] - cast_suggestion: AmbiguousWidePointerComparisonsCastSuggestion<'a>, - #[subdiagnostic] - expect_suggestion: AmbiguousWidePointerComparisonsExpectSuggestion<'a>, - }, - #[diag( - "ambiguous wide pointer comparison, the comparison includes metadata which may not be expected" - )] - #[help("use explicit `std::ptr::eq` method to compare metadata and addresses")] - #[help("use `std::ptr::addr_eq` or untyped pointers to only compare their addresses")] - Spanless, -} - -#[derive(Subdiagnostic)] -#[multipart_suggestion( - "use explicit `std::ptr::eq` method to compare metadata and addresses", - style = "verbose", - // FIXME(#53934): make machine-applicable again - applicability = "maybe-incorrect" -)] -pub(crate) struct AmbiguousWidePointerComparisonsAddrMetadataSuggestion<'a> { - pub ne: &'a str, - pub deref_left: &'a str, - pub deref_right: &'a str, - pub l_modifiers: &'a str, - pub r_modifiers: &'a str, - #[suggestion_part(code = "{ne}std::ptr::eq({deref_left}")] - pub left: Span, - #[suggestion_part(code = "{l_modifiers}, {deref_right}")] - pub middle: Span, - #[suggestion_part(code = "{r_modifiers})")] - pub right: Span, -} - -#[derive(Subdiagnostic)] -#[multipart_suggestion( - "use `std::ptr::addr_eq` or untyped pointers to only compare their addresses", - style = "verbose", - // FIXME(#53934): make machine-applicable again - applicability = "maybe-incorrect" -)] -pub(crate) struct AmbiguousWidePointerComparisonsAddrSuggestion<'a> { - pub(crate) ne: &'a str, - pub(crate) deref_left: &'a str, - pub(crate) deref_right: &'a str, - pub(crate) l_modifiers: &'a str, - pub(crate) r_modifiers: &'a str, - #[suggestion_part(code = "{ne}std::ptr::addr_eq({deref_left}")] - pub(crate) left: Span, - #[suggestion_part(code = "{l_modifiers}, {deref_right}")] - pub(crate) middle: Span, - #[suggestion_part(code = "{r_modifiers})")] - pub(crate) right: Span, -} - -#[derive(Subdiagnostic)] -#[multipart_suggestion( - "use untyped pointers to only compare their addresses", - style = "verbose", - // FIXME(#53934): make machine-applicable again - applicability = "maybe-incorrect" -)] -pub(crate) struct AmbiguousWidePointerComparisonsCastSuggestion<'a> { - pub(crate) deref_left: &'a str, - pub(crate) deref_right: &'a str, - pub(crate) paren_left: &'a str, - pub(crate) paren_right: &'a str, - pub(crate) l_modifiers: &'a str, - pub(crate) r_modifiers: &'a str, - #[suggestion_part(code = "({deref_left}")] - pub(crate) left_before: Option, - #[suggestion_part(code = "{l_modifiers}{paren_left}.cast::<()>()")] - pub(crate) left_after: Span, - #[suggestion_part(code = "({deref_right}")] - pub(crate) right_before: Option, - #[suggestion_part(code = "{r_modifiers}{paren_right}.cast::<()>()")] - pub(crate) right_after: Span, -} - -#[derive(Subdiagnostic)] -#[multipart_suggestion( - "or expect the lint to compare the pointers metadata and addresses", - style = "verbose", - // FIXME(#53934): make machine-applicable again - applicability = "maybe-incorrect" -)] -pub(crate) struct AmbiguousWidePointerComparisonsExpectSuggestion<'a> { - pub(crate) paren_left: &'a str, - pub(crate) paren_right: &'a str, - // FIXME(#127436): Adjust once resolved - #[suggestion_part( - code = r#"{{ #[expect(ambiguous_wide_pointer_comparisons, reason = "...")] {paren_left}"# - )] - pub(crate) before: Span, - #[suggestion_part(code = "{paren_right} }}")] - pub(crate) after: Span, -} - -#[derive(Diagnostic)] -pub(crate) enum UnpredictableFunctionPointerComparisons<'a, 'tcx> { - #[diag( - "function pointer comparisons do not produce meaningful results since their addresses are not guaranteed to be unique" - )] - #[note("the address of the same function can vary between different codegen units")] - #[note( - "furthermore, different functions could have the same address after being merged together" - )] - #[note( - "for more information visit " - )] - Suggestion { - #[subdiagnostic] - sugg: UnpredictableFunctionPointerComparisonsSuggestion<'a, 'tcx>, - }, - #[diag( - "function pointer comparisons do not produce meaningful results since their addresses are not guaranteed to be unique" - )] - #[note("the address of the same function can vary between different codegen units")] - #[note( - "furthermore, different functions could have the same address after being merged together" - )] - #[note( - "for more information visit " - )] - Warn, -} - -#[derive(Subdiagnostic)] -pub(crate) enum UnpredictableFunctionPointerComparisonsSuggestion<'a, 'tcx> { - #[multipart_suggestion( - "refactor your code, or use `std::ptr::fn_addr_eq` to suppress the lint", - style = "verbose", - applicability = "maybe-incorrect" - )] - FnAddrEq { - ne: &'a str, - deref_left: &'a str, - deref_right: &'a str, - #[suggestion_part(code = "{ne}std::ptr::fn_addr_eq({deref_left}")] - left: Span, - #[suggestion_part(code = ", {deref_right}")] - middle: Span, - #[suggestion_part(code = ")")] - right: Span, - }, - #[multipart_suggestion( - "refactor your code, or use `std::ptr::fn_addr_eq` to suppress the lint", - style = "verbose", - applicability = "maybe-incorrect" - )] - FnAddrEqWithCast { - ne: &'a str, - deref_left: &'a str, - deref_right: &'a str, - fn_sig: rustc_middle::ty::PolyFnSig<'tcx>, - #[suggestion_part(code = "{ne}std::ptr::fn_addr_eq({deref_left}")] - left: Span, - #[suggestion_part(code = ", {deref_right}")] - middle: Span, - #[suggestion_part(code = " as {fn_sig})")] - right: Span, - }, -} - -pub(crate) struct ImproperCTypes<'a> { - pub ty: Ty<'a>, - pub desc: &'a str, - pub label: Span, - pub help: Option, - pub note: DiagMessage, - pub span_note: Option, -} - -// Used because of the complexity of Option, DiagMessage, and Option -impl<'a> Diagnostic<'a, ()> for ImproperCTypes<'_> { - fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> { - let mut diag = Diag::new( - dcx, - level, - msg!("`extern` {$desc} uses type `{$ty}`, which is not FFI-safe"), - ) - .with_arg("ty", self.ty) - .with_arg("desc", self.desc) - .with_span_label(self.label, msg!("not FFI-safe")); - if let Some(help) = self.help { - diag.help(help); - } - diag.note(self.note); - if let Some(note) = self.span_note { - diag.span_note(note, msg!("the type is defined here")); - } - diag - } -} - -#[derive(Diagnostic)] -#[diag("passing type `{$ty}` to a function with \"gpu-kernel\" ABI may have unexpected behavior")] -#[help("use primitive types and raw pointers to get reliable behavior")] -pub(crate) struct ImproperGpuKernelArg<'a> { - pub ty: Ty<'a>, -} - -#[derive(Diagnostic)] -#[diag("function with the \"gpu-kernel\" ABI has a mangled name")] -#[help("use `unsafe(no_mangle)` or `unsafe(export_name = \"\")`")] -#[note("mangled names make it hard to find the kernel, this is usually not intended")] -pub(crate) struct MissingGpuKernelExportName; - -#[derive(Diagnostic)] -#[diag("enum variant is more than three times larger ({$largest} bytes) than the next largest")] -pub(crate) struct VariantSizeDifferencesDiag { - pub largest: u64, -} - -#[derive(Diagnostic)] -#[diag("atomic loads cannot have `Release` or `AcqRel` ordering")] -#[help("consider using ordering modes `Acquire`, `SeqCst` or `Relaxed`")] -pub(crate) struct AtomicOrderingLoad; - -#[derive(Diagnostic)] -#[diag("atomic stores cannot have `Acquire` or `AcqRel` ordering")] -#[help("consider using ordering modes `Release`, `SeqCst` or `Relaxed`")] -pub(crate) struct AtomicOrderingStore; - -#[derive(Diagnostic)] -#[diag("memory fences cannot have `Relaxed` ordering")] -#[help("consider using ordering modes `Acquire`, `Release`, `AcqRel` or `SeqCst`")] -pub(crate) struct AtomicOrderingFence; - -#[derive(Diagnostic)] -#[diag( - "`{$method}`'s failure ordering may not be `Release` or `AcqRel`, since a failed `{$method}` does not result in a write" -)] -#[help("consider using `Acquire` or `Relaxed` failure ordering instead")] -pub(crate) struct InvalidAtomicOrderingDiag { - pub method: Symbol, - #[label("invalid failure ordering")] - pub fail_order_arg_span: Span, -} - -// unused.rs -#[derive(Diagnostic)] -#[diag("unused {$op} that must be used")] -pub(crate) struct UnusedOp<'a> { - pub op: &'a str, - #[label("the {$op} produces a value")] - pub label: Span, - #[subdiagnostic] - pub suggestion: UnusedOpSuggestion, -} - -#[derive(Subdiagnostic)] -pub(crate) enum UnusedOpSuggestion { - #[suggestion( - "use `let _ = ...` to ignore the resulting value", - style = "verbose", - code = "let _ = ", - applicability = "maybe-incorrect" - )] - NormalExpr { - #[primary_span] - span: Span, - }, - #[multipart_suggestion( - "use `let _ = ...` to ignore the resulting value", - style = "verbose", - applicability = "maybe-incorrect" - )] - BlockTailExpr { - #[suggestion_part(code = "let _ = ")] - before_span: Span, - #[suggestion_part(code = ";")] - after_span: Span, - }, -} - -#[derive(Diagnostic)] -#[diag("unused result of type `{$ty}`")] -pub(crate) struct UnusedResult<'a> { - pub ty: Ty<'a>, -} - -// FIXME(davidtwco): this isn't properly translatable because of the -// pre/post strings -#[derive(Diagnostic)] -#[diag( - "unused {$pre}{$count -> - [one] closure - *[other] closures - }{$post} that must be used" -)] -#[note("closures are lazy and do nothing unless called")] -pub(crate) struct UnusedClosure<'a> { - pub count: usize, - pub pre: &'a str, - pub post: &'a str, -} - -// FIXME(davidtwco): this isn't properly translatable because of the -// pre/post strings -#[derive(Diagnostic)] -#[diag( - "unused {$pre}{$count -> - [one] coroutine - *[other] coroutine - }{$post} that must be used" -)] -#[note("coroutines are lazy and do nothing unless resumed")] -pub(crate) struct UnusedCoroutine<'a> { - pub count: usize, - pub pre: &'a str, - pub post: &'a str, -} - -// FIXME(davidtwco): this isn't properly translatable because of the pre/post -// strings -pub(crate) struct UnusedDef<'a, 'b> { - pub pre: &'a str, - pub post: &'a str, - pub cx: &'a LateContext<'b>, - pub def_id: DefId, - pub note: Option, - pub suggestion: Option, -} - -#[derive(Subdiagnostic)] -pub(crate) enum UnusedDefSuggestion { - #[suggestion( - "use `let _ = ...` to ignore the resulting value", - style = "verbose", - code = "let _ = ", - applicability = "maybe-incorrect" - )] - NormalExpr { - #[primary_span] - span: Span, - }, - #[multipart_suggestion( - "use `let _ = ...` to ignore the resulting value", - style = "verbose", - applicability = "maybe-incorrect" - )] - BlockTailExpr { - #[suggestion_part(code = "let _ = ")] - before_span: Span, - #[suggestion_part(code = ";")] - after_span: Span, - }, -} - -// Needed because of def_path_str -impl<'a> Diagnostic<'a, ()> for UnusedDef<'_, '_> { - fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> { - let mut diag = - Diag::new(dcx, level, msg!("unused {$pre}`{$def}`{$post} that must be used")) - .with_arg("pre", self.pre) - .with_arg("post", self.post) - .with_arg("def", self.cx.tcx.def_path_str(self.def_id)); - // check for #[must_use = "..."] - if let Some(note) = self.note { - diag.note(note.to_string()); - } - if let Some(sugg) = self.suggestion { - diag.subdiagnostic(sugg); - } - diag - } -} - -#[derive(Diagnostic)] -#[diag("path statement drops value")] -pub(crate) struct PathStatementDrop { - #[subdiagnostic] - pub sub: PathStatementDropSub, -} - -#[derive(Subdiagnostic)] -pub(crate) enum PathStatementDropSub { - #[suggestion( - "use `drop` to clarify the intent", - code = "drop({snippet});", - applicability = "machine-applicable" - )] - Suggestion { - #[primary_span] - span: Span, - snippet: String, - }, - #[help("use `drop` to clarify the intent")] - Help { - #[primary_span] - span: Span, - }, -} - -#[derive(Diagnostic)] -#[diag("path statement with no effect")] -pub(crate) struct PathStatementNoEffect; - -#[derive(Diagnostic)] -#[diag("unnecessary {$delim} around {$item}")] -pub(crate) struct UnusedDelim<'a> { - pub delim: &'static str, - pub item: &'a str, - #[subdiagnostic] - pub suggestion: Option, -} - -#[derive(Subdiagnostic)] -#[multipart_suggestion("remove these {$delim}", applicability = "machine-applicable")] -pub(crate) struct UnusedDelimSuggestion { - #[suggestion_part(code = "{start_replace}")] - pub start_span: Span, - pub start_replace: &'static str, - #[suggestion_part(code = "{end_replace}")] - pub end_span: Span, - pub end_replace: &'static str, - pub delim: &'static str, -} - -#[derive(Diagnostic)] -#[diag("braces around {$node} is unnecessary")] -pub(crate) struct UnusedImportBracesDiag { - pub node: Symbol, -} - -#[derive(Diagnostic)] -#[diag("unnecessary allocation, use `&` instead")] -pub(crate) struct UnusedAllocationDiag; - -#[derive(Diagnostic)] -#[diag("unnecessary allocation, use `&mut` instead")] -pub(crate) struct UnusedAllocationMutDiag; - -pub(crate) struct AsyncFnInTraitDiag { - pub sugg: Option>, -} - -impl<'a> Diagnostic<'a, ()> for AsyncFnInTraitDiag { - fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> { - let mut diag = Diag::new( - dcx, - level, - "use of `async fn` in public traits is discouraged as auto trait bounds cannot be specified", - ); - diag.note("you can suppress this lint if you plan to use the trait only in your own code, or do not care about auto traits like `Send` on the `Future`"); - if let Some(sugg) = self.sugg { - diag.multipart_suggestion("you can alternatively desugar to a normal `fn` that returns `impl Future` and add any desired bounds such as `Send`, but these cannot be relaxed without a breaking API change", sugg, Applicability::MaybeIncorrect); - } - diag - } -} - -#[derive(Diagnostic)] -#[diag("binding has unit type `()`")] -pub(crate) struct UnitBindingsDiag { - #[label("this pattern is inferred to be the unit type `()`")] - pub label: Span, -} - -#[derive(Diagnostic)] -pub(crate) enum InvalidAsmLabel { - #[diag("avoid using named labels in inline assembly")] - #[help("only local labels of the form `:` should be used in inline asm")] - #[note( - "see the asm section of Rust By Example for more information" - )] - Named { - #[note("the label may be declared in the expansion of a macro")] - missing_precise_span: bool, - }, - #[diag("avoid using named labels in inline assembly")] - #[help("only local labels of the form `:` should be used in inline asm")] - #[note("format arguments may expand to a non-numeric value")] - #[note( - "see the asm section of Rust By Example for more information" - )] - FormatArg { - #[note("the label may be declared in the expansion of a macro")] - missing_precise_span: bool, - }, - #[diag("avoid using labels containing only the digits `0` and `1` in inline assembly")] - #[help("start numbering with `2` instead")] - #[note("an LLVM bug makes these labels ambiguous with a binary literal number on x86")] - #[note("see for more information")] - Binary { - #[note("the label may be declared in the expansion of a macro")] - missing_precise_span: bool, - // hack to get a label on the whole span, must match the emitted span - #[label("use a different label that doesn't start with `0` or `1`")] - span: Span, - }, -} - -#[derive(Diagnostic)] -#[diag("creating a {$shared_label}reference to mutable static")] -pub(crate) struct RefOfMutStatic<'a> { - #[label("{$shared_label}reference to mutable static")] - pub span: Span, - #[subdiagnostic] - pub sugg: Option, - pub shared_label: &'a str, - #[note( - "shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives" - )] - pub shared_note: bool, - #[note( - "mutable references to mutable statics are dangerous; it's undefined behavior if any other pointer to the static is used or if any other reference is created for the static while the mutable reference lives" - )] - pub mut_note: bool, - #[help( - "use a type that relies on \"interior mutability\" instead; to read more on this, visit " - )] - pub interior_mutability_help: bool, - #[subdiagnostic] - pub interior_mutability_sugg: Option, -} - -#[derive(Subdiagnostic)] -pub(crate) enum MutRefSugg { - #[multipart_suggestion( - "use `&raw const` instead to create a raw pointer", - style = "verbose", - applicability = "maybe-incorrect" - )] - Shared { - #[suggestion_part(code = "&raw const ")] - span: Span, - }, - #[multipart_suggestion( - "use `&raw mut` instead to create a raw pointer", - style = "verbose", - applicability = "maybe-incorrect" - )] - Mut { - #[suggestion_part(code = "&raw mut ")] - span: Span, - }, -} - -#[derive(Subdiagnostic)] -#[suggestion( - "this type already provides \"interior mutability\", so its binding doesn't need to be declared as mutable when borrowed with a shared reference", - style = "verbose", - applicability = "maybe-incorrect", - code = "" -)] -pub(crate) struct StaticMutRefsInteriorMutabilitySugg { - #[primary_span] - pub span: Span, -} - -#[derive(Diagnostic)] -#[diag("`use` of a local item without leading `self::`, `super::`, or `crate::`")] -pub(crate) struct UnqualifiedLocalImportsDiag; - -#[derive(Diagnostic)] -#[diag("direct cast of function item into an integer")] -pub(crate) struct FunctionCastsAsIntegerDiag<'tcx> { - #[subdiagnostic] - pub(crate) sugg: FunctionCastsAsIntegerSugg<'tcx>, -} - -#[derive(Subdiagnostic)] -#[suggestion( - "first cast to a pointer `as *const ()`", - code = " as *const ()", - applicability = "machine-applicable", - style = "verbose" -)] -pub(crate) struct FunctionCastsAsIntegerSugg<'tcx> { - #[primary_span] - pub suggestion: Span, - pub cast_to_ty: Ty<'tcx>, -} - -#[derive(Debug)] -pub(crate) struct MismatchedLifetimeSyntaxes { - pub inputs: LifetimeSyntaxCategories>, - pub outputs: LifetimeSyntaxCategories>, - - pub suggestions: Vec, -} - -impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for MismatchedLifetimeSyntaxes { - fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, G> { - let counts = self.inputs.len() + self.outputs.len(); - let message = match counts { - LifetimeSyntaxCategories { hidden: 0, elided: 0, named: 0 } => { - panic!("No lifetime mismatch detected") - } - - LifetimeSyntaxCategories { hidden: _, elided: _, named: 0 } => { - msg!("hiding a lifetime that's elided elsewhere is confusing") - } - - LifetimeSyntaxCategories { hidden: _, elided: 0, named: _ } => { - msg!("hiding a lifetime that's named elsewhere is confusing") - } - - LifetimeSyntaxCategories { hidden: 0, elided: _, named: _ } => { - msg!("eliding a lifetime that's named elsewhere is confusing") - } - - LifetimeSyntaxCategories { hidden: _, elided: _, named: _ } => { - msg!("hiding or eliding a lifetime that's named elsewhere is confusing") - } - }; - let mut diag = Diag::new(dcx, level, message); - - for s in self.inputs.hidden { - diag.span_label(s, msg!("the lifetime is hidden here")); - } - for s in self.inputs.elided { - diag.span_label(s, msg!("the lifetime is elided here")); - } - for s in self.inputs.named { - diag.span_label(s, msg!("the lifetime is named here")); - } - - let mut hidden_output_counts: FxIndexMap = FxIndexMap::default(); - for s in self.outputs.hidden { - *hidden_output_counts.entry(s).or_insert(0) += 1; - } - for (span, count) in hidden_output_counts { - let label = msg!( - "the same {$count -> - [one] lifetime - *[other] lifetimes - } {$count -> - [one] is - *[other] are - } hidden here" - ) - .arg("count", count) - .format(); - diag.span_label(span, label); - } - for s in self.outputs.elided { - diag.span_label(s, msg!("the same lifetime is elided here")); - } - for s in self.outputs.named { - diag.span_label(s, msg!("the same lifetime is named here")); - } - - diag.help(msg!( - "the same lifetime is referred to in inconsistent ways, making the signature confusing" - )); - - let mut suggestions = self.suggestions.into_iter(); - if let Some(s) = suggestions.next() { - diag.subdiagnostic(s); - - for mut s in suggestions { - s.make_optional_alternative(); - diag.subdiagnostic(s); - } - } - diag - } -} - -#[derive(Debug)] -pub(crate) enum MismatchedLifetimeSyntaxesSuggestion { - Implicit { - suggestions: Vec, - optional_alternative: bool, - }, - - Mixed { - implicit_suggestions: Vec, - explicit_anonymous_suggestions: Vec<(Span, String)>, - optional_alternative: bool, - }, - - Explicit { - lifetime_name: String, - suggestions: Vec<(Span, String)>, - optional_alternative: bool, - }, -} - -impl MismatchedLifetimeSyntaxesSuggestion { - fn make_optional_alternative(&mut self) { - use MismatchedLifetimeSyntaxesSuggestion::*; - - let optional_alternative = match self { - Implicit { optional_alternative, .. } - | Mixed { optional_alternative, .. } - | Explicit { optional_alternative, .. } => optional_alternative, - }; - - *optional_alternative = true; - } -} - -impl Subdiagnostic for MismatchedLifetimeSyntaxesSuggestion { - fn add_to_diag(self, diag: &mut Diag<'_, G>) { - use MismatchedLifetimeSyntaxesSuggestion::*; - - let style = |optional_alternative| { - if optional_alternative { - SuggestionStyle::CompletelyHidden - } else { - SuggestionStyle::ShowAlways - } - }; - - let applicability = |optional_alternative| { - // `cargo fix` can't handle more than one fix for the same issue, - // so hide alternative suggestions from it by marking them as maybe-incorrect - if optional_alternative { - Applicability::MaybeIncorrect - } else { - Applicability::MachineApplicable - } - }; - - match self { - Implicit { suggestions, optional_alternative } => { - let suggestions = suggestions.into_iter().map(|s| (s, String::new())).collect(); - diag.multipart_suggestion_with_style( - msg!("remove the lifetime name from references"), - suggestions, - applicability(optional_alternative), - style(optional_alternative), - ); - } - - Mixed { - implicit_suggestions, - explicit_anonymous_suggestions, - optional_alternative, - } => { - let message = if implicit_suggestions.is_empty() { - msg!("use `'_` for type paths") - } else { - msg!("remove the lifetime name from references and use `'_` for type paths") - }; - - let implicit_suggestions = - implicit_suggestions.into_iter().map(|s| (s, String::new())); - - let suggestions = - implicit_suggestions.chain(explicit_anonymous_suggestions).collect(); - - diag.multipart_suggestion_with_style( - message, - suggestions, - applicability(optional_alternative), - style(optional_alternative), - ); - } - - Explicit { lifetime_name, suggestions, optional_alternative } => { - let msg = msg!("consistently use `{$lifetime_name}`") - .arg("lifetime_name", lifetime_name) - .format(); - diag.multipart_suggestion_with_style( - msg, - suggestions, - applicability(optional_alternative), - style(optional_alternative), - ); - } - } - } -} - -#[derive(Diagnostic)] -#[diag("`Eq::assert_receiver_is_total_eq` should never be implemented by hand")] -#[note("this method was used to add checks to the `Eq` derive macro")] -pub(crate) struct EqInternalMethodImplemented; - -#[derive(Diagnostic)] -#[diag("cast from `{$expr_ty}` to `{$cast_ty}` implicitly relies on exposed provenance")] -#[help( - "if conforming to strict provenance is not possible, use `std::ptr::with_exposed_provenance()`" -)] -#[note("for more information, visit ")] -pub(crate) struct ImplicitProvenanceCastsInt2Ptr<'tcx> { - pub expr_ty: Ty<'tcx>, - pub cast_ty: Ty<'tcx>, - #[subdiagnostic] - pub sugg: Option, -} - -#[derive(Subdiagnostic)] -#[multipart_suggestion( - "use `.with_addr()` to adjust the address of a valid pointer in the same allocation", - applicability = "has-placeholders" -)] -pub(crate) struct Int2PtrSuggestion { - #[suggestion_part(code = "(...).with_addr(")] - pub lo: Span, - #[suggestion_part(code = ")")] - pub hi: Span, -} - -#[derive(Diagnostic)] -#[diag("cast from `{$cast_from_ty}` to `{$cast_to_ty}` implicitly exposes pointer provenance")] -#[help("if conforming to strict provenance is not possible, use `.expose_provenance()`")] -#[note("for more information, visit ")] -pub(crate) struct ImplicitProvenanceCastsPtr2Int<'tcx> { - pub cast_from_ty: Ty<'tcx>, - pub cast_to_ty: Ty<'tcx>, - #[subdiagnostic] - pub sugg: Option>, -} - -#[derive(Subdiagnostic)] -pub(crate) enum Ptr2IntSuggestion<'tcx> { - #[multipart_suggestion( - "use `.addr()` to obtain the address of a pointer", - applicability = "maybe-incorrect" - )] - NeedsParensCast { - #[suggestion_part(code = "(")] - expr_span: Span, - #[suggestion_part(code = ").addr() as {cast_to_ty}")] - cast_span: Span, - cast_to_ty: Ty<'tcx>, - }, - #[multipart_suggestion( - "use `.addr()` to obtain the address of a pointer", - applicability = "maybe-incorrect" - )] - NeedsParens { - #[suggestion_part(code = "(")] - expr_span: Span, - #[suggestion_part(code = ").addr()")] - cast_span: Span, - }, - #[suggestion( - "use `.addr()` to obtain the address of a pointer", - code = ".addr() as {cast_to_ty}", - applicability = "maybe-incorrect" - )] - NeedsCast { - #[primary_span] - cast_span: Span, - cast_to_ty: Ty<'tcx>, - }, - #[suggestion( - "use `.addr()` to obtain the address of a pointer", - code = ".addr()", - applicability = "maybe-incorrect" - )] - Other { - #[primary_span] - cast_span: Span, - }, -} - -#[derive(Diagnostic)] -#[diag( - "creating an intermediate reference implies aliasing requirements even when immediately cast to a raw pointers" -)] -pub(crate) struct RawBorrowViaReference<'a> { - #[subdiagnostic] - pub suggestion: RawBorrowViaReferenceSuggestion<'a>, -} - -#[derive(Subdiagnostic)] -pub(crate) enum RawBorrowViaReferenceSuggestion<'a> { - #[multipart_suggestion( - "consider using `&raw {$mutbl}` for a safer and more explicit raw pointer", - applicability = "machine-applicable" - )] - Spanful { - #[suggestion_part(code = "&raw {mutbl} ")] - left: Span, - #[suggestion_part(code = "")] - right: Span, - mutbl: &'a str, - }, - #[help("consider using `&raw {$mutbl}` for a safer and more explicit raw pointer")] - Spanless { mutbl: &'a str }, -} diff --git a/compiler/rustc_lint/src/macro_expr_fragment_specifier_2024_migration.rs b/compiler/rustc_lint/src/macro_expr_fragment_specifier_2024_migration.rs index 9220702c21f1d..f942cb72bc875 100644 --- a/compiler/rustc_lint/src/macro_expr_fragment_specifier_2024_migration.rs +++ b/compiler/rustc_lint/src/macro_expr_fragment_specifier_2024_migration.rs @@ -9,7 +9,7 @@ use rustc_span::sym; use tracing::debug; use crate::EarlyLintPass; -use crate::lints::MacroExprFragment2024; +use crate::diagnostics::MacroExprFragment2024; declare_lint! { /// The `edition_2024_expr_fragment_specifier` lint detects the use of diff --git a/compiler/rustc_lint/src/map_unit_fn.rs b/compiler/rustc_lint/src/map_unit_fn.rs index 50471b40ecdea..da971562edc43 100644 --- a/compiler/rustc_lint/src/map_unit_fn.rs +++ b/compiler/rustc_lint/src/map_unit_fn.rs @@ -3,7 +3,7 @@ use rustc_middle::ty; use rustc_session::{declare_lint, declare_lint_pass}; use rustc_span::sym; -use crate::lints::MappingToUnit; +use crate::diagnostics::MappingToUnit; use crate::{LateContext, LateLintPass, LintContext}; declare_lint! { diff --git a/compiler/rustc_lint/src/multiple_supertrait_upcastable.rs b/compiler/rustc_lint/src/multiple_supertrait_upcastable.rs index 7f0c615923ef1..766365134a3f4 100644 --- a/compiler/rustc_lint/src/multiple_supertrait_upcastable.rs +++ b/compiler/rustc_lint/src/multiple_supertrait_upcastable.rs @@ -55,7 +55,7 @@ impl<'tcx> LateLintPass<'tcx> for MultipleSupertraitUpcastable { cx.emit_span_lint( MULTIPLE_SUPERTRAIT_UPCASTABLE, cx.tcx.def_span(def_id), - crate::lints::MultipleSupertraitUpcastable { ident }, + crate::diagnostics::MultipleSupertraitUpcastable { ident }, ); } } diff --git a/compiler/rustc_lint/src/non_ascii_idents.rs b/compiler/rustc_lint/src/non_ascii_idents.rs index 42aba3ffcfe24..704e58c1e9a88 100644 --- a/compiler/rustc_lint/src/non_ascii_idents.rs +++ b/compiler/rustc_lint/src/non_ascii_idents.rs @@ -5,7 +5,7 @@ use rustc_session::{declare_lint, declare_lint_pass}; use rustc_span::Symbol; use unicode_security::general_security_profile::IdentifierType; -use crate::lints::{ +use crate::diagnostics::{ ConfusableIdentifierPair, IdentifierNonAsciiChar, IdentifierUncommonCodepoints, MixedScriptConfusables, }; diff --git a/compiler/rustc_lint/src/non_fmt_panic.rs b/compiler/rustc_lint/src/non_fmt_panic.rs index 7f137d5bf0603..055d2c1702406 100644 --- a/compiler/rustc_lint/src/non_fmt_panic.rs +++ b/compiler/rustc_lint/src/non_fmt_panic.rs @@ -10,7 +10,7 @@ use rustc_session::{declare_lint, declare_lint_pass}; use rustc_span::{InnerSpan, Span, Symbol, hygiene, sym}; use rustc_trait_selection::infer::InferCtxtExt; -use crate::lints::{NonFmtPanicBraces, NonFmtPanicUnused}; +use crate::diagnostics::{NonFmtPanicBraces, NonFmtPanicUnused}; use crate::{LateContext, LateLintPass, LintContext}; declare_lint! { diff --git a/compiler/rustc_lint/src/non_local_def.rs b/compiler/rustc_lint/src/non_local_def.rs index ac7155eabfdc9..e7cac4dc47ca5 100644 --- a/compiler/rustc_lint/src/non_local_def.rs +++ b/compiler/rustc_lint/src/non_local_def.rs @@ -7,7 +7,7 @@ use rustc_session::{declare_lint, impl_lint_pass}; use rustc_span::def_id::{DefId, LOCAL_CRATE}; use rustc_span::{ExpnKind, Span, kw}; -use crate::lints::{NonLocalDefinitionsCargoUpdateNote, NonLocalDefinitionsDiag}; +use crate::diagnostics::{NonLocalDefinitionsCargoUpdateNote, NonLocalDefinitionsDiag}; use crate::{LateContext, LateLintPass, LintContext}; declare_lint! { diff --git a/compiler/rustc_lint/src/nonstandard_style.rs b/compiler/rustc_lint/src/nonstandard_style.rs index 5a1b56f004be0..075fcb1115464 100644 --- a/compiler/rustc_lint/src/nonstandard_style.rs +++ b/compiler/rustc_lint/src/nonstandard_style.rs @@ -15,7 +15,7 @@ use rustc_session::{declare_lint, declare_lint_pass}; use rustc_span::def_id::LocalDefId; use rustc_span::{BytePos, Ident, Span, sym}; -use crate::lints::{ +use crate::diagnostics::{ NonCamelCaseType, NonCamelCaseTypeSub, NonSnakeCaseDiag, NonSnakeCaseDiagSub, NonUpperCaseGlobal, NonUpperCaseGlobalSub, NonUpperCaseGlobalSubTool, }; diff --git a/compiler/rustc_lint/src/noop_method_call.rs b/compiler/rustc_lint/src/noop_method_call.rs index 6ea72de92ce8c..64acd73201399 100644 --- a/compiler/rustc_lint/src/noop_method_call.rs +++ b/compiler/rustc_lint/src/noop_method_call.rs @@ -7,7 +7,7 @@ use rustc_session::{declare_lint, declare_lint_pass}; use rustc_span::sym; use crate::context::LintContext; -use crate::lints::{ +use crate::diagnostics::{ NoopMethodCallDiag, SuspiciousDoubleRefCloneDiag, SuspiciousDoubleRefDerefDiag, }; use crate::{LateContext, LateLintPass}; diff --git a/compiler/rustc_lint/src/precedence.rs b/compiler/rustc_lint/src/precedence.rs index 7c073e5025b9b..dc60ed12644a0 100644 --- a/compiler/rustc_lint/src/precedence.rs +++ b/compiler/rustc_lint/src/precedence.rs @@ -2,7 +2,7 @@ use rustc_ast::token::LitKind; use rustc_ast::{Expr, ExprKind, MethodCall, UnOp}; use rustc_session::{declare_lint, declare_lint_pass}; -use crate::lints::{ +use crate::diagnostics::{ AmbiguousNegativeLiteralsCurrentBehaviorSuggestion, AmbiguousNegativeLiteralsDiag, AmbiguousNegativeLiteralsNegativeLiteralSuggestion, }; diff --git a/compiler/rustc_lint/src/ptr_nulls.rs b/compiler/rustc_lint/src/ptr_nulls.rs index e8783db8524a8..f84ea8b91e888 100644 --- a/compiler/rustc_lint/src/ptr_nulls.rs +++ b/compiler/rustc_lint/src/ptr_nulls.rs @@ -4,7 +4,7 @@ use rustc_middle::ty::RawPtr; use rustc_session::{declare_lint, declare_lint_pass}; use rustc_span::{Span, sym}; -use crate::lints::{InvalidNullArgumentsDiag, UselessPtrNullChecksDiag}; +use crate::diagnostics::{InvalidNullArgumentsDiag, UselessPtrNullChecksDiag}; use crate::utils::peel_casts; use crate::{LateContext, LateLintPass, LintContext}; diff --git a/compiler/rustc_lint/src/raw_borrows_via_references.rs b/compiler/rustc_lint/src/raw_borrows_via_references.rs index 69ae1b61e094c..1d2b5aaf211ce 100644 --- a/compiler/rustc_lint/src/raw_borrows_via_references.rs +++ b/compiler/rustc_lint/src/raw_borrows_via_references.rs @@ -2,7 +2,7 @@ use rustc_ast::BorrowKind; use rustc_hir::{Expr, ExprKind, TyKind}; use rustc_session::{declare_lint, declare_lint_pass}; -use crate::lints::{RawBorrowViaReference, RawBorrowViaReferenceSuggestion}; +use crate::diagnostics::{RawBorrowViaReference, RawBorrowViaReferenceSuggestion}; use crate::{LateContext, LateLintPass, LintContext}; declare_lint! { diff --git a/compiler/rustc_lint/src/redundant_semicolon.rs b/compiler/rustc_lint/src/redundant_semicolon.rs index f6d2fbe42618e..4910be5c8753e 100644 --- a/compiler/rustc_lint/src/redundant_semicolon.rs +++ b/compiler/rustc_lint/src/redundant_semicolon.rs @@ -2,7 +2,7 @@ use rustc_ast::{Block, StmtKind}; use rustc_session::{declare_lint, declare_lint_pass}; use rustc_span::Span; -use crate::lints::{RedundantSemicolonsDiag, RedundantSemicolonsSuggestion}; +use crate::diagnostics::{RedundantSemicolonsDiag, RedundantSemicolonsSuggestion}; use crate::{EarlyContext, EarlyLintPass, LintContext}; declare_lint! { diff --git a/compiler/rustc_lint/src/reference_casting.rs b/compiler/rustc_lint/src/reference_casting.rs index d3ae30492aada..fccde7b93c5d3 100644 --- a/compiler/rustc_lint/src/reference_casting.rs +++ b/compiler/rustc_lint/src/reference_casting.rs @@ -5,7 +5,7 @@ use rustc_middle::ty::{self, Ty}; use rustc_session::{declare_lint, declare_lint_pass}; use rustc_span::sym; -use crate::lints::InvalidReferenceCastingDiag; +use crate::diagnostics::InvalidReferenceCastingDiag; use crate::utils::peel_casts; use crate::{LateContext, LateLintPass, LintContext}; diff --git a/compiler/rustc_lint/src/runtime_symbols.rs b/compiler/rustc_lint/src/runtime_symbols.rs index cf1db7e28364c..c909eb87d67be 100644 --- a/compiler/rustc_lint/src/runtime_symbols.rs +++ b/compiler/rustc_lint/src/runtime_symbols.rs @@ -7,7 +7,7 @@ use rustc_session::{declare_lint, declare_lint_pass}; use rustc_span::{Span, Symbol}; use rustc_trait_selection::infer::TyCtxtInferExt; -use crate::lints::RedefiningRuntimeSymbolsDiag; +use crate::diagnostics::RedefiningRuntimeSymbolsDiag; use crate::{LateContext, LateLintPass, LintContext}; declare_lint! { diff --git a/compiler/rustc_lint/src/shadowed_into_iter.rs b/compiler/rustc_lint/src/shadowed_into_iter.rs index 05bb2113db09e..c03e7396fd2b7 100644 --- a/compiler/rustc_lint/src/shadowed_into_iter.rs +++ b/compiler/rustc_lint/src/shadowed_into_iter.rs @@ -3,7 +3,7 @@ use rustc_middle::ty::{self, Ty}; use rustc_session::lint::fcw; use rustc_session::{declare_lint, impl_lint_pass}; -use crate::lints::{ShadowedIntoIterDiag, ShadowedIntoIterDiagSub}; +use crate::diagnostics::{ShadowedIntoIterDiag, ShadowedIntoIterDiagSub}; use crate::{LateContext, LateLintPass, LintContext}; declare_lint! { diff --git a/compiler/rustc_lint/src/static_mut_refs.rs b/compiler/rustc_lint/src/static_mut_refs.rs index 0dbed4ed1c0da..347bc8fa25403 100644 --- a/compiler/rustc_lint/src/static_mut_refs.rs +++ b/compiler/rustc_lint/src/static_mut_refs.rs @@ -6,7 +6,7 @@ use rustc_session::lint::fcw; use rustc_session::{declare_lint, declare_lint_pass}; use rustc_span::{BytePos, Span}; -use crate::lints::{MutRefSugg, RefOfMutStatic, StaticMutRefsInteriorMutabilitySugg}; +use crate::diagnostics::{MutRefSugg, RefOfMutStatic, StaticMutRefsInteriorMutabilitySugg}; use crate::{LateContext, LateLintPass, LintContext}; declare_lint! { diff --git a/compiler/rustc_lint/src/traits.rs b/compiler/rustc_lint/src/traits.rs index f5b21792af3ce..9ffc3246a5f38 100644 --- a/compiler/rustc_lint/src/traits.rs +++ b/compiler/rustc_lint/src/traits.rs @@ -2,7 +2,7 @@ use rustc_hir::{self as hir, AmbigArg, LangItem}; use rustc_session::{declare_lint, declare_lint_pass}; use rustc_span::sym; -use crate::lints::{DropGlue, DropTraitConstraintsDiag}; +use crate::diagnostics::{DropGlue, DropTraitConstraintsDiag}; use crate::{LateContext, LateLintPass, LintContext}; declare_lint! { diff --git a/compiler/rustc_lint/src/transmute.rs b/compiler/rustc_lint/src/transmute.rs index 4ee25ac008eb7..86d88849b2ef6 100644 --- a/compiler/rustc_lint/src/transmute.rs +++ b/compiler/rustc_lint/src/transmute.rs @@ -8,7 +8,7 @@ use rustc_middle::ty::{self, Ty}; use rustc_session::{declare_lint, impl_lint_pass}; use rustc_span::sym; -use crate::lints::{IntegerToPtrTransmutes, IntegerToPtrTransmutesSuggestion}; +use crate::diagnostics::{IntegerToPtrTransmutes, IntegerToPtrTransmutesSuggestion}; use crate::{LateContext, LateLintPass}; declare_lint! { diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs index 083d2e4ee0499..44167af19f1e7 100644 --- a/compiler/rustc_lint/src/types.rs +++ b/compiler/rustc_lint/src/types.rs @@ -14,7 +14,7 @@ use tracing::debug; mod improper_ctypes; // these files do the implementation for ImproperCTypesDefinitions,ImproperCTypesDeclarations pub(crate) use improper_ctypes::ImproperCTypesLint; -use crate::lints::{ +use crate::diagnostics::{ AmbiguousWidePointerComparisons, AmbiguousWidePointerComparisonsAddrMetadataSuggestion, AmbiguousWidePointerComparisonsAddrSuggestion, AmbiguousWidePointerComparisonsCastSuggestion, AmbiguousWidePointerComparisonsExpectSuggestion, AtomicOrderingFence, AtomicOrderingLoad, diff --git a/compiler/rustc_lint/src/types/improper_ctypes.rs b/compiler/rustc_lint/src/types/improper_ctypes.rs index 0c34d9da66f1d..496cf40490552 100644 --- a/compiler/rustc_lint/src/types/improper_ctypes.rs +++ b/compiler/rustc_lint/src/types/improper_ctypes.rs @@ -20,7 +20,7 @@ use rustc_target::spec::Os; use tracing::debug; use super::repr_nullable_ptr; -use crate::lints::{ImproperCTypes, UsesPowerAlignment}; +use crate::diagnostics::{ImproperCTypes, UsesPowerAlignment}; use crate::{LateContext, LateLintPass, LintContext}; declare_lint! { diff --git a/compiler/rustc_lint/src/types/literal.rs b/compiler/rustc_lint/src/types/literal.rs index 4759f087ed08b..bffd5d144c778 100644 --- a/compiler/rustc_lint/src/types/literal.rs +++ b/compiler/rustc_lint/src/types/literal.rs @@ -12,7 +12,7 @@ use rustc_span::{Span, Symbol}; use crate::LateContext; use crate::context::LintContext; -use crate::lints::{ +use crate::diagnostics::{ OnlyCastu8ToChar, OverflowingBinHex, OverflowingBinHexSign, OverflowingBinHexSignBitSub, OverflowingBinHexSub, OverflowingInt, OverflowingIntHelp, OverflowingLiteral, OverflowingUInt, RangeEndpointOutOfRange, SurrogateCharCast, TooLargeCharCast, UseInclusiveRange, diff --git a/compiler/rustc_lint/src/unit_bindings.rs b/compiler/rustc_lint/src/unit_bindings.rs index 61c4a95c995b4..ef014a987bb9e 100644 --- a/compiler/rustc_lint/src/unit_bindings.rs +++ b/compiler/rustc_lint/src/unit_bindings.rs @@ -1,7 +1,7 @@ use rustc_hir as hir; use rustc_session::{declare_lint, declare_lint_pass}; -use crate::lints::UnitBindingsDiag; +use crate::diagnostics::UnitBindingsDiag; use crate::{LateLintPass, LintContext}; declare_lint! { diff --git a/compiler/rustc_lint/src/unqualified_local_imports.rs b/compiler/rustc_lint/src/unqualified_local_imports.rs index 888bf026b4ed9..40bafff12d8d4 100644 --- a/compiler/rustc_lint/src/unqualified_local_imports.rs +++ b/compiler/rustc_lint/src/unqualified_local_imports.rs @@ -2,7 +2,7 @@ use rustc_hir as hir; use rustc_session::{declare_lint, declare_lint_pass}; use rustc_span::kw; -use crate::{LateContext, LateLintPass, LintContext, lints}; +use crate::{LateContext, LateLintPass, LintContext, diagnostics}; declare_lint! { /// The `unqualified_local_imports` lint checks for `use` items that import a local item using a @@ -77,7 +77,7 @@ impl<'tcx> LateLintPass<'tcx> for UnqualifiedLocalImports { cx.emit_span_lint( UNQUALIFIED_LOCAL_IMPORTS, first_seg.ident.span, - lints::UnqualifiedLocalImportsDiag, + diagnostics::UnqualifiedLocalImportsDiag, ); } } diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs index c1bf9b3345bc3..7dea17ac55140 100644 --- a/compiler/rustc_lint/src/unused.rs +++ b/compiler/rustc_lint/src/unused.rs @@ -8,7 +8,7 @@ use rustc_session::{declare_lint, declare_lint_pass, impl_lint_pass}; use rustc_span::edition::Edition::Edition2015; use rustc_span::{BytePos, Span, kw, sym}; -use crate::lints::{ +use crate::diagnostics::{ PathStatementDrop, PathStatementDropSub, PathStatementNoEffect, UnusedAllocationDiag, UnusedAllocationMutDiag, UnusedDelim, UnusedDelimSuggestion, UnusedImportBracesDiag, }; diff --git a/compiler/rustc_lint/src/unused/must_use.rs b/compiler/rustc_lint/src/unused/must_use.rs index e72335c80d505..3f10b521883ef 100644 --- a/compiler/rustc_lint/src/unused/must_use.rs +++ b/compiler/rustc_lint/src/unused/must_use.rs @@ -10,7 +10,7 @@ use rustc_session::{declare_lint, declare_lint_pass}; use rustc_span::{Span, Symbol, sym}; use tracing::instrument; -use crate::lints::{ +use crate::diagnostics::{ UnusedClosure, UnusedCoroutine, UnusedDef, UnusedDefSuggestion, UnusedOp, UnusedOpSuggestion, UnusedResult, }; From 442b3ec3f94a3902e13ab4b2f84fb628b06a6a01 Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Sat, 8 Aug 2026 15:12:07 +0200 Subject: [PATCH 09/13] Merge `rustc_attr_parsing/session_diagnostics.rs` into `diagnostics.rs` --- .../src/attributes/allow_unstable.rs | 6 +- .../rustc_attr_parsing/src/attributes/cfg.rs | 28 +- .../src/attributes/codegen_attrs.rs | 2 +- .../src/attributes/confusables.rs | 2 +- .../src/attributes/deprecation.rs | 4 +- .../rustc_attr_parsing/src/attributes/doc.rs | 14 +- .../src/attributes/inline.rs | 2 +- .../src/attributes/instruction_set.rs | 4 +- .../src/attributes/link_attrs.rs | 2 +- .../src/attributes/lint_helpers.rs | 2 +- .../src/attributes/macro_attrs.rs | 2 +- .../rustc_attr_parsing/src/attributes/mod.rs | 2 +- .../src/attributes/prototype.rs | 11 +- .../rustc_attr_parsing/src/attributes/repr.rs | 9 +- .../src/attributes/rustc_internal.rs | 6 +- .../src/attributes/stability.rs | 58 +- .../rustc_attr_parsing/src/attributes/util.rs | 2 +- compiler/rustc_attr_parsing/src/context.rs | 8 +- .../rustc_attr_parsing/src/diagnostics.rs | 1163 ++++++++++++++++- compiler/rustc_attr_parsing/src/interface.rs | 2 +- compiler/rustc_attr_parsing/src/lib.rs | 3 +- compiler/rustc_attr_parsing/src/parser.rs | 2 +- compiler/rustc_attr_parsing/src/safety.rs | 11 +- .../src/session_diagnostics.rs | 1162 ---------------- .../rustc_attr_parsing/src/target_checking.rs | 4 +- .../rustc_attr_parsing/src/validate_attr.rs | 2 +- 26 files changed, 1241 insertions(+), 1272 deletions(-) delete mode 100644 compiler/rustc_attr_parsing/src/session_diagnostics.rs diff --git a/compiler/rustc_attr_parsing/src/attributes/allow_unstable.rs b/compiler/rustc_attr_parsing/src/attributes/allow_unstable.rs index 5610ef6a83dc0..743d3c9b5e76e 100644 --- a/compiler/rustc_attr_parsing/src/attributes/allow_unstable.rs +++ b/compiler/rustc_attr_parsing/src/attributes/allow_unstable.rs @@ -4,7 +4,7 @@ use rustc_feature::AttributeStability; use super::macro_attrs::check_macro_only; use super::prelude::*; -use crate::session_diagnostics; +use crate::diagnostics; pub(crate) struct AllowInternalUnstableParser; impl CombineAttributeParser for AllowInternalUnstableParser { @@ -92,7 +92,7 @@ fn parse_unstable( let mut res = Vec::new(); let Some(list) = args.as_list() else { - cx.emit_err(session_diagnostics::ExpectsFeatureList { + cx.emit_err(diagnostics::ExpectsFeatureList { span: cx.attr_span, name: symbol.to_ident_string(), }); @@ -104,7 +104,7 @@ fn parse_unstable( if let Some(ident) = param.meta_item_no_args().and_then(|i| i.path().word()) { res.push(ident.name); } else { - cx.emit_err(session_diagnostics::ExpectsFeatures { + cx.emit_err(diagnostics::ExpectsFeatures { span: param_span, name: symbol.to_ident_string(), }); diff --git a/compiler/rustc_attr_parsing/src/attributes/cfg.rs b/compiler/rustc_attr_parsing/src/attributes/cfg.rs index ef37027f07b96..9ac15a5dc87b7 100644 --- a/compiler/rustc_attr_parsing/src/attributes/cfg.rs +++ b/compiler/rustc_attr_parsing/src/attributes/cfg.rs @@ -19,16 +19,14 @@ use thin_vec::ThinVec; use crate::attributes::AttributeSafety; use crate::context::{AcceptContext, ShouldEmit}; -use crate::parser::{ - AllowExprMetavar, ArgParser, MetaItemListParser, MetaItemOrLitParser, NameValueParser, -}; -use crate::session_diagnostics::{ +use crate::diagnostics::{ AttributeParseError, AttributeParseErrorReason, CfgAttrBadDelim, MetaBadDelimSugg, ParsedDescription, }; -use crate::{ - AttributeParser, AttributeTemplate, check_cfg, parse_version, session_diagnostics, template, +use crate::parser::{ + AllowExprMetavar, ArgParser, MetaItemListParser, MetaItemOrLitParser, NameValueParser, }; +use crate::{AttributeParser, AttributeTemplate, check_cfg, diagnostics, parse_version, template}; pub const CFG_TEMPLATE: AttributeTemplate = template!( List: &["predicate"], @@ -131,25 +129,17 @@ fn parse_cfg_entry_version( ) -> Result { try_gate_cfg(sym::version, meta_span, cx.sess(), cx.features_option()); let Some(version) = list.as_single() else { - return Err( - cx.emit_err(session_diagnostics::ExpectedSingleVersionLiteral { span: list.span }) - ); + return Err(cx.emit_err(diagnostics::ExpectedSingleVersionLiteral { span: list.span })); }; let Some(version_lit) = version.as_lit() else { - return Err( - cx.emit_err(session_diagnostics::ExpectedVersionLiteral { span: version.span() }) - ); + return Err(cx.emit_err(diagnostics::ExpectedVersionLiteral { span: version.span() })); }; let Some(version_str) = version_lit.value_as_str() else { - return Err( - cx.emit_err(session_diagnostics::ExpectedVersionLiteral { span: version_lit.span }) - ); + return Err(cx.emit_err(diagnostics::ExpectedVersionLiteral { span: version_lit.span })); }; let min_version = parse_version(version_str).or_else(|| { - cx.sess() - .dcx() - .emit_warn(session_diagnostics::UnknownVersionLiteral { span: version_lit.span }); + cx.sess().dcx().emit_warn(diagnostics::UnknownVersionLiteral { span: version_lit.span }); None }); @@ -362,7 +352,7 @@ pub fn parse_cfg_attr( path: AttrPath::from_ast(&cfg_attr.get_normal_item().path, identity), description: ParsedDescription::Attribute, reason, - suggestions: session_diagnostics::AttributeParseErrorSuggestions::CreatedByTemplate( + suggestions: diagnostics::AttributeParseErrorSuggestions::CreatedByTemplate( CFG_ATTR_TEMPLATE.suggestions( ParsedDescription::Attribute, cfg_attr.get_normal_item().unsafety, diff --git a/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs index d9ae0aa0b2307..1e56b65c633b1 100644 --- a/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs @@ -8,7 +8,7 @@ use rustc_span::edition::Edition::Edition2024; use super::prelude::*; use crate::attributes::AttributeSafety; -use crate::session_diagnostics::{ +use crate::diagnostics::{ EmptyExportName, EmptySection, NakedFunctionIncompatibleAttribute, NullOnExport, NullOnObjcClass, NullOnObjcSelector, NullOnSection, ObjcClassExpectedStringLiteral, ObjcSelectorExpectedStringLiteral, SanitizeInvalidStatic, TargetFeatureOnLangItem, diff --git a/compiler/rustc_attr_parsing/src/attributes/confusables.rs b/compiler/rustc_attr_parsing/src/attributes/confusables.rs index 091566012d158..780e7fc1333b6 100644 --- a/compiler/rustc_attr_parsing/src/attributes/confusables.rs +++ b/compiler/rustc_attr_parsing/src/attributes/confusables.rs @@ -1,7 +1,7 @@ use rustc_feature::AttributeStability; use super::prelude::*; -use crate::session_diagnostics::EmptyConfusables; +use crate::diagnostics::EmptyConfusables; #[derive(Default)] pub(crate) struct ConfusablesParser { diff --git a/compiler/rustc_attr_parsing/src/attributes/deprecation.rs b/compiler/rustc_attr_parsing/src/attributes/deprecation.rs index 46f99691b602d..c3fadb9f41489 100644 --- a/compiler/rustc_attr_parsing/src/attributes/deprecation.rs +++ b/compiler/rustc_attr_parsing/src/attributes/deprecation.rs @@ -5,9 +5,7 @@ use rustc_hir::attrs::{DeprecatedSince, Deprecation, RustcVersion}; use super::prelude::*; use super::util::parse_version; -use crate::session_diagnostics::{ - DeprecatedItemSuggestion, InvalidSince, MissingNote, MissingSince, -}; +use crate::diagnostics::{DeprecatedItemSuggestion, InvalidSince, MissingNote, MissingSince}; fn get( cx: &mut AcceptContext<'_, '_>, diff --git a/compiler/rustc_attr_parsing/src/attributes/doc.rs b/compiler/rustc_attr_parsing/src/attributes/doc.rs index cba00f5f068a6..897dea6cd49f9 100644 --- a/compiler/rustc_attr_parsing/src/attributes/doc.rs +++ b/compiler/rustc_attr_parsing/src/attributes/doc.rs @@ -14,20 +14,18 @@ use super::prelude::{ALL_TARGETS, AllowedTargets}; use super::{AcceptMapping, AttributeParser, template}; use crate::context::{AcceptContext, FinalizeContext}; use crate::diagnostics::{ - AttrCrateLevelOnly, DocAliasDuplicated, DocAutoCfgExpectsHideOrShow, + AttrCrateLevelOnly, DocAliasBadChar, DocAliasDuplicated, DocAliasEmpty, DocAliasMalformed, + DocAliasStartEnd, DocAttrNotCrateLevel, DocAttributeNotAttribute, DocAutoCfgExpectsHideOrShow, DocAutoCfgHideShowExpectsList, DocAutoCfgHideShowNoIdentBeforeValues, DocAutoCfgHideShowUnexpectedItem, DocAutoCfgHideShowUnexpectedItemAfterValues, - DocAutoCfgHideShowValuesMix, DocAutoCfgWrongLiteral, DocTestLiteral, DocTestTakesList, - DocTestUnknown, DocUnknownAny, DocUnknownInclude, DocUnknownPasses, DocUnknownPlugins, - DocUnknownSpotlight, ExpectedNameValue, ExpectedNoArgs, IllFormedAttributeInput, MalformedDoc, + DocAutoCfgHideShowValuesMix, DocAutoCfgWrongLiteral, DocKeywordNotKeyword, DocTestLiteral, + DocTestTakesList, DocTestUnknown, DocUnknownAny, DocUnknownInclude, DocUnknownPasses, + DocUnknownPlugins, DocUnknownSpotlight, ExpectedNameValue, ExpectedNoArgs, + IllFormedAttributeInput, MalformedDoc, UnusedDuplicate, }; use crate::parser::{ ArgParser, MetaItemListParser, MetaItemOrLitParser, MetaItemParser, OwnedPathParser, }; -use crate::session_diagnostics::{ - DocAliasBadChar, DocAliasEmpty, DocAliasMalformed, DocAliasStartEnd, DocAttrNotCrateLevel, - DocAttributeNotAttribute, DocKeywordNotKeyword, UnusedDuplicate, -}; fn check_keyword(cx: &mut AcceptContext<'_, '_>, keyword: Symbol, span: Span) -> bool { // FIXME: Once rustdoc can handle URL conflicts on case insensitive file systems, we diff --git a/compiler/rustc_attr_parsing/src/attributes/inline.rs b/compiler/rustc_attr_parsing/src/attributes/inline.rs index 52960ae220a59..c3972b23eb101 100644 --- a/compiler/rustc_attr_parsing/src/attributes/inline.rs +++ b/compiler/rustc_attr_parsing/src/attributes/inline.rs @@ -4,7 +4,7 @@ use rustc_hir::find_attr; use rustc_session::lint::builtin::ILL_FORMED_ATTRIBUTE_INPUT; use super::prelude::*; -use crate::session_diagnostics::InlineForceInlineConflict; +use crate::diagnostics::InlineForceInlineConflict; pub(crate) struct InlineParser; diff --git a/compiler/rustc_attr_parsing/src/attributes/instruction_set.rs b/compiler/rustc_attr_parsing/src/attributes/instruction_set.rs index 3a4bb926f759c..afca9845f8cbe 100644 --- a/compiler/rustc_attr_parsing/src/attributes/instruction_set.rs +++ b/compiler/rustc_attr_parsing/src/attributes/instruction_set.rs @@ -2,7 +2,7 @@ use rustc_feature::AttributeStability; use rustc_hir::attrs::InstructionSetAttr; use super::prelude::*; -use crate::session_diagnostics; +use crate::diagnostics; pub(crate) struct InstructionSetParser; @@ -43,7 +43,7 @@ impl SingleAttributeParser for InstructionSetParser { let instruction_set = match architecture.name { sym::arm => { if !cx.sess.target.has_thumb_interworking { - cx.dcx().emit_err(session_diagnostics::UnsupportedInstructionSet { + cx.dcx().emit_err(diagnostics::UnsupportedInstructionSet { span: cx.attr_span, instruction_set: sym::arm, current_target: &cx.sess.opts.target_triple, diff --git a/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs index 935265924d7da..ed44cb1d5afc9 100644 --- a/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs @@ -13,7 +13,7 @@ use super::prelude::*; use super::util::parse_single_integer; use crate::attributes::AttributeSafety; use crate::attributes::cfg::parse_cfg_entry; -use crate::session_diagnostics::{ +use crate::diagnostics::{ AsNeededCompatibility, BothFfiConstAndPure, BundleNeedsStatic, EmptyLinkName, ExportSymbolsNeedsStatic, ImportNameTypeRaw, ImportNameTypeX86, IncompatibleWasmLink, InvalidLinkModifier, InvalidMachoSection, InvalidMachoSectionReason, LinkFrameworkApple, diff --git a/compiler/rustc_attr_parsing/src/attributes/lint_helpers.rs b/compiler/rustc_attr_parsing/src/attributes/lint_helpers.rs index 8011beb05546f..719afeb1de0d1 100644 --- a/compiler/rustc_attr_parsing/src/attributes/lint_helpers.rs +++ b/compiler/rustc_attr_parsing/src/attributes/lint_helpers.rs @@ -3,7 +3,7 @@ use rustc_hir::attrs::ReprAttr; use rustc_hir::find_attr; use super::prelude::*; -use crate::session_diagnostics::RustcPubTransparent; +use crate::diagnostics::RustcPubTransparent; pub(crate) struct RustcAsPtrParser; impl NoArgsAttributeParser for RustcAsPtrParser { diff --git a/compiler/rustc_attr_parsing/src/attributes/macro_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/macro_attrs.rs index 3dec77d3a3550..d382a948bffca 100644 --- a/compiler/rustc_attr_parsing/src/attributes/macro_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/macro_attrs.rs @@ -4,7 +4,7 @@ use rustc_hir::find_attr; use rustc_session::lint::builtin::INVALID_MACRO_EXPORT_ARGUMENTS; use super::prelude::*; -use crate::session_diagnostics::MacroOnlyAttribute; +use crate::diagnostics::MacroOnlyAttribute; pub(crate) struct MacroEscapeParser; impl NoArgsAttributeParser for MacroEscapeParser { diff --git a/compiler/rustc_attr_parsing/src/attributes/mod.rs b/compiler/rustc_attr_parsing/src/attributes/mod.rs index 1f88d2ab95e9b..09db8dcb84785 100644 --- a/compiler/rustc_attr_parsing/src/attributes/mod.rs +++ b/compiler/rustc_attr_parsing/src/attributes/mod.rs @@ -27,8 +27,8 @@ use rustc_span::{Span, Symbol}; use thin_vec::ThinVec; use crate::context::{AcceptContext, FinalizeCheckContext, FinalizeCheckFn, FinalizeContext}; +use crate::diagnostics::UnusedMultiple; use crate::parser::ArgParser; -use crate::session_diagnostics::UnusedMultiple; use crate::target_checking::AllowedTargets; use crate::{AttributeTemplate, template}; diff --git a/compiler/rustc_attr_parsing/src/attributes/prototype.rs b/compiler/rustc_attr_parsing/src/attributes/prototype.rs index a41010395e7c1..48f65c2434584 100644 --- a/compiler/rustc_attr_parsing/src/attributes/prototype.rs +++ b/compiler/rustc_attr_parsing/src/attributes/prototype.rs @@ -10,7 +10,7 @@ use crate::context::AcceptContext; use crate::parser::{ArgParser, NameValueParser}; use crate::target_checking::AllowedTargets; use crate::target_checking::Policy::Allow; -use crate::{AttributeTemplate, session_diagnostics, template, unstable}; +use crate::{AttributeTemplate, diagnostics, template, unstable}; pub(crate) struct CustomMirParser; @@ -140,10 +140,7 @@ fn check_custom_mir( let Some((dialect, dialect_span)) = dialect else { if let Some((_, phase_span)) = phase { *failed = true; - cx.emit_err(session_diagnostics::CustomMirPhaseRequiresDialect { - attr_span, - phase_span, - }); + cx.emit_err(diagnostics::CustomMirPhaseRequiresDialect { attr_span, phase_span }); } return; }; @@ -152,7 +149,7 @@ fn check_custom_mir( MirDialect::Analysis => { if let Some((MirPhase::Optimized, phase_span)) = phase { *failed = true; - cx.emit_err(session_diagnostics::CustomMirIncompatibleDialectAndPhase { + cx.emit_err(diagnostics::CustomMirIncompatibleDialectAndPhase { dialect, phase: MirPhase::Optimized, attr_span, @@ -165,7 +162,7 @@ fn check_custom_mir( MirDialect::Built => { if let Some((phase, phase_span)) = phase { *failed = true; - cx.emit_err(session_diagnostics::CustomMirIncompatibleDialectAndPhase { + cx.emit_err(diagnostics::CustomMirIncompatibleDialectAndPhase { dialect, phase, attr_span, diff --git a/compiler/rustc_attr_parsing/src/attributes/repr.rs b/compiler/rustc_attr_parsing/src/attributes/repr.rs index bb0da73df015c..d815cf7e5d931 100644 --- a/compiler/rustc_attr_parsing/src/attributes/repr.rs +++ b/compiler/rustc_attr_parsing/src/attributes/repr.rs @@ -6,7 +6,7 @@ use rustc_hir::attrs::ReprAttr; use rustc_session::diagnostics::feature_err; use super::prelude::*; -use crate::session_diagnostics; +use crate::diagnostics; /// Parse #[repr(...)] forms. /// @@ -236,10 +236,7 @@ fn parse_repr_align( AlignKind::Align => ReprAttr::ReprAlign(literal), }), Err(message) => { - cx.emit_err(session_diagnostics::InvalidAlignmentValue { - span: lit.span, - error_part: message, - }); + cx.emit_err(diagnostics::InvalidAlignmentValue { span: lit.span, error_part: message }); None } } @@ -298,7 +295,7 @@ impl RustcAlignParser { match parse_alignment(&lit.kind, cx) { Ok(literal) => self.0 = Ord::max(self.0, Some((literal, cx.attr_span))), Err(message) => { - cx.emit_err(session_diagnostics::InvalidAlignmentValue { + cx.emit_err(diagnostics::InvalidAlignmentValue { span: lit.span, error_part: message, }); diff --git a/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs b/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs index b101d378bab98..5b7d305ba0d28 100644 --- a/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs +++ b/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs @@ -14,9 +14,9 @@ use rustc_span::Symbol; use super::prelude::*; use super::util::parse_single_integer; use crate::diagnostics; -use crate::diagnostics::UnknownExternLangItem; -use crate::session_diagnostics::{ - AttributeRequiresOpt, CguFieldsMissing, RustcScalableVectorCountOutOfRange, UnknownLangItem, +use crate::diagnostics::{ + AttributeRequiresOpt, CguFieldsMissing, RustcScalableVectorCountOutOfRange, + UnknownExternLangItem, UnknownLangItem, }; pub(crate) struct RustcMainParser; diff --git a/compiler/rustc_attr_parsing/src/attributes/stability.rs b/compiler/rustc_attr_parsing/src/attributes/stability.rs index 62f16d9719d23..71be778905f26 100644 --- a/compiler/rustc_attr_parsing/src/attributes/stability.rs +++ b/compiler/rustc_attr_parsing/src/attributes/stability.rs @@ -11,7 +11,7 @@ use rustc_hir::{ use super::prelude::*; use super::util::parse_version; -use crate::session_diagnostics; +use crate::diagnostics; const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[ Allow(Target::Fn), @@ -54,7 +54,7 @@ impl StabilityParser { /// Checks, and emits an error when a stability (or unstability) was already set, which would be a duplicate. fn check_duplicate(&self, cx: &AcceptContext<'_, '_>) -> bool { if let Some((_, _)) = self.stability { - cx.emit_err(session_diagnostics::MultipleStabilityLevels { span: cx.attr_span }); + cx.emit_err(diagnostics::MultipleStabilityLevels { span: cx.attr_span }); true } else { false @@ -117,16 +117,15 @@ impl AttributeParser for StabilityParser { { *allowed_through_unstable_modules = Some(atum); } else { - cx.dcx().emit_err(session_diagnostics::RustcAllowedUnstablePairing { - span: cx.target_span, - }); + cx.dcx() + .emit_err(diagnostics::RustcAllowedUnstablePairing { span: cx.target_span }); } } if let Some((Stability { level: StabilityLevel::Stable { .. }, .. }, _)) = self.stability { for other_attr in cx.all_attrs { if other_attr.word_is(sym::unstable_feature_bound) { - cx.emit_err(session_diagnostics::UnstableFeatureBoundIncompatibleStability { + cx.emit_err(diagnostics::UnstableFeatureBoundIncompatibleStability { span: cx.target_span, }); } @@ -152,8 +151,7 @@ impl AttributeParser for BodyStabilityParser { unstable!(staged_api), |this, cx, args| { if this.stability.is_some() { - cx.dcx() - .emit_err(session_diagnostics::MultipleStabilityLevels { span: cx.attr_span }); + cx.dcx().emit_err(diagnostics::MultipleStabilityLevels { span: cx.attr_span }); } else if let Some((feature, level)) = parse_unstability(cx, args) { this.stability = Some((DefaultBodyStability { level, feature }, cx.attr_span)); } @@ -190,7 +188,7 @@ impl ConstStabilityParser { /// Checks, and emits an error when a stability (or unstability) was already set, which would be a duplicate. fn check_duplicate(&self, cx: &AcceptContext<'_, '_>) -> bool { if let Some((_, _)) = self.stability { - cx.emit_err(session_diagnostics::MultipleStabilityLevels { span: cx.attr_span }); + cx.emit_err(diagnostics::MultipleStabilityLevels { span: cx.attr_span }); true } else { false @@ -254,8 +252,7 @@ impl AttributeParser for ConstStabilityParser { if let Some((ref mut stab, _)) = self.stability { stab.promotable = true; } else { - cx.dcx() - .emit_err(session_diagnostics::RustcPromotablePairing { span: cx.target_span }); + cx.dcx().emit_err(diagnostics::RustcPromotablePairing { span: cx.target_span }); } } @@ -323,10 +320,8 @@ pub(crate) fn parse_stability( let feature = match feature { Some(feature) if rustc_lexer::is_ident(feature.as_str()) => Ok(feature), - Some(_bad_feature) => { - Err(cx.emit_err(session_diagnostics::NonIdentFeature { span: cx.attr_span })) - } - None => Err(cx.emit_err(session_diagnostics::MissingFeature { span: cx.attr_span })), + Some(_bad_feature) => Err(cx.emit_err(diagnostics::NonIdentFeature { span: cx.attr_span })), + None => Err(cx.emit_err(diagnostics::MissingFeature { span: cx.attr_span })), }; let since = if let Some(since) = since { @@ -335,11 +330,11 @@ pub(crate) fn parse_stability( } else if let Some(version) = parse_version(since) { StableSince::Version(version) } else { - let err = cx.emit_err(session_diagnostics::InvalidSince { span: cx.attr_span }); + let err = cx.emit_err(diagnostics::InvalidSince { span: cx.attr_span }); StableSince::Err(err) } } else { - let err = cx.emit_err(session_diagnostics::MissingSince { span: cx.attr_span }); + let err = cx.emit_err(diagnostics::MissingSince { span: cx.attr_span }); StableSince::Err(err) }; @@ -391,15 +386,13 @@ pub(crate) fn parse_unstability( issue_str => match issue_str.parse::>() { Ok(num) => Some(num), Err(err) => { - cx.emit_err( - session_diagnostics::InvalidIssueString { - span: param.span(), - cause: session_diagnostics::InvalidIssueStringCause::from_int_error_kind( - param.args().as_name_value().unwrap().value_span, - err.kind(), - ), - }, - ); + cx.emit_err(diagnostics::InvalidIssueString { + span: param.span(), + cause: diagnostics::InvalidIssueStringCause::from_int_error_kind( + param.args().as_name_value().unwrap().value_span, + err.kind(), + ), + }); return None; } }, @@ -423,21 +416,18 @@ pub(crate) fn parse_unstability( let feature = match feature { Some(feature) if rustc_lexer::is_ident(feature.as_str()) => Ok(feature), - Some(_bad_feature) => { - Err(cx.emit_err(session_diagnostics::NonIdentFeature { span: cx.attr_span })) - } - None => Err(cx.emit_err(session_diagnostics::MissingFeature { span: cx.attr_span })), + Some(_bad_feature) => Err(cx.emit_err(diagnostics::NonIdentFeature { span: cx.attr_span })), + None => Err(cx.emit_err(diagnostics::MissingFeature { span: cx.attr_span })), }; - let issue = - issue.ok_or_else(|| cx.emit_err(session_diagnostics::MissingIssue { span: cx.attr_span })); + let issue = issue.ok_or_else(|| cx.emit_err(diagnostics::MissingIssue { span: cx.attr_span })); match (feature, issue) { (Ok(feature), Ok(_)) => { // Stable *language* features shouldn't be used as unstable library features. // (Not doing this for stable library features is checked by tidy.) if ACCEPTED_LANG_FEATURES.iter().any(|f| f.name == feature) { - cx.emit_err(session_diagnostics::UnstableAttrForAlreadyStableFeature { + cx.emit_err(diagnostics::UnstableAttrForAlreadyStableFeature { attr_span: cx.attr_span, item_span: cx.target_span, }); @@ -526,7 +516,7 @@ impl CombineAttributeParser for UnstableRemovedParser { }; let Some(version) = parse_version(since) else { - cx.emit_err(session_diagnostics::InvalidSince { span: cx.attr_span }); + cx.emit_err(diagnostics::InvalidSince { span: cx.attr_span }); return None; }; diff --git a/compiler/rustc_attr_parsing/src/attributes/util.rs b/compiler/rustc_attr_parsing/src/attributes/util.rs index 7969d1bb9ce2c..b6cc68ffc04fe 100644 --- a/compiler/rustc_attr_parsing/src/attributes/util.rs +++ b/compiler/rustc_attr_parsing/src/attributes/util.rs @@ -7,8 +7,8 @@ use rustc_hir::attrs::RustcVersion; use rustc_span::Symbol; use crate::context::AcceptContext; +use crate::diagnostics::LimitInvalid; use crate::parser::{ArgParser, NameValueParser}; -use crate::session_diagnostics::LimitInvalid; /// Parse a rustc version number written inside string literal in an attribute, /// like appears in `since = "1.0.0"`. Suffixes like "-dev" and "-nightly" are diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index 55732edfbd166..72673214b42d9 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -66,14 +66,14 @@ use crate::attributes::traits::*; use crate::attributes::transparency::*; use crate::attributes::unroll::*; use crate::attributes::{AttributeParser as _, AttributeSafety, Combine, Single, WithoutArgs}; +use crate::diagnostics::{ + AttributeParseError, AttributeParseErrorReason, AttributeParseErrorSuggestions, + ParsedDescription, UnusedDuplicate, +}; use crate::parser::{ ArgParser, MetaItemListParser, MetaItemOrLitParser, MetaItemParser, NameValueParser, RefPathParser, }; -use crate::session_diagnostics::{ - AttributeParseError, AttributeParseErrorReason, AttributeParseErrorSuggestions, - ParsedDescription, UnusedDuplicate, -}; use crate::target_checking::AllowedTargets; use crate::{AttributeParser, AttributeTemplate, EmitAttribute}; diff --git a/compiler/rustc_attr_parsing/src/diagnostics.rs b/compiler/rustc_attr_parsing/src/diagnostics.rs index 1e76ab44826a9..48128b109194c 100644 --- a/compiler/rustc_attr_parsing/src/diagnostics.rs +++ b/compiler/rustc_attr_parsing/src/diagnostics.rs @@ -1,7 +1,18 @@ -use rustc_errors::{Applicability, DiagArgValue, E0264, MultiSpan}; +use std::num::IntErrorKind; + +use rustc_errors::codes::*; +use rustc_errors::{ + Applicability, Diag, DiagArgValue, DiagCtxtHandle, Diagnostic, E0264, EmissionGuarantee, Level, + MultiSpan, +}; use rustc_hir::AttrPath; +use rustc_hir::attrs::{MirDialect, MirPhase}; use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_span::{Ident, Span, Symbol}; +use rustc_target::spec::TargetTuple; + +use crate::AttributeTemplate; +use crate::context::Suggestion; #[derive(Diagnostic)] #[diag("`{$name}` attribute cannot be used at crate level")] @@ -73,7 +84,7 @@ pub(crate) struct UnsafeAttrOutsideUnsafeLint { #[label("usage of unsafe attribute")] pub span: Span, #[subdiagnostic] - pub suggestion: Option, + pub suggestion: Option, } #[derive(Diagnostic)] @@ -877,3 +888,1151 @@ pub(crate) struct UnstableDiagnosticAttribute { pub nightly_build: bool, pub feature: Symbol, } + +#[derive(Diagnostic)] +#[diag("`#[rustc_force_inline]` and `#[inline]` cannot be used together")] +pub(crate) struct InlineForceInlineConflict { + #[primary_span] + pub force_inline_span: Span, + #[label("the inline attribute is specified here")] + pub inline_span: Span, +} + +#[derive(Diagnostic)] +#[diag("`#[ffi_const]` function cannot be `#[ffi_pure]`", code = E0757)] +pub(crate) struct BothFfiConstAndPure { + #[primary_span] + pub attr_span: Span, +} + +#[derive(Diagnostic)] +#[diag("attribute should be applied to `#[repr(transparent)]` types")] +pub(crate) struct RustcPubTransparent { + #[primary_span] + pub attr_span: Span, + #[label("not a `#[repr(transparent)]` type")] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag("attribute should be applied to a macro")] +pub(crate) struct MacroOnlyAttribute { + #[primary_span] + pub attr_span: Span, + #[label("not a macro")] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag("{$attr_str} attribute cannot have empty value")] +pub(crate) struct DocAliasEmpty<'a> { + #[primary_span] + pub span: Span, + pub attr_str: &'a str, +} + +#[derive(Diagnostic)] +#[diag("{$char_} character isn't allowed in {$attr_str}")] +pub(crate) struct DocAliasBadChar<'a> { + #[primary_span] + pub span: Span, + pub attr_str: &'a str, + pub char_: char, +} + +#[derive(Diagnostic)] +#[diag("{$attr_str} cannot start or end with ' '")] +pub(crate) struct DocAliasStartEnd<'a> { + #[primary_span] + pub span: Span, + pub attr_str: &'a str, +} + +#[derive(Diagnostic)] +#[diag("`#[{$name})]` is missing a `{$field}` argument")] +pub(crate) struct CguFieldsMissing<'a> { + #[primary_span] + pub span: Span, + pub name: &'a AttrPath, + pub field: Symbol, +} + +#[derive(Diagnostic)] +#[diag("`#![doc({$attr_name} = \"...\")]` isn't allowed as a crate-level attribute")] +pub(crate) struct DocAttrNotCrateLevel { + #[primary_span] + pub span: Span, + pub attr_name: Symbol, +} + +#[derive(Diagnostic)] +#[diag("nonexistent keyword `{$keyword}` used in `#[doc(keyword = \"...\")]`")] +#[help("only existing keywords are allowed in core/std")] +pub(crate) struct DocKeywordNotKeyword { + #[primary_span] + pub span: Span, + pub keyword: Symbol, +} + +#[derive(Diagnostic)] +#[diag("nonexistent builtin attribute `{$attribute}` used in `#[doc(attribute = \"...\")]`")] +#[help("only existing builtin attributes are allowed in core/std")] +pub(crate) struct DocAttributeNotAttribute { + #[primary_span] + pub span: Span, + pub attribute: Symbol, +} + +#[derive(Diagnostic)] +#[diag( + "`#[target_feature]` cannot be applied to a {$kind -> + [panic_handler] `#[panic_handler]` + *[other] lang item + } function" +)] +pub(crate) struct TargetFeatureOnLangItem { + #[primary_span] + pub attr_span: Span, + pub kind: Symbol, + #[label( + "{$kind -> + [panic_handler] `#[panic_handler]` + *[other] lang item + } function is not allowed to have `#[target_feature]`" + )] + pub item_span: Span, +} + +#[derive(Diagnostic)] +#[diag( + "{$name -> + [panic_impl] `#[panic_handler]` + *[other] `{$name}` lang item +} function is not allowed to have `#[track_caller]`" +)] +pub(crate) struct TrackCallerOnLangItem { + #[primary_span] + pub attr_span: Span, + pub name: Symbol, + #[label( + "{$name -> + [panic_impl] `#[panic_handler]` + *[other] `{$name}` lang item + } function is not allowed to have `#[track_caller]`" + )] + pub sig_span: Span, +} + +#[derive(Diagnostic)] +#[diag("missing 'since'", code = E0542)] +pub(crate) struct MissingSince { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag("missing 'note'", code = E0543)] +pub(crate) struct MissingNote { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag("multiple stability levels", code = E0544)] +pub(crate) struct MultipleStabilityLevels { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag("`issue` must be a non-zero numeric string or \"none\"", code = E0545)] +pub(crate) struct InvalidIssueString { + #[primary_span] + pub span: Span, + + #[subdiagnostic] + pub cause: Option, +} + +// The error kinds of `IntErrorKind` are duplicated here in order to allow the messages to be +// translatable. +#[derive(Subdiagnostic)] +pub(crate) enum InvalidIssueStringCause { + #[label("`issue` must not be \"0\", use \"none\" instead")] + MustNotBeZero { + #[primary_span] + span: Span, + }, + + #[label("cannot parse integer from empty string")] + Empty { + #[primary_span] + span: Span, + }, + + #[label("invalid digit found in string")] + InvalidDigit { + #[primary_span] + span: Span, + }, + + #[label("number too large to fit in target type")] + PosOverflow { + #[primary_span] + span: Span, + }, + + #[label("number too small to fit in target type")] + NegOverflow { + #[primary_span] + span: Span, + }, +} + +impl InvalidIssueStringCause { + pub(crate) fn from_int_error_kind(span: Span, kind: &IntErrorKind) -> Option { + match kind { + IntErrorKind::Empty => Some(Self::Empty { span }), + IntErrorKind::InvalidDigit => Some(Self::InvalidDigit { span }), + IntErrorKind::PosOverflow => Some(Self::PosOverflow { span }), + IntErrorKind::NegOverflow => Some(Self::NegOverflow { span }), + IntErrorKind::Zero => Some(Self::MustNotBeZero { span }), + _ => None, + } + } +} + +#[derive(Diagnostic)] +#[diag("missing 'feature'", code = E0546)] +pub(crate) struct MissingFeature { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag("'feature' is not an identifier", code = E0546)] +pub(crate) struct NonIdentFeature { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag("missing 'issue'", code = E0547)] +pub(crate) struct MissingIssue { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag("`rustc_promotable` attribute must be paired with either a `rustc_const_unstable` or a `rustc_const_stable` attribute", code = E0717)] +pub(crate) struct RustcPromotablePairing { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag("`rustc_allowed_through_unstable_modules` attribute must be paired with a `stable` attribute", code = E0789)] +pub(crate) struct RustcAllowedUnstablePairing { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag("suggestions on deprecated items are unstable")] +pub(crate) struct DeprecatedItemSuggestion { + #[primary_span] + pub span: Span, + + #[help("add `#![feature(deprecated_suggestion)]` to the crate root")] + pub is_nightly: bool, + + #[note("see #94785 for more details")] + pub details: (), +} + +#[derive(Diagnostic)] +#[diag("expected single version literal")] +pub(crate) struct ExpectedSingleVersionLiteral { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag("expected a version literal")] +pub(crate) struct ExpectedVersionLiteral { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag("`{$name}` expects a list of feature names")] +pub(crate) struct ExpectsFeatureList { + #[primary_span] + pub span: Span, + + pub name: String, +} + +#[derive(Diagnostic)] +#[diag("`{$name}` expects feature names")] +pub(crate) struct ExpectsFeatures { + #[primary_span] + pub span: Span, + + pub name: String, +} + +#[derive(Diagnostic)] +#[diag("'since' must be a Rust version number, such as \"1.31.0\"")] +pub(crate) struct InvalidSince { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag("unknown version literal format, assuming it refers to a future version")] +pub(crate) struct UnknownVersionLiteral { + #[primary_span] + pub span: Span, +} + +// FIXME(jdonszelmann) duplicated from `rustc_passes`, remove once `check_attr` is integrated. +#[derive(Diagnostic)] +#[diag("multiple `{$name}` attributes")] +pub(crate) struct UnusedMultiple { + #[primary_span] + #[suggestion("remove this attribute", code = "", applicability = "machine-applicable")] + pub this: Span, + #[note("attribute also specified here")] + pub other: Span, + pub name: Symbol, +} + +#[derive(Diagnostic)] +#[diag("`export_name` may not be empty")] +pub(crate) struct EmptyExportName { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag("`section` may not be empty")] +pub(crate) struct EmptySection { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag("`export_name` may not contain null characters", code = E0648)] +pub(crate) struct NullOnExport { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag("`link_section` may not contain null characters", code = E0648)] +pub(crate) struct NullOnLinkSection { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag("link name may not contain null characters", code = E0648)] +pub(crate) struct NullOnLinkName { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag("`objc::class!` may not contain null characters")] +pub(crate) struct NullOnObjcClass { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag("`objc::selector!` may not contain null characters")] +pub(crate) struct NullOnObjcSelector { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag("`section` may not contain null characters", code = E0648)] +pub(crate) struct NullOnSection { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag("`objc::class!` expected a string literal")] +pub(crate) struct ObjcClassExpectedStringLiteral { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag("`objc::selector!` expected a string literal")] +pub(crate) struct ObjcSelectorExpectedStringLiteral { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag("expected at least one confusable name")] +pub(crate) struct EmptyConfusables { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[help("the `{$name}{$attribute_args}` attribute can {$only}be applied to {$applied}")] +#[diag("the `{$name}{$attribute_args}` attribute cannot be used on {$target}")] +pub(crate) struct InvalidTarget { + #[primary_span] + pub span: Span, + #[suggestion( + "remove the attribute", + code = "", + applicability = "machine-applicable", + style = "tool-only" + )] + pub attr_span: Span, + pub name: AttrPath, + pub target: &'static str, + pub applied: DiagArgValue, + pub only: &'static str, + pub attribute_args: String, + #[subdiagnostic] + pub help: Option, + #[warning( + "this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!" + )] + pub previously_accepted: bool, + #[note( + "placing this attribute on a macro invocation does nothing even if the macro expands to what would be a valid target for the attribute" + )] + pub on_macro_call: bool, +} + +#[derive(Subdiagnostic)] +pub(crate) enum InvalidTargetHelp { + #[multipart_suggestion( + "did you mean to use `#[export_name]`?", + applicability = "maybe-incorrect" + )] + UseExportName { + #[suggestion_part(code = "unsafe(")] + unsafe_open: Option, + #[suggestion_part(code = "export_name")] + name: Span, + #[suggestion_part(code = ")")] + unsafe_close: Option, + }, + #[help("use `#[rustc_align(...)]` instead")] + UseRustcAlign, + #[help("use `#[rustc_align_static(...)]` instead")] + UseRustcAlignStatic, +} + +#[derive(Diagnostic)] +#[diag("invalid alignment value: {$error_part}", code = E0589)] +pub(crate) struct InvalidAlignmentValue { + #[primary_span] + pub span: Span, + pub error_part: String, +} + +#[derive(Diagnostic)] +#[diag("item annotated with `#[unstable_feature_bound]` should not be stable")] +#[help( + "if this item is meant to be stable, do not use any functions annotated with `#[unstable_feature_bound]`. Otherwise, mark this item as unstable with `#[unstable]`" +)] +pub(crate) struct UnstableFeatureBoundIncompatibleStability { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag("attribute incompatible with `#[unsafe(naked)]`", code = E0736)] +pub(crate) struct NakedFunctionIncompatibleAttribute { + #[primary_span] + #[label("the `{$attr}` attribute is incompatible with `#[unsafe(naked)]`")] + pub span: Span, + #[label("function marked with `#[unsafe(naked)]` here")] + pub naked_span: Span, + pub attr: String, +} + +#[derive(Diagnostic)] +#[diag("ordinal value in `link_ordinal` is too large: `{$ordinal}`")] +#[note("the value may not exceed `u16::MAX`")] +pub(crate) struct LinkOrdinalOutOfRange { + #[primary_span] + pub span: Span, + pub ordinal: u128, +} + +#[derive(Diagnostic)] +#[diag("element count in `rustc_scalable_vector` is too large: `{$n}`")] +#[note("the value may not exceed `u16::MAX`")] +pub(crate) struct RustcScalableVectorCountOutOfRange { + #[primary_span] + pub span: Span, + pub n: u128, +} + +#[derive(Diagnostic)] +#[diag("attribute requires {$opt} to be enabled")] +pub(crate) struct AttributeRequiresOpt { + #[primary_span] + pub span: Span, + pub opt: &'static str, +} + +pub(crate) enum AttributeParseErrorReason<'a> { + ExpectedNoArgs, + ExpectedStringLiteral { + byte_string: Option, + }, + ExpectedFilenameLiteral, + ExpectedIntegerLiteral, + ExpectedIntegerLiteralInRange { + lower_bound: isize, + upper_bound: isize, + }, + ExpectedAtLeastOneArgument, + ExpectedArgument, + ExpectedSingleArgument, + ExpectedList, + ExpectedListOrNoArgs, + ExpectedListWithNumArgsOrMore { + args: usize, + }, + ExpectedNameValueOrNoArgs, + ExpectedNonEmptyStringLiteral, + ExpectedNotLiteral, + ExpectedNameValue(Option), + MissingNameValue(Symbol), + DuplicateKey(Symbol), + ExpectedSpecificArgument { + possibilities: &'a [Symbol], + strings: bool, + /// Should we tell the user to write a list when they didn't? + list: bool, + }, + ExpectedIdentifier, +} + +/// A description of a thing that can be parsed using an attribute parser. +#[derive(Copy, Clone)] +pub enum ParsedDescription { + /// Used when parsing attributes. + Attribute, + /// Used when parsing some macros, such as the `cfg!()` macro. + Macro, +} + +pub(crate) struct AttributeParseError<'a> { + pub(crate) span: Span, + pub(crate) inner_span: Span, + pub(crate) template: AttributeTemplate, + pub(crate) path: AttrPath, + pub(crate) description: ParsedDescription, + pub(crate) reason: AttributeParseErrorReason<'a>, + pub(crate) suggestions: AttributeParseErrorSuggestions, +} + +pub(crate) enum AttributeParseErrorSuggestions { + CreatedByTemplate(Vec), + CreatedByParser(Vec), +} + +impl<'a> AttributeParseError<'a> { + fn render_expected_specific_argument( + &self, + diag: &mut Diag<'_, G>, + possibilities: &[Symbol], + strings: bool, + ) where + G: EmissionGuarantee, + { + let quote = if strings { '"' } else { '`' }; + match possibilities { + &[] => {} + &[x] => { + diag.span_label( + self.span, + format!("the only valid argument here is {quote}{x}{quote}"), + ); + } + [first, second] => { + diag.span_label( + self.span, + format!("valid arguments are {quote}{first}{quote} or {quote}{second}{quote}"), + ); + } + [first @ .., second_to_last, last] => { + let mut res = String::new(); + for i in first { + res.push_str(&format!("{quote}{i}{quote}, ")); + } + res.push_str(&format!("{quote}{second_to_last}{quote} or {quote}{last}{quote}")); + + diag.span_label(self.span, format!("valid arguments are {res}")); + } + } + } + + fn render_expected_specific_argument_list( + &self, + diag: &mut Diag<'_, G>, + possibilities: &[Symbol], + strings: bool, + ) where + G: EmissionGuarantee, + { + let description = self.description(); + + let quote = if strings { '"' } else { '`' }; + match possibilities { + &[] => {} + &[x] => { + diag.span_label( + self.span, + format!( + "this {description} is only valid with {quote}{x}{quote} as an argument" + ), + ); + } + [first, second] => { + diag.span_label(self.span, format!("this {description} is only valid with either {quote}{first}{quote} or {quote}{second}{quote} as an argument")); + } + [first @ .., second_to_last, last] => { + let mut res = String::new(); + for i in first { + res.push_str(&format!("{quote}{i}{quote}, ")); + } + res.push_str(&format!("{quote}{second_to_last}{quote} or {quote}{last}{quote}")); + + diag.span_label(self.span, format!("this {description} is only valid with one of the following arguments: {res}")); + } + } + } + + fn render_suggestions(&self, diag: &mut Diag<'_, G>) + where + G: EmissionGuarantee, + { + let description = self.description(); + + match &self.suggestions { + AttributeParseErrorSuggestions::CreatedByTemplate(suggestions) => { + diag.span_suggestions( + self.inner_span, + if suggestions.len() == 1 { + "must be of the form".to_string() + } else { + format!( + "try changing it to one of the following valid forms of the {description}" + ) + }, + suggestions.iter().cloned(), + Applicability::HasPlaceholders, + ); + } + + AttributeParseErrorSuggestions::CreatedByParser(suggestions) => { + for Suggestion { msg, sp, code } in suggestions { + diag.span_suggestion_verbose( + *sp, + msg.clone(), + code.clone(), + Applicability::MaybeIncorrect, + ); + } + } + } + } + + fn description(&self) -> &'static str { + match self.description { + ParsedDescription::Attribute => "attribute", + ParsedDescription::Macro => "macro", + } + } +} + +impl AttributeParseErrorSuggestions { + fn len(&self) -> usize { + match self { + AttributeParseErrorSuggestions::CreatedByTemplate(items) => items.len(), + AttributeParseErrorSuggestions::CreatedByParser(items) => items.len(), + } + } +} + +impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for AttributeParseError<'_> { + fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, G> { + let name = self.path.to_string(); + + let description = self.description(); + + let mut diag = Diag::new(dcx, level, format!("malformed `{name}` {description} input")); + diag.span(self.inner_span); + diag.code(E0539); + match &self.reason { + AttributeParseErrorReason::ExpectedStringLiteral { byte_string } => { + if let Some(start_point_span) = byte_string { + diag.span_suggestion( + *start_point_span, + "consider removing the prefix", + "", + Applicability::MaybeIncorrect, + ); + diag.note("expected a normal string literal, not a byte string literal"); + + // Avoid emitting an "attribute must be of the form" suggestion, as the + // attribute is likely to be well-formed already. + return diag; + } + diag.span_label(self.span, "expected a string literal here"); + } + AttributeParseErrorReason::ExpectedFilenameLiteral => { + diag.span_label(self.span, "expected a filename string literal here"); + } + AttributeParseErrorReason::ExpectedIntegerLiteral => { + diag.span_label(self.span, "expected an integer literal here"); + } + AttributeParseErrorReason::ExpectedIntegerLiteralInRange { + lower_bound, + upper_bound, + } => { + diag.span_label( + self.span, + format!( + "expected an integer literal in the range of {lower_bound}..={upper_bound}" + ), + ); + } + AttributeParseErrorReason::ExpectedSingleArgument => { + diag.span_label(self.span, "expected a single argument here"); + diag.code(E0805); + } + AttributeParseErrorReason::ExpectedArgument => { + diag.span_label(self.span, "expected an argument here"); + diag.code(E0805); + } + AttributeParseErrorReason::ExpectedAtLeastOneArgument => { + diag.span_label(self.span, "expected at least 1 argument here"); + } + AttributeParseErrorReason::ExpectedList => { + diag.span_label(self.span, "expected this to be a list"); + } + AttributeParseErrorReason::ExpectedListOrNoArgs => { + diag.span_label(self.span, "expected a list or no arguments here"); + } + AttributeParseErrorReason::ExpectedListWithNumArgsOrMore { args } => { + diag.span_label(self.span, format!("expected {args} or more items")); + } + AttributeParseErrorReason::ExpectedNameValueOrNoArgs => { + diag.span_label(self.span, "didn't expect a list here"); + } + AttributeParseErrorReason::ExpectedNonEmptyStringLiteral => { + diag.span_label(self.span, "string is not allowed to be empty"); + } + AttributeParseErrorReason::DuplicateKey(key) => { + diag.span_label(self.span, format!("found `{key}` used as a key more than once")); + diag.code(E0538); + } + AttributeParseErrorReason::ExpectedNotLiteral => { + diag.span_label(self.span, "didn't expect a literal here"); + diag.code(E0565); + } + AttributeParseErrorReason::ExpectedNoArgs => { + diag.span_label(self.span, "didn't expect any arguments here"); + diag.code(E0565); + } + AttributeParseErrorReason::ExpectedNameValue(None) => { + // If the span is the entire attribute inner, the suggestion we add below this + // match already contains enough information. + if self.span != self.inner_span { + diag.span_label(self.span, "expected this to be of the form `... = \"...\"`"); + } + } + AttributeParseErrorReason::ExpectedNameValue(Some(name)) => { + diag.span_label( + self.span, + format!("expected this to be of the form `{name} = \"...\"`"), + ); + } + AttributeParseErrorReason::MissingNameValue(name) => { + diag.span_label(self.span, format!("missing argument `{name} = \"...\"`")); + } + AttributeParseErrorReason::ExpectedSpecificArgument { + possibilities, + strings, + list: false, + } => { + self.render_expected_specific_argument(&mut diag, possibilities, *strings); + } + AttributeParseErrorReason::ExpectedSpecificArgument { + possibilities, + strings, + list: true, + } => { + self.render_expected_specific_argument_list(&mut diag, possibilities, *strings); + } + AttributeParseErrorReason::ExpectedIdentifier => { + diag.span_label(self.span, "expected a valid identifier here"); + diag.code(E0565); + } + } + + if let Some(link) = self.template.docs { + diag.note(format!("for more information, visit <{link}>")); + } + + if self.suggestions.len() < 4 { + self.render_suggestions(&mut diag); + } + + diag + } +} + +#[derive(Diagnostic)] +#[diag("`{$name}` is not an unsafe attribute")] +#[note("extraneous unsafe is not allowed in attributes")] +pub(crate) struct InvalidAttrUnsafe { + #[primary_span] + #[label("this is not an unsafe attribute")] + pub span: Span, + pub name: AttrPath, +} + +#[derive(Diagnostic)] +#[diag("unsafe attribute used without unsafe")] +pub(crate) struct UnsafeAttrOutsideUnsafe { + #[primary_span] + #[label("usage of unsafe attribute")] + pub span: Span, + #[subdiagnostic] + pub suggestion: Option, +} + +#[derive(Subdiagnostic)] +#[multipart_suggestion("wrap the attribute in `unsafe(...)`", applicability = "machine-applicable")] +pub(crate) struct UnsafeAttrOutsideUnsafeSuggestion { + #[suggestion_part(code = "unsafe(")] + pub left: Span, + #[suggestion_part(code = ")")] + pub right: Span, +} + +#[derive(Diagnostic)] +#[diag("wrong meta list delimiters")] +pub(crate) struct MetaBadDelim { + #[primary_span] + pub span: Span, + #[subdiagnostic] + pub sugg: MetaBadDelimSugg, +} + +#[derive(Subdiagnostic)] +#[multipart_suggestion( + "the delimiters should be `(` and `)`", + applicability = "machine-applicable" +)] +pub(crate) struct MetaBadDelimSugg { + #[suggestion_part(code = "(")] + pub open: Span, + #[suggestion_part(code = ")")] + pub close: Span, +} + +#[derive(Diagnostic)] +#[diag("expected a literal (`1u8`, `1.0f32`, `\"string\"`, etc.) here, found {$descr}")] +pub(crate) struct InvalidMetaItem { + #[primary_span] + pub span: Span, + pub descr: String, + #[subdiagnostic] + pub quote_ident_sugg: Option, + #[subdiagnostic] + pub remove_neg_sugg: Option, + #[label("{$descr}s are not allowed here")] + pub label: Option, +} + +#[derive(Subdiagnostic)] +#[multipart_suggestion( + "surround the identifier with quotation marks to make it into a string literal", + applicability = "machine-applicable" +)] +pub(crate) struct InvalidMetaItemQuoteIdentSugg { + #[suggestion_part(code = "\"")] + pub before: Span, + #[suggestion_part(code = "\"")] + pub after: Span, +} + +#[derive(Subdiagnostic)] +#[multipart_suggestion( + "negative numbers are not literals, try removing the `-` sign", + applicability = "machine-applicable" +)] +pub(crate) struct InvalidMetaItemRemoveNegSugg { + #[suggestion_part(code = "")] + pub negative_sign: Span, +} + +#[derive(Diagnostic)] +#[diag("suffixed literals are not allowed in attributes")] +#[help( + "instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), use an unsuffixed version (`1`, `1.0`, etc.)" +)] +pub(crate) struct SuffixedLiteralInAttribute { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag("link name must not be empty", code = E0454)] +pub(crate) struct EmptyLinkName { + #[primary_span] + #[label("empty link name")] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag("link kind `framework` is only supported on Apple targets", code = E0455)] +pub(crate) struct LinkFrameworkApple { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag("`wasm_import_module` is incompatible with other arguments in `#[link]` attributes")] +pub(crate) struct IncompatibleWasmLink { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag("`#[link]` attribute requires a `name = \"string\"` argument", code = E0459)] +pub(crate) struct LinkRequiresName { + #[primary_span] + #[label("missing `name` argument")] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag("link kind `raw-dylib` is only supported on Windows targets", code = E0455)] +pub(crate) struct RawDylibOnlyWindows { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag( + "invalid linking modifier syntax, expected '+' or '-' prefix before one of: bundle, verbatim, whole-archive, as-needed, export-symbols" +)] +pub(crate) struct InvalidLinkModifier { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag("multiple `{$modifier}` modifiers in a single `modifiers` argument")] +pub(crate) struct MultipleModifiers { + #[primary_span] + pub span: Span, + pub modifier: Symbol, +} + +#[derive(Diagnostic)] +#[diag("import name type is only supported on x86")] +pub(crate) struct ImportNameTypeX86 { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag("linking modifier `bundle` is only compatible with `static` linking kind")] +pub(crate) struct BundleNeedsStatic { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag("linking modifier `export-symbols` is only compatible with `static` linking kind")] +pub(crate) struct ExportSymbolsNeedsStatic { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag("linking modifier `whole-archive` is only compatible with `static` linking kind")] +pub(crate) struct WholeArchiveNeedsStatic { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag( + "linking modifier `as-needed` is only compatible with `dylib`, `framework` and `raw-dylib` linking kinds" +)] +pub(crate) struct AsNeededCompatibility { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag("import name type can only be used with link kind `raw-dylib`")] +pub(crate) struct ImportNameTypeRaw { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag("`limit` must be a non-negative integer")] +pub(crate) struct LimitInvalid<'a> { + #[primary_span] + pub span: Span, + #[label("{$error_str}")] + pub value_span: Span, + pub error_str: &'a str, +} + +#[derive(Diagnostic)] +#[diag("wrong `cfg_attr` delimiters")] +pub(crate) struct CfgAttrBadDelim { + #[primary_span] + pub span: Span, + #[subdiagnostic] + pub sugg: MetaBadDelimSugg, +} + +#[derive(Diagnostic)] +#[diag( + "doc alias attribute expects a string `#[doc(alias = \"a\")]` or a list of strings `#[doc(alias(\"a\", \"b\"))]`" +)] +pub(crate) struct DocAliasMalformed { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag("definition of an unknown lang item: `{$name}`", code = E0522)] +pub(crate) struct UnknownLangItem { + #[primary_span] + #[label("definition of unknown lang item `{$name}`")] + pub span: Span, + pub name: Symbol, +} + +#[derive(Diagnostic)] +#[diag("target `{$current_target}` does not support `#[instruction_set({$instruction_set}::*)]`")] +pub(crate) struct UnsupportedInstructionSet<'a> { + #[primary_span] + pub span: Span, + pub instruction_set: Symbol, + pub current_target: &'a TargetTuple, +} + +#[derive(Diagnostic)] +#[diag("`dialect` key required")] +pub(crate) struct CustomMirPhaseRequiresDialect { + #[primary_span] + pub attr_span: Span, + #[label("`phase` argument requires a `dialect` argument")] + pub phase_span: Span, +} + +#[derive(Diagnostic)] +#[diag("the {$dialect} dialect is not compatible with the {$phase} phase")] +pub(crate) struct CustomMirIncompatibleDialectAndPhase { + pub dialect: MirDialect, + pub phase: MirPhase, + #[primary_span] + pub attr_span: Span, + #[label("this dialect...")] + pub dialect_span: Span, + #[label("... is not compatible with this phase")] + pub phase_span: Span, +} + +#[derive(Diagnostic)] +#[diag("can't mark as unstable using an already stable feature")] +pub(crate) struct UnstableAttrForAlreadyStableFeature { + #[primary_span] + #[label("this feature is already stable")] + #[help("consider removing the attribute")] + pub attr_span: Span, + #[label("the stability attribute annotates this item")] + pub item_span: Span, +} + +#[derive(Diagnostic)] +#[diag("invalid Mach-O section specifier")] +pub(crate) struct InvalidMachoSection { + #[primary_span] + #[label("not a valid Mach-O section specifier")] + pub name_span: Span, + #[subdiagnostic] + pub reason: InvalidMachoSectionReason, +} + +#[derive(Subdiagnostic)] +pub(crate) enum InvalidMachoSectionReason { + #[note("a Mach-O section specifier requires a segment and a section, separated by a comma")] + #[help("an example of a valid Mach-O section specifier is `__TEXT,__cstring`")] + MissingSection, + #[note("section name `{$section}` is longer than 16 bytes")] + SectionTooLong { section: String }, +} + +#[derive(Diagnostic)] +#[diag("`#[sanitize({$field} = ...)]` attribute cannot be used on statics")] +#[help("`#[sanitize]` can be used on statics if only the address is sanitized")] +pub(crate) struct SanitizeInvalidStatic { + #[primary_span] + pub span: Span, + pub field: &'static str, +} + +#[derive(Diagnostic)] +#[diag("attribute items not separated with `,`")] +pub(crate) struct ExpectedComma { + #[primary_span] + #[suggestion( + "try adding `,` here", + code = ",", + applicability = "maybe-incorrect", + style = "short" + )] + pub span: Span, + #[subdiagnostic] + pub additional: Vec, +} + +#[derive(Subdiagnostic)] +#[suggestion("try adding `,` here", code = ",", applicability = "maybe-incorrect", style = "short")] +pub(crate) struct AdditionalCommaSuggestion { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag("unused attribute")] +pub(crate) struct UnusedDuplicate { + #[suggestion("remove this attribute", code = "", applicability = "machine-applicable")] + pub this: Span, + #[note("attribute also specified here")] + pub other: Span, + #[warning( + "this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!" + )] + pub warning: bool, +} diff --git a/compiler/rustc_attr_parsing/src/interface.rs b/compiler/rustc_attr_parsing/src/interface.rs index 73108e42d5ab5..492cf1e268ac6 100644 --- a/compiler/rustc_attr_parsing/src/interface.rs +++ b/compiler/rustc_attr_parsing/src/interface.rs @@ -21,8 +21,8 @@ use crate::context::{ ATTRIBUTE_PARSERS, AcceptContext, FinalizeCheckContext, FinalizeCheckFn, FinalizeContext, FinalizeFn, FinalizeOutput, SharedContext, }; +use crate::diagnostics::ParsedDescription; use crate::parser::{AllowExprMetavar, ArgParser, PathParser, RefPathParser}; -use crate::session_diagnostics::ParsedDescription; use crate::synthetic::SyntheticAttrState; use crate::{AttributeTemplate, OmitDoc, ShouldEmit}; diff --git a/compiler/rustc_attr_parsing/src/lib.rs b/compiler/rustc_attr_parsing/src/lib.rs index bcdb401bc08c3..5a1d1b8091da2 100644 --- a/compiler/rustc_attr_parsing/src/lib.rs +++ b/compiler/rustc_attr_parsing/src/lib.rs @@ -104,7 +104,6 @@ mod diagnostics; mod interface; pub mod parser; mod safety; -mod session_diagnostics; mod stability; mod synthetic; mod target_checking; @@ -118,7 +117,7 @@ pub use attributes::cfg::{ pub use attributes::cfg_select::*; pub use attributes::util::{is_builtin_attr, parse_version}; pub use context::{OmitDoc, ShouldEmit}; +pub use diagnostics::ParsedDescription; pub use interface::{AttributeParser, EmitAttribute}; pub use rustc_parse::parser::Recovery; -pub use session_diagnostics::ParsedDescription; pub use template::AttributeTemplate; diff --git a/compiler/rustc_attr_parsing/src/parser.rs b/compiler/rustc_attr_parsing/src/parser.rs index 5f1fc8ba90d5e..a1563d629d474 100644 --- a/compiler/rustc_attr_parsing/src/parser.rs +++ b/compiler/rustc_attr_parsing/src/parser.rs @@ -29,7 +29,7 @@ use rustc_span::{Ident, Span, Symbol, sym}; use thin_vec::ThinVec; use crate::ShouldEmit; -use crate::session_diagnostics::{ +use crate::diagnostics::{ AdditionalCommaSuggestion, ExpectedComma, InvalidMetaItem, InvalidMetaItemQuoteIdentSugg, InvalidMetaItemRemoveNegSugg, MetaBadDelim, MetaBadDelimSugg, SuffixedLiteralInAttribute, }; diff --git a/compiler/rustc_attr_parsing/src/safety.rs b/compiler/rustc_attr_parsing/src/safety.rs index 5b3d52c18aae1..1e0717dfd8e26 100644 --- a/compiler/rustc_attr_parsing/src/safety.rs +++ b/compiler/rustc_attr_parsing/src/safety.rs @@ -66,10 +66,10 @@ impl<'sess> AttributeParser<'sess> { } if emit_error { - self.emit_err(crate::session_diagnostics::UnsafeAttrOutsideUnsafe { + self.emit_err(crate::diagnostics::UnsafeAttrOutsideUnsafe { span: path_span, suggestion: not_from_proc_macro.then(|| { - crate::session_diagnostics::UnsafeAttrOutsideUnsafeSuggestion { + crate::diagnostics::UnsafeAttrOutsideUnsafeSuggestion { left: diag_span.shrink_to_lo(), right: diag_span.shrink_to_hi(), } @@ -85,7 +85,10 @@ impl<'sess> AttributeParser<'sess> { suggestion: not_from_proc_macro .then(|| (diag_span.shrink_to_lo(), diag_span.shrink_to_hi())) .map(|(left, right)| { - crate::session_diagnostics::UnsafeAttrOutsideUnsafeSuggestion { left, right } + crate::diagnostics::UnsafeAttrOutsideUnsafeSuggestion { + left, + right, + } }), } .into_diag(dcx, level) @@ -97,7 +100,7 @@ impl<'sess> AttributeParser<'sess> { // - Normal builtin attribute // - Writing `#[unsafe(..)]` is not permitted on normal builtin attributes (AttributeSafety::Normal, Safety::Unsafe(unsafe_span)) => { - self.emit_err(crate::session_diagnostics::InvalidAttrUnsafe { + self.emit_err(crate::diagnostics::InvalidAttrUnsafe { span: unsafe_span, name: attr_path.clone(), }); diff --git a/compiler/rustc_attr_parsing/src/session_diagnostics.rs b/compiler/rustc_attr_parsing/src/session_diagnostics.rs deleted file mode 100644 index b7c7b39bcb48b..0000000000000 --- a/compiler/rustc_attr_parsing/src/session_diagnostics.rs +++ /dev/null @@ -1,1162 +0,0 @@ -use std::num::IntErrorKind; - -use rustc_errors::codes::*; -use rustc_errors::{ - Applicability, Diag, DiagArgValue, DiagCtxtHandle, Diagnostic, EmissionGuarantee, Level, -}; -use rustc_hir::AttrPath; -use rustc_hir::attrs::{MirDialect, MirPhase}; -use rustc_macros::{Diagnostic, Subdiagnostic}; -use rustc_span::{Span, Symbol}; -use rustc_target::spec::TargetTuple; - -use crate::AttributeTemplate; -use crate::context::Suggestion; - -#[derive(Diagnostic)] -#[diag("`#[rustc_force_inline]` and `#[inline]` cannot be used together")] -pub(crate) struct InlineForceInlineConflict { - #[primary_span] - pub force_inline_span: Span, - #[label("the inline attribute is specified here")] - pub inline_span: Span, -} - -#[derive(Diagnostic)] -#[diag("`#[ffi_const]` function cannot be `#[ffi_pure]`", code = E0757)] -pub(crate) struct BothFfiConstAndPure { - #[primary_span] - pub attr_span: Span, -} - -#[derive(Diagnostic)] -#[diag("attribute should be applied to `#[repr(transparent)]` types")] -pub(crate) struct RustcPubTransparent { - #[primary_span] - pub attr_span: Span, - #[label("not a `#[repr(transparent)]` type")] - pub span: Span, -} - -#[derive(Diagnostic)] -#[diag("attribute should be applied to a macro")] -pub(crate) struct MacroOnlyAttribute { - #[primary_span] - pub attr_span: Span, - #[label("not a macro")] - pub span: Span, -} - -#[derive(Diagnostic)] -#[diag("{$attr_str} attribute cannot have empty value")] -pub(crate) struct DocAliasEmpty<'a> { - #[primary_span] - pub span: Span, - pub attr_str: &'a str, -} - -#[derive(Diagnostic)] -#[diag("{$char_} character isn't allowed in {$attr_str}")] -pub(crate) struct DocAliasBadChar<'a> { - #[primary_span] - pub span: Span, - pub attr_str: &'a str, - pub char_: char, -} - -#[derive(Diagnostic)] -#[diag("{$attr_str} cannot start or end with ' '")] -pub(crate) struct DocAliasStartEnd<'a> { - #[primary_span] - pub span: Span, - pub attr_str: &'a str, -} - -#[derive(Diagnostic)] -#[diag("`#[{$name})]` is missing a `{$field}` argument")] -pub(crate) struct CguFieldsMissing<'a> { - #[primary_span] - pub span: Span, - pub name: &'a AttrPath, - pub field: Symbol, -} - -#[derive(Diagnostic)] -#[diag("`#![doc({$attr_name} = \"...\")]` isn't allowed as a crate-level attribute")] -pub(crate) struct DocAttrNotCrateLevel { - #[primary_span] - pub span: Span, - pub attr_name: Symbol, -} - -#[derive(Diagnostic)] -#[diag("nonexistent keyword `{$keyword}` used in `#[doc(keyword = \"...\")]`")] -#[help("only existing keywords are allowed in core/std")] -pub(crate) struct DocKeywordNotKeyword { - #[primary_span] - pub span: Span, - pub keyword: Symbol, -} - -#[derive(Diagnostic)] -#[diag("nonexistent builtin attribute `{$attribute}` used in `#[doc(attribute = \"...\")]`")] -#[help("only existing builtin attributes are allowed in core/std")] -pub(crate) struct DocAttributeNotAttribute { - #[primary_span] - pub span: Span, - pub attribute: Symbol, -} - -#[derive(Diagnostic)] -#[diag( - "`#[target_feature]` cannot be applied to a {$kind -> - [panic_handler] `#[panic_handler]` - *[other] lang item - } function" -)] -pub(crate) struct TargetFeatureOnLangItem { - #[primary_span] - pub attr_span: Span, - pub kind: Symbol, - #[label( - "{$kind -> - [panic_handler] `#[panic_handler]` - *[other] lang item - } function is not allowed to have `#[target_feature]`" - )] - pub item_span: Span, -} - -#[derive(Diagnostic)] -#[diag( - "{$name -> - [panic_impl] `#[panic_handler]` - *[other] `{$name}` lang item -} function is not allowed to have `#[track_caller]`" -)] -pub(crate) struct TrackCallerOnLangItem { - #[primary_span] - pub attr_span: Span, - pub name: Symbol, - #[label( - "{$name -> - [panic_impl] `#[panic_handler]` - *[other] `{$name}` lang item - } function is not allowed to have `#[track_caller]`" - )] - pub sig_span: Span, -} - -#[derive(Diagnostic)] -#[diag("missing 'since'", code = E0542)] -pub(crate) struct MissingSince { - #[primary_span] - pub span: Span, -} - -#[derive(Diagnostic)] -#[diag("missing 'note'", code = E0543)] -pub(crate) struct MissingNote { - #[primary_span] - pub span: Span, -} - -#[derive(Diagnostic)] -#[diag("multiple stability levels", code = E0544)] -pub(crate) struct MultipleStabilityLevels { - #[primary_span] - pub span: Span, -} - -#[derive(Diagnostic)] -#[diag("`issue` must be a non-zero numeric string or \"none\"", code = E0545)] -pub(crate) struct InvalidIssueString { - #[primary_span] - pub span: Span, - - #[subdiagnostic] - pub cause: Option, -} - -// The error kinds of `IntErrorKind` are duplicated here in order to allow the messages to be -// translatable. -#[derive(Subdiagnostic)] -pub(crate) enum InvalidIssueStringCause { - #[label("`issue` must not be \"0\", use \"none\" instead")] - MustNotBeZero { - #[primary_span] - span: Span, - }, - - #[label("cannot parse integer from empty string")] - Empty { - #[primary_span] - span: Span, - }, - - #[label("invalid digit found in string")] - InvalidDigit { - #[primary_span] - span: Span, - }, - - #[label("number too large to fit in target type")] - PosOverflow { - #[primary_span] - span: Span, - }, - - #[label("number too small to fit in target type")] - NegOverflow { - #[primary_span] - span: Span, - }, -} - -impl InvalidIssueStringCause { - pub(crate) fn from_int_error_kind(span: Span, kind: &IntErrorKind) -> Option { - match kind { - IntErrorKind::Empty => Some(Self::Empty { span }), - IntErrorKind::InvalidDigit => Some(Self::InvalidDigit { span }), - IntErrorKind::PosOverflow => Some(Self::PosOverflow { span }), - IntErrorKind::NegOverflow => Some(Self::NegOverflow { span }), - IntErrorKind::Zero => Some(Self::MustNotBeZero { span }), - _ => None, - } - } -} - -#[derive(Diagnostic)] -#[diag("missing 'feature'", code = E0546)] -pub(crate) struct MissingFeature { - #[primary_span] - pub span: Span, -} - -#[derive(Diagnostic)] -#[diag("'feature' is not an identifier", code = E0546)] -pub(crate) struct NonIdentFeature { - #[primary_span] - pub span: Span, -} - -#[derive(Diagnostic)] -#[diag("missing 'issue'", code = E0547)] -pub(crate) struct MissingIssue { - #[primary_span] - pub span: Span, -} - -#[derive(Diagnostic)] -#[diag("`rustc_promotable` attribute must be paired with either a `rustc_const_unstable` or a `rustc_const_stable` attribute", code = E0717)] -pub(crate) struct RustcPromotablePairing { - #[primary_span] - pub span: Span, -} - -#[derive(Diagnostic)] -#[diag("`rustc_allowed_through_unstable_modules` attribute must be paired with a `stable` attribute", code = E0789)] -pub(crate) struct RustcAllowedUnstablePairing { - #[primary_span] - pub span: Span, -} - -#[derive(Diagnostic)] -#[diag("suggestions on deprecated items are unstable")] -pub(crate) struct DeprecatedItemSuggestion { - #[primary_span] - pub span: Span, - - #[help("add `#![feature(deprecated_suggestion)]` to the crate root")] - pub is_nightly: bool, - - #[note("see #94785 for more details")] - pub details: (), -} - -#[derive(Diagnostic)] -#[diag("expected single version literal")] -pub(crate) struct ExpectedSingleVersionLiteral { - #[primary_span] - pub span: Span, -} - -#[derive(Diagnostic)] -#[diag("expected a version literal")] -pub(crate) struct ExpectedVersionLiteral { - #[primary_span] - pub span: Span, -} - -#[derive(Diagnostic)] -#[diag("`{$name}` expects a list of feature names")] -pub(crate) struct ExpectsFeatureList { - #[primary_span] - pub span: Span, - - pub name: String, -} - -#[derive(Diagnostic)] -#[diag("`{$name}` expects feature names")] -pub(crate) struct ExpectsFeatures { - #[primary_span] - pub span: Span, - - pub name: String, -} - -#[derive(Diagnostic)] -#[diag("'since' must be a Rust version number, such as \"1.31.0\"")] -pub(crate) struct InvalidSince { - #[primary_span] - pub span: Span, -} - -#[derive(Diagnostic)] -#[diag("unknown version literal format, assuming it refers to a future version")] -pub(crate) struct UnknownVersionLiteral { - #[primary_span] - pub span: Span, -} - -// FIXME(jdonszelmann) duplicated from `rustc_passes`, remove once `check_attr` is integrated. -#[derive(Diagnostic)] -#[diag("multiple `{$name}` attributes")] -pub(crate) struct UnusedMultiple { - #[primary_span] - #[suggestion("remove this attribute", code = "", applicability = "machine-applicable")] - pub this: Span, - #[note("attribute also specified here")] - pub other: Span, - pub name: Symbol, -} - -#[derive(Diagnostic)] -#[diag("`export_name` may not be empty")] -pub(crate) struct EmptyExportName { - #[primary_span] - pub span: Span, -} - -#[derive(Diagnostic)] -#[diag("`section` may not be empty")] -pub(crate) struct EmptySection { - #[primary_span] - pub span: Span, -} - -#[derive(Diagnostic)] -#[diag("`export_name` may not contain null characters", code = E0648)] -pub(crate) struct NullOnExport { - #[primary_span] - pub span: Span, -} - -#[derive(Diagnostic)] -#[diag("`link_section` may not contain null characters", code = E0648)] -pub(crate) struct NullOnLinkSection { - #[primary_span] - pub span: Span, -} - -#[derive(Diagnostic)] -#[diag("link name may not contain null characters", code = E0648)] -pub(crate) struct NullOnLinkName { - #[primary_span] - pub span: Span, -} - -#[derive(Diagnostic)] -#[diag("`objc::class!` may not contain null characters")] -pub(crate) struct NullOnObjcClass { - #[primary_span] - pub span: Span, -} - -#[derive(Diagnostic)] -#[diag("`objc::selector!` may not contain null characters")] -pub(crate) struct NullOnObjcSelector { - #[primary_span] - pub span: Span, -} - -#[derive(Diagnostic)] -#[diag("`section` may not contain null characters", code = E0648)] -pub(crate) struct NullOnSection { - #[primary_span] - pub span: Span, -} - -#[derive(Diagnostic)] -#[diag("`objc::class!` expected a string literal")] -pub(crate) struct ObjcClassExpectedStringLiteral { - #[primary_span] - pub span: Span, -} - -#[derive(Diagnostic)] -#[diag("`objc::selector!` expected a string literal")] -pub(crate) struct ObjcSelectorExpectedStringLiteral { - #[primary_span] - pub span: Span, -} - -#[derive(Diagnostic)] -#[diag("expected at least one confusable name")] -pub(crate) struct EmptyConfusables { - #[primary_span] - pub span: Span, -} - -#[derive(Diagnostic)] -#[help("the `{$name}{$attribute_args}` attribute can {$only}be applied to {$applied}")] -#[diag("the `{$name}{$attribute_args}` attribute cannot be used on {$target}")] -pub(crate) struct InvalidTarget { - #[primary_span] - pub span: Span, - #[suggestion( - "remove the attribute", - code = "", - applicability = "machine-applicable", - style = "tool-only" - )] - pub attr_span: Span, - pub name: AttrPath, - pub target: &'static str, - pub applied: DiagArgValue, - pub only: &'static str, - pub attribute_args: String, - #[subdiagnostic] - pub help: Option, - #[warning( - "this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!" - )] - pub previously_accepted: bool, - #[note( - "placing this attribute on a macro invocation does nothing even if the macro expands to what would be a valid target for the attribute" - )] - pub on_macro_call: bool, -} - -#[derive(Subdiagnostic)] -pub(crate) enum InvalidTargetHelp { - #[multipart_suggestion( - "did you mean to use `#[export_name]`?", - applicability = "maybe-incorrect" - )] - UseExportName { - #[suggestion_part(code = "unsafe(")] - unsafe_open: Option, - #[suggestion_part(code = "export_name")] - name: Span, - #[suggestion_part(code = ")")] - unsafe_close: Option, - }, - #[help("use `#[rustc_align(...)]` instead")] - UseRustcAlign, - #[help("use `#[rustc_align_static(...)]` instead")] - UseRustcAlignStatic, -} - -#[derive(Diagnostic)] -#[diag("invalid alignment value: {$error_part}", code = E0589)] -pub(crate) struct InvalidAlignmentValue { - #[primary_span] - pub span: Span, - pub error_part: String, -} - -#[derive(Diagnostic)] -#[diag("item annotated with `#[unstable_feature_bound]` should not be stable")] -#[help( - "if this item is meant to be stable, do not use any functions annotated with `#[unstable_feature_bound]`. Otherwise, mark this item as unstable with `#[unstable]`" -)] -pub(crate) struct UnstableFeatureBoundIncompatibleStability { - #[primary_span] - pub span: Span, -} - -#[derive(Diagnostic)] -#[diag("attribute incompatible with `#[unsafe(naked)]`", code = E0736)] -pub(crate) struct NakedFunctionIncompatibleAttribute { - #[primary_span] - #[label("the `{$attr}` attribute is incompatible with `#[unsafe(naked)]`")] - pub span: Span, - #[label("function marked with `#[unsafe(naked)]` here")] - pub naked_span: Span, - pub attr: String, -} - -#[derive(Diagnostic)] -#[diag("ordinal value in `link_ordinal` is too large: `{$ordinal}`")] -#[note("the value may not exceed `u16::MAX`")] -pub(crate) struct LinkOrdinalOutOfRange { - #[primary_span] - pub span: Span, - pub ordinal: u128, -} - -#[derive(Diagnostic)] -#[diag("element count in `rustc_scalable_vector` is too large: `{$n}`")] -#[note("the value may not exceed `u16::MAX`")] -pub(crate) struct RustcScalableVectorCountOutOfRange { - #[primary_span] - pub span: Span, - pub n: u128, -} - -#[derive(Diagnostic)] -#[diag("attribute requires {$opt} to be enabled")] -pub(crate) struct AttributeRequiresOpt { - #[primary_span] - pub span: Span, - pub opt: &'static str, -} - -pub(crate) enum AttributeParseErrorReason<'a> { - ExpectedNoArgs, - ExpectedStringLiteral { - byte_string: Option, - }, - ExpectedFilenameLiteral, - ExpectedIntegerLiteral, - ExpectedIntegerLiteralInRange { - lower_bound: isize, - upper_bound: isize, - }, - ExpectedAtLeastOneArgument, - ExpectedArgument, - ExpectedSingleArgument, - ExpectedList, - ExpectedListOrNoArgs, - ExpectedListWithNumArgsOrMore { - args: usize, - }, - ExpectedNameValueOrNoArgs, - ExpectedNonEmptyStringLiteral, - ExpectedNotLiteral, - ExpectedNameValue(Option), - MissingNameValue(Symbol), - DuplicateKey(Symbol), - ExpectedSpecificArgument { - possibilities: &'a [Symbol], - strings: bool, - /// Should we tell the user to write a list when they didn't? - list: bool, - }, - ExpectedIdentifier, -} - -/// A description of a thing that can be parsed using an attribute parser. -#[derive(Copy, Clone)] -pub enum ParsedDescription { - /// Used when parsing attributes. - Attribute, - /// Used when parsing some macros, such as the `cfg!()` macro. - Macro, -} - -pub(crate) struct AttributeParseError<'a> { - pub(crate) span: Span, - pub(crate) inner_span: Span, - pub(crate) template: AttributeTemplate, - pub(crate) path: AttrPath, - pub(crate) description: ParsedDescription, - pub(crate) reason: AttributeParseErrorReason<'a>, - pub(crate) suggestions: AttributeParseErrorSuggestions, -} - -pub(crate) enum AttributeParseErrorSuggestions { - CreatedByTemplate(Vec), - CreatedByParser(Vec), -} - -impl<'a> AttributeParseError<'a> { - fn render_expected_specific_argument( - &self, - diag: &mut Diag<'_, G>, - possibilities: &[Symbol], - strings: bool, - ) where - G: EmissionGuarantee, - { - let quote = if strings { '"' } else { '`' }; - match possibilities { - &[] => {} - &[x] => { - diag.span_label( - self.span, - format!("the only valid argument here is {quote}{x}{quote}"), - ); - } - [first, second] => { - diag.span_label( - self.span, - format!("valid arguments are {quote}{first}{quote} or {quote}{second}{quote}"), - ); - } - [first @ .., second_to_last, last] => { - let mut res = String::new(); - for i in first { - res.push_str(&format!("{quote}{i}{quote}, ")); - } - res.push_str(&format!("{quote}{second_to_last}{quote} or {quote}{last}{quote}")); - - diag.span_label(self.span, format!("valid arguments are {res}")); - } - } - } - - fn render_expected_specific_argument_list( - &self, - diag: &mut Diag<'_, G>, - possibilities: &[Symbol], - strings: bool, - ) where - G: EmissionGuarantee, - { - let description = self.description(); - - let quote = if strings { '"' } else { '`' }; - match possibilities { - &[] => {} - &[x] => { - diag.span_label( - self.span, - format!( - "this {description} is only valid with {quote}{x}{quote} as an argument" - ), - ); - } - [first, second] => { - diag.span_label(self.span, format!("this {description} is only valid with either {quote}{first}{quote} or {quote}{second}{quote} as an argument")); - } - [first @ .., second_to_last, last] => { - let mut res = String::new(); - for i in first { - res.push_str(&format!("{quote}{i}{quote}, ")); - } - res.push_str(&format!("{quote}{second_to_last}{quote} or {quote}{last}{quote}")); - - diag.span_label(self.span, format!("this {description} is only valid with one of the following arguments: {res}")); - } - } - } - - fn render_suggestions(&self, diag: &mut Diag<'_, G>) - where - G: EmissionGuarantee, - { - let description = self.description(); - - match &self.suggestions { - AttributeParseErrorSuggestions::CreatedByTemplate(suggestions) => { - diag.span_suggestions( - self.inner_span, - if suggestions.len() == 1 { - "must be of the form".to_string() - } else { - format!( - "try changing it to one of the following valid forms of the {description}" - ) - }, - suggestions.iter().cloned(), - Applicability::HasPlaceholders, - ); - } - - AttributeParseErrorSuggestions::CreatedByParser(suggestions) => { - for Suggestion { msg, sp, code } in suggestions { - diag.span_suggestion_verbose( - *sp, - msg.clone(), - code.clone(), - Applicability::MaybeIncorrect, - ); - } - } - } - } - - fn description(&self) -> &'static str { - match self.description { - ParsedDescription::Attribute => "attribute", - ParsedDescription::Macro => "macro", - } - } -} - -impl AttributeParseErrorSuggestions { - fn len(&self) -> usize { - match self { - AttributeParseErrorSuggestions::CreatedByTemplate(items) => items.len(), - AttributeParseErrorSuggestions::CreatedByParser(items) => items.len(), - } - } -} - -impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for AttributeParseError<'_> { - fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, G> { - let name = self.path.to_string(); - - let description = self.description(); - - let mut diag = Diag::new(dcx, level, format!("malformed `{name}` {description} input")); - diag.span(self.inner_span); - diag.code(E0539); - match &self.reason { - AttributeParseErrorReason::ExpectedStringLiteral { byte_string } => { - if let Some(start_point_span) = byte_string { - diag.span_suggestion( - *start_point_span, - "consider removing the prefix", - "", - Applicability::MaybeIncorrect, - ); - diag.note("expected a normal string literal, not a byte string literal"); - - // Avoid emitting an "attribute must be of the form" suggestion, as the - // attribute is likely to be well-formed already. - return diag; - } - diag.span_label(self.span, "expected a string literal here"); - } - AttributeParseErrorReason::ExpectedFilenameLiteral => { - diag.span_label(self.span, "expected a filename string literal here"); - } - AttributeParseErrorReason::ExpectedIntegerLiteral => { - diag.span_label(self.span, "expected an integer literal here"); - } - AttributeParseErrorReason::ExpectedIntegerLiteralInRange { - lower_bound, - upper_bound, - } => { - diag.span_label( - self.span, - format!( - "expected an integer literal in the range of {lower_bound}..={upper_bound}" - ), - ); - } - AttributeParseErrorReason::ExpectedSingleArgument => { - diag.span_label(self.span, "expected a single argument here"); - diag.code(E0805); - } - AttributeParseErrorReason::ExpectedArgument => { - diag.span_label(self.span, "expected an argument here"); - diag.code(E0805); - } - AttributeParseErrorReason::ExpectedAtLeastOneArgument => { - diag.span_label(self.span, "expected at least 1 argument here"); - } - AttributeParseErrorReason::ExpectedList => { - diag.span_label(self.span, "expected this to be a list"); - } - AttributeParseErrorReason::ExpectedListOrNoArgs => { - diag.span_label(self.span, "expected a list or no arguments here"); - } - AttributeParseErrorReason::ExpectedListWithNumArgsOrMore { args } => { - diag.span_label(self.span, format!("expected {args} or more items")); - } - AttributeParseErrorReason::ExpectedNameValueOrNoArgs => { - diag.span_label(self.span, "didn't expect a list here"); - } - AttributeParseErrorReason::ExpectedNonEmptyStringLiteral => { - diag.span_label(self.span, "string is not allowed to be empty"); - } - AttributeParseErrorReason::DuplicateKey(key) => { - diag.span_label(self.span, format!("found `{key}` used as a key more than once")); - diag.code(E0538); - } - AttributeParseErrorReason::ExpectedNotLiteral => { - diag.span_label(self.span, "didn't expect a literal here"); - diag.code(E0565); - } - AttributeParseErrorReason::ExpectedNoArgs => { - diag.span_label(self.span, "didn't expect any arguments here"); - diag.code(E0565); - } - AttributeParseErrorReason::ExpectedNameValue(None) => { - // If the span is the entire attribute inner, the suggestion we add below this - // match already contains enough information. - if self.span != self.inner_span { - diag.span_label(self.span, "expected this to be of the form `... = \"...\"`"); - } - } - AttributeParseErrorReason::ExpectedNameValue(Some(name)) => { - diag.span_label( - self.span, - format!("expected this to be of the form `{name} = \"...\"`"), - ); - } - AttributeParseErrorReason::MissingNameValue(name) => { - diag.span_label(self.span, format!("missing argument `{name} = \"...\"`")); - } - AttributeParseErrorReason::ExpectedSpecificArgument { - possibilities, - strings, - list: false, - } => { - self.render_expected_specific_argument(&mut diag, possibilities, *strings); - } - AttributeParseErrorReason::ExpectedSpecificArgument { - possibilities, - strings, - list: true, - } => { - self.render_expected_specific_argument_list(&mut diag, possibilities, *strings); - } - AttributeParseErrorReason::ExpectedIdentifier => { - diag.span_label(self.span, "expected a valid identifier here"); - diag.code(E0565); - } - } - - if let Some(link) = self.template.docs { - diag.note(format!("for more information, visit <{link}>")); - } - - if self.suggestions.len() < 4 { - self.render_suggestions(&mut diag); - } - - diag - } -} - -#[derive(Diagnostic)] -#[diag("`{$name}` is not an unsafe attribute")] -#[note("extraneous unsafe is not allowed in attributes")] -pub(crate) struct InvalidAttrUnsafe { - #[primary_span] - #[label("this is not an unsafe attribute")] - pub span: Span, - pub name: AttrPath, -} - -#[derive(Diagnostic)] -#[diag("unsafe attribute used without unsafe")] -pub(crate) struct UnsafeAttrOutsideUnsafe { - #[primary_span] - #[label("usage of unsafe attribute")] - pub span: Span, - #[subdiagnostic] - pub suggestion: Option, -} - -#[derive(Subdiagnostic)] -#[multipart_suggestion("wrap the attribute in `unsafe(...)`", applicability = "machine-applicable")] -pub(crate) struct UnsafeAttrOutsideUnsafeSuggestion { - #[suggestion_part(code = "unsafe(")] - pub left: Span, - #[suggestion_part(code = ")")] - pub right: Span, -} - -#[derive(Diagnostic)] -#[diag("wrong meta list delimiters")] -pub(crate) struct MetaBadDelim { - #[primary_span] - pub span: Span, - #[subdiagnostic] - pub sugg: MetaBadDelimSugg, -} - -#[derive(Subdiagnostic)] -#[multipart_suggestion( - "the delimiters should be `(` and `)`", - applicability = "machine-applicable" -)] -pub(crate) struct MetaBadDelimSugg { - #[suggestion_part(code = "(")] - pub open: Span, - #[suggestion_part(code = ")")] - pub close: Span, -} - -#[derive(Diagnostic)] -#[diag("expected a literal (`1u8`, `1.0f32`, `\"string\"`, etc.) here, found {$descr}")] -pub(crate) struct InvalidMetaItem { - #[primary_span] - pub span: Span, - pub descr: String, - #[subdiagnostic] - pub quote_ident_sugg: Option, - #[subdiagnostic] - pub remove_neg_sugg: Option, - #[label("{$descr}s are not allowed here")] - pub label: Option, -} - -#[derive(Subdiagnostic)] -#[multipart_suggestion( - "surround the identifier with quotation marks to make it into a string literal", - applicability = "machine-applicable" -)] -pub(crate) struct InvalidMetaItemQuoteIdentSugg { - #[suggestion_part(code = "\"")] - pub before: Span, - #[suggestion_part(code = "\"")] - pub after: Span, -} - -#[derive(Subdiagnostic)] -#[multipart_suggestion( - "negative numbers are not literals, try removing the `-` sign", - applicability = "machine-applicable" -)] -pub(crate) struct InvalidMetaItemRemoveNegSugg { - #[suggestion_part(code = "")] - pub negative_sign: Span, -} - -#[derive(Diagnostic)] -#[diag("suffixed literals are not allowed in attributes")] -#[help( - "instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), use an unsuffixed version (`1`, `1.0`, etc.)" -)] -pub(crate) struct SuffixedLiteralInAttribute { - #[primary_span] - pub span: Span, -} - -#[derive(Diagnostic)] -#[diag("link name must not be empty", code = E0454)] -pub(crate) struct EmptyLinkName { - #[primary_span] - #[label("empty link name")] - pub span: Span, -} - -#[derive(Diagnostic)] -#[diag("link kind `framework` is only supported on Apple targets", code = E0455)] -pub(crate) struct LinkFrameworkApple { - #[primary_span] - pub span: Span, -} - -#[derive(Diagnostic)] -#[diag("`wasm_import_module` is incompatible with other arguments in `#[link]` attributes")] -pub(crate) struct IncompatibleWasmLink { - #[primary_span] - pub span: Span, -} - -#[derive(Diagnostic)] -#[diag("`#[link]` attribute requires a `name = \"string\"` argument", code = E0459)] -pub(crate) struct LinkRequiresName { - #[primary_span] - #[label("missing `name` argument")] - pub span: Span, -} - -#[derive(Diagnostic)] -#[diag("link kind `raw-dylib` is only supported on Windows targets", code = E0455)] -pub(crate) struct RawDylibOnlyWindows { - #[primary_span] - pub span: Span, -} - -#[derive(Diagnostic)] -#[diag( - "invalid linking modifier syntax, expected '+' or '-' prefix before one of: bundle, verbatim, whole-archive, as-needed, export-symbols" -)] -pub(crate) struct InvalidLinkModifier { - #[primary_span] - pub span: Span, -} - -#[derive(Diagnostic)] -#[diag("multiple `{$modifier}` modifiers in a single `modifiers` argument")] -pub(crate) struct MultipleModifiers { - #[primary_span] - pub span: Span, - pub modifier: Symbol, -} - -#[derive(Diagnostic)] -#[diag("import name type is only supported on x86")] -pub(crate) struct ImportNameTypeX86 { - #[primary_span] - pub span: Span, -} - -#[derive(Diagnostic)] -#[diag("linking modifier `bundle` is only compatible with `static` linking kind")] -pub(crate) struct BundleNeedsStatic { - #[primary_span] - pub span: Span, -} - -#[derive(Diagnostic)] -#[diag("linking modifier `export-symbols` is only compatible with `static` linking kind")] -pub(crate) struct ExportSymbolsNeedsStatic { - #[primary_span] - pub span: Span, -} - -#[derive(Diagnostic)] -#[diag("linking modifier `whole-archive` is only compatible with `static` linking kind")] -pub(crate) struct WholeArchiveNeedsStatic { - #[primary_span] - pub span: Span, -} - -#[derive(Diagnostic)] -#[diag( - "linking modifier `as-needed` is only compatible with `dylib`, `framework` and `raw-dylib` linking kinds" -)] -pub(crate) struct AsNeededCompatibility { - #[primary_span] - pub span: Span, -} - -#[derive(Diagnostic)] -#[diag("import name type can only be used with link kind `raw-dylib`")] -pub(crate) struct ImportNameTypeRaw { - #[primary_span] - pub span: Span, -} - -#[derive(Diagnostic)] -#[diag("`limit` must be a non-negative integer")] -pub(crate) struct LimitInvalid<'a> { - #[primary_span] - pub span: Span, - #[label("{$error_str}")] - pub value_span: Span, - pub error_str: &'a str, -} - -#[derive(Diagnostic)] -#[diag("wrong `cfg_attr` delimiters")] -pub(crate) struct CfgAttrBadDelim { - #[primary_span] - pub span: Span, - #[subdiagnostic] - pub sugg: MetaBadDelimSugg, -} - -#[derive(Diagnostic)] -#[diag( - "doc alias attribute expects a string `#[doc(alias = \"a\")]` or a list of strings `#[doc(alias(\"a\", \"b\"))]`" -)] -pub(crate) struct DocAliasMalformed { - #[primary_span] - pub span: Span, -} - -#[derive(Diagnostic)] -#[diag("definition of an unknown lang item: `{$name}`", code = E0522)] -pub(crate) struct UnknownLangItem { - #[primary_span] - #[label("definition of unknown lang item `{$name}`")] - pub span: Span, - pub name: Symbol, -} - -#[derive(Diagnostic)] -#[diag("target `{$current_target}` does not support `#[instruction_set({$instruction_set}::*)]`")] -pub(crate) struct UnsupportedInstructionSet<'a> { - #[primary_span] - pub span: Span, - pub instruction_set: Symbol, - pub current_target: &'a TargetTuple, -} - -#[derive(Diagnostic)] -#[diag("`dialect` key required")] -pub(crate) struct CustomMirPhaseRequiresDialect { - #[primary_span] - pub attr_span: Span, - #[label("`phase` argument requires a `dialect` argument")] - pub phase_span: Span, -} - -#[derive(Diagnostic)] -#[diag("the {$dialect} dialect is not compatible with the {$phase} phase")] -pub(crate) struct CustomMirIncompatibleDialectAndPhase { - pub dialect: MirDialect, - pub phase: MirPhase, - #[primary_span] - pub attr_span: Span, - #[label("this dialect...")] - pub dialect_span: Span, - #[label("... is not compatible with this phase")] - pub phase_span: Span, -} - -#[derive(Diagnostic)] -#[diag("can't mark as unstable using an already stable feature")] -pub(crate) struct UnstableAttrForAlreadyStableFeature { - #[primary_span] - #[label("this feature is already stable")] - #[help("consider removing the attribute")] - pub attr_span: Span, - #[label("the stability attribute annotates this item")] - pub item_span: Span, -} - -#[derive(Diagnostic)] -#[diag("invalid Mach-O section specifier")] -pub(crate) struct InvalidMachoSection { - #[primary_span] - #[label("not a valid Mach-O section specifier")] - pub name_span: Span, - #[subdiagnostic] - pub reason: InvalidMachoSectionReason, -} - -#[derive(Subdiagnostic)] -pub(crate) enum InvalidMachoSectionReason { - #[note("a Mach-O section specifier requires a segment and a section, separated by a comma")] - #[help("an example of a valid Mach-O section specifier is `__TEXT,__cstring`")] - MissingSection, - #[note("section name `{$section}` is longer than 16 bytes")] - SectionTooLong { section: String }, -} - -#[derive(Diagnostic)] -#[diag("`#[sanitize({$field} = ...)]` attribute cannot be used on statics")] -#[help("`#[sanitize]` can be used on statics if only the address is sanitized")] -pub(crate) struct SanitizeInvalidStatic { - #[primary_span] - pub span: Span, - pub field: &'static str, -} - -#[derive(Diagnostic)] -#[diag("attribute items not separated with `,`")] -pub(crate) struct ExpectedComma { - #[primary_span] - #[suggestion( - "try adding `,` here", - code = ",", - applicability = "maybe-incorrect", - style = "short" - )] - pub span: Span, - #[subdiagnostic] - pub additional: Vec, -} - -#[derive(Subdiagnostic)] -#[suggestion("try adding `,` here", code = ",", applicability = "maybe-incorrect", style = "short")] -pub(crate) struct AdditionalCommaSuggestion { - #[primary_span] - pub span: Span, -} - -#[derive(Diagnostic)] -#[diag("unused attribute")] -pub(crate) struct UnusedDuplicate { - #[suggestion("remove this attribute", code = "", applicability = "machine-applicable")] - pub this: Span, - #[note("attribute also specified here")] - pub other: Span, - #[warning( - "this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!" - )] - pub warning: bool, -} diff --git a/compiler/rustc_attr_parsing/src/target_checking.rs b/compiler/rustc_attr_parsing/src/target_checking.rs index 6b0d1b094ca0f..fc78279da0c62 100644 --- a/compiler/rustc_attr_parsing/src/target_checking.rs +++ b/compiler/rustc_attr_parsing/src/target_checking.rs @@ -9,9 +9,9 @@ use rustc_span::{BytePos, FileName, RemapPathScopeComponents, Span, Symbol, sym} use crate::context::AcceptContext; use crate::diagnostics::{ - InvalidAttrAtCrateLevel, ItemFollowingInnerAttr, UnsupportedAttributesInWhere, + InvalidAttrAtCrateLevel, InvalidTarget, InvalidTargetHelp, ItemFollowingInnerAttr, + UnsupportedAttributesInWhere, }; -use crate::session_diagnostics::{InvalidTarget, InvalidTargetHelp}; use crate::target_checking::Policy::Allow; use crate::{AttributeParser, ShouldEmit}; diff --git a/compiler/rustc_attr_parsing/src/validate_attr.rs b/compiler/rustc_attr_parsing/src/validate_attr.rs index 08c73352f27eb..53a06e27cc4e8 100644 --- a/compiler/rustc_attr_parsing/src/validate_attr.rs +++ b/compiler/rustc_attr_parsing/src/validate_attr.rs @@ -18,7 +18,7 @@ use rustc_session::lint::builtin::ILL_FORMED_ATTRIBUTE_INPUT; use rustc_session::parse::ParseSess; use rustc_span::{Span, Symbol, sym}; -use crate::{AttributeParser, AttributeTemplate, session_diagnostics as errors, template}; +use crate::{AttributeParser, AttributeTemplate, diagnostics as errors, template}; pub fn check_attr(psess: &ParseSess, attr: &Attribute) { use ast::SyntheticAttr::*; From 9846cb6f3fed5d6020ca1b08727e5acdb0bbb5e2 Mon Sep 17 00:00:00 2001 From: Jules Bertholet Date: Sat, 8 Aug 2026 15:08:13 +0000 Subject: [PATCH 10/13] Make `char::is_default_ignorable` unstably public * Make `char::is_default_ignorable` unstably public * Add tracking issue Co-authored-by: Jules Bertholet --- library/core/src/char/methods.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/library/core/src/char/methods.rs b/library/core/src/char/methods.rs index 8c5f9d472bfa8..1fa4dc37aff5a 100644 --- a/library/core/src/char/methods.rs +++ b/library/core/src/char/methods.rs @@ -1241,7 +1241,8 @@ impl char { /// /// Basic usage: /// - /// ```ignore(private) + /// ``` + /// #![feature(default_ignorable)] /// assert!('\u{AD}'.is_default_ignorable()); // SOFT HYPHEN /// assert!('\u{115F}'.is_default_ignorable()); // HANGUL CHOSEONG FILLER /// assert!('\u{200B}'.is_default_ignorable()); // ZERO WIDTH SPACE @@ -1252,9 +1253,11 @@ impl char { /// assert!(!'\n'.is_default_ignorable()); /// assert!(!'\0'.is_default_ignorable()); /// assert!(!'q'.is_default_ignorable()); + /// ``` #[must_use] + #[unstable(feature = "default_ignorable", issue = "160583")] #[inline] - fn is_default_ignorable(self) -> bool { + pub fn is_default_ignorable(self) -> bool { self > '\u{AC}' && unicode::Default_Ignorable_Code_Point(self) } From c0a4462a238a5295b89880bc529c14e5f936b37b Mon Sep 17 00:00:00 2001 From: SomeFlyingThing <306498559+SomeFlyingThing@users.noreply.github.com> Date: Sat, 8 Aug 2026 08:55:05 -0700 Subject: [PATCH 11/13] Use transmute_copy in SliceContains --- library/core/src/slice/cmp.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/core/src/slice/cmp.rs b/library/core/src/slice/cmp.rs index 9c670d360b633..623e4ad5ce330 100644 --- a/library/core/src/slice/cmp.rs +++ b/library/core/src/slice/cmp.rs @@ -5,7 +5,7 @@ use crate::ascii; use crate::cmp::{self, BytewiseEq, Ordering}; use crate::intrinsics::compare_bytes; use crate::marker::Destruct; -use crate::mem::SizedTypeProperties; +use crate::mem::{SizedTypeProperties, transmute_copy}; use crate::num::NonZero; use crate::ops::ControlFlow; @@ -400,7 +400,7 @@ impl SliceContains for T { // slice can be read as `u8`s. let (byte, bytes) = unsafe { ( - *(self as *const Self).cast::(), + transmute_copy::(self), from_raw_parts(x.as_ptr().cast::(), x.len()), ) }; From 538b30365524115fea02777899cc2be015a9ad5f Mon Sep 17 00:00:00 2001 From: SomeFlyingThing <306498559+SomeFlyingThing@users.noreply.github.com> Date: Sat, 8 Aug 2026 09:04:54 -0700 Subject: [PATCH 12/13] Apply rustfmt to SliceContains --- library/core/src/slice/cmp.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/library/core/src/slice/cmp.rs b/library/core/src/slice/cmp.rs index 623e4ad5ce330..70d2392dfb3c6 100644 --- a/library/core/src/slice/cmp.rs +++ b/library/core/src/slice/cmp.rs @@ -399,10 +399,7 @@ impl SliceContains for T { // compare like their underlying bytes. Since `T` is one byte, both the value and // slice can be read as `u8`s. let (byte, bytes) = unsafe { - ( - transmute_copy::(self), - from_raw_parts(x.as_ptr().cast::(), x.len()), - ) + (transmute_copy::(self), from_raw_parts(x.as_ptr().cast::(), x.len())) }; memchr::memchr(byte, bytes).is_some() } else { From 7b1731bf82b39b5d1519d02a3895c18127eb7344 Mon Sep 17 00:00:00 2001 From: ravlyn Date: Fri, 24 Jul 2026 20:01:03 +0700 Subject: [PATCH 13/13] rustc_passes: lint unused `#[path]` attributes on inline modules --- compiler/rustc_attr_ir/src/data_structures.rs | 2 +- .../rustc_attr_parsing/src/attributes/path.rs | 2 +- compiler/rustc_passes/src/check_attr.rs | 51 ++- compiler/rustc_passes/src/diagnostics.rs | 2 + tests/ui/attributes/auxiliary/foo.rs | 1 + tests/ui/attributes/auxiliary/sub/foo.rs | 1 + tests/ui/attributes/path-inline-module.rs | 74 ++++ tests/ui/attributes/path-inline-module.stderr | 51 +++ .../issue-43106-gating-of-builtin-attrs.rs | 7 +- ...issue-43106-gating-of-builtin-attrs.stderr | 352 +++++++++--------- 10 files changed, 366 insertions(+), 177 deletions(-) create mode 100644 tests/ui/attributes/auxiliary/foo.rs create mode 100644 tests/ui/attributes/auxiliary/sub/foo.rs create mode 100644 tests/ui/attributes/path-inline-module.rs create mode 100644 tests/ui/attributes/path-inline-module.stderr diff --git a/compiler/rustc_attr_ir/src/data_structures.rs b/compiler/rustc_attr_ir/src/data_structures.rs index 5fb57606e14fd..81887e0176ee7 100644 --- a/compiler/rustc_attr_ir/src/data_structures.rs +++ b/compiler/rustc_attr_ir/src/data_structures.rs @@ -1273,7 +1273,7 @@ pub enum AttributeKind { }, /// Represents `#[path]` - Path(Symbol), + Path(Symbol, Span), /// Represents `#[pattern_complexity_limit]` PatternComplexityLimit { diff --git a/compiler/rustc_attr_parsing/src/attributes/path.rs b/compiler/rustc_attr_parsing/src/attributes/path.rs index ad4641c4be7f2..a44414f5aead2 100644 --- a/compiler/rustc_attr_parsing/src/attributes/path.rs +++ b/compiler/rustc_attr_parsing/src/attributes/path.rs @@ -19,6 +19,6 @@ impl SingleAttributeParser for PathParser { let nv = cx.expect_name_value(args, cx.attr_span, None)?; let path = cx.expect_string_literal(nv)?; - Some(AttributeKind::Path(path)) + Some(AttributeKind::Path(path, cx.attr_span)) } } diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index a5ba6d2f14d12..d29d5280e77e9 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -24,7 +24,7 @@ use rustc_hir::def_id::LocalModId; use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::{ self as hir, Attribute, CRATE_HIR_ID, Constness, FnSig, ForeignItem, GenericParam, - GenericParamKind, HirId, Item, ItemKind, MethodKind, Node, ParamName, Target, TraitItem, + GenericParamKind, HirId, Item, ItemKind, MethodKind, Mod, Node, ParamName, Target, TraitItem, find_attr, }; use rustc_macros::Diagnostic; @@ -288,7 +288,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { AttributeKind::Optimize(..) => (), AttributeKind::PanicRuntime => (), AttributeKind::PatchableFunctionEntry { .. } => (), - AttributeKind::Path(..) => (), + AttributeKind::Path(_, span) => self.check_path(*span, hir_id), AttributeKind::PatternComplexityLimit { .. } => (), AttributeKind::PinV2(..) => (), AttributeKind::PreludeImport => (), @@ -411,6 +411,53 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } } + fn check_path(&self, span: Span, hir_id: HirId) { + let Node::Item(item) = self.tcx.hir_node(hir_id) else { + return; + }; + + let ItemKind::Mod(_, module) = &item.kind else { + return; + }; + + if item.span == module.spans.inner_span || !item.span.contains(module.spans.inner_span) { + return; + } + + // Do not warn when a nested module uses `#[path]` or is out-of-line, + // because the attribute may affect nested module path resolution. + if self.has_nested_module_path_dependency(module) { + return; + } + + self.tcx.emit_node_span_lint( + UNUSED_ATTRIBUTES, + hir_id, + span, + diagnostics::Unused { + attr_span: span, + note: diagnostics::UnusedNote::PathOnInlineModule, + }, + ); + } + + fn has_nested_module_path_dependency(&self, module: &Mod<'tcx>) -> bool { + module.item_ids.iter().any(|item_id| { + let child = self.tcx.hir_item(*item_id); + + let ItemKind::Mod(_, child_module) = &child.kind else { + return false; + }; + + let is_out_of_line = child.span == child_module.spans.inner_span + || !child.span.contains(child_module.spans.inner_span); + + let has_path_attr = find_attr!(self.tcx, child.hir_id(), Path(..)); + + is_out_of_line || has_path_attr || self.has_nested_module_path_dependency(child_module) + }) + } + fn check_rustc_must_implement_one_of( &self, attr_span: Span, diff --git a/compiler/rustc_passes/src/diagnostics.rs b/compiler/rustc_passes/src/diagnostics.rs index b0faff303d523..59b393fc8e68b 100644 --- a/compiler/rustc_passes/src/diagnostics.rs +++ b/compiler/rustc_passes/src/diagnostics.rs @@ -263,6 +263,8 @@ pub(crate) enum UnusedNote { LinkerMessagesBinaryCrateOnly, #[note("the `dead_code_pub_in_binary` lint has no effect in library crates")] NoEffectDeadCodePubInBinary, + #[note("`#[path]` is unused on this inline module")] + PathOnInlineModule, } #[derive(Diagnostic)] diff --git a/tests/ui/attributes/auxiliary/foo.rs b/tests/ui/attributes/auxiliary/foo.rs new file mode 100644 index 0000000000000..e5736aedfdc7c --- /dev/null +++ b/tests/ui/attributes/auxiliary/foo.rs @@ -0,0 +1 @@ +mod foo {} diff --git a/tests/ui/attributes/auxiliary/sub/foo.rs b/tests/ui/attributes/auxiliary/sub/foo.rs new file mode 100644 index 0000000000000..e5736aedfdc7c --- /dev/null +++ b/tests/ui/attributes/auxiliary/sub/foo.rs @@ -0,0 +1 @@ +mod foo {} diff --git a/tests/ui/attributes/path-inline-module.rs b/tests/ui/attributes/path-inline-module.rs new file mode 100644 index 0000000000000..835b9d4566e0e --- /dev/null +++ b/tests/ui/attributes/path-inline-module.rs @@ -0,0 +1,74 @@ +//@ check-pass + +fn main() {} + +#[path = "foo.rs"] //~ WARN unused attribute [unused_attributes] +mod inline_module {} + +mod inline_module_with_inner_path { + #![path = "foo.rs"] //~ WARN unused attribute [unused_attributes] +} + +#[path = "auxiliary/foo.rs"] +mod outline_module; // Should not warn + +mod inline_with_inner_path { + #![path = "auxiliary"] + + #[path = "foo.rs"] // Should not warn + mod file_submodule; +} + +mod inline_with_inline_child { + #![path = "auxiliary"] + + #[path = "foo.rs"] //~ WARN unused attribute [unused_attributes] + mod nested_inline_module {} +} + +#[path = "auxiliary"] +mod inline_parent_with_file_child { + #[path = "foo.rs"] // Should not warn + mod file_submodule; +} + +#[path = "auxiliary"] +mod inline_parent_with_inline_child { + #[path = "foo.rs"] //~ WARN unused attribute [unused_attributes] + mod inline_submodule {} +} + +#[path = "auxiliary"] +mod inline_parent_with_nested_file_child { + mod sub { + #[path = "foo.rs"] // Should not warn + mod file_submodule; + } +} + +mod inline_with_inner_path_and_nested_file_child { + #![path = "auxiliary"] + + #[path = "sub"] + mod middle { + #[path = "foo.rs"] // Should not warn + mod file_submodule; + } +} + +#[path = "auxiliary"] //~ WARN unused attribute [unused_attributes] +mod inline_parent_with_nested_inline_child { + mod middle { + mod inline_submodule {} + } +} + +#[path = "auxiliary"] +mod inline_parent_with_nested_inline_path { + + #[path = "sub"] + mod middle { + #[path = "foo.rs"] //~ WARN unused attribute [unused_attributes] + mod inline_submodule {} + } +} diff --git a/tests/ui/attributes/path-inline-module.stderr b/tests/ui/attributes/path-inline-module.stderr new file mode 100644 index 0000000000000..bfa8d0457c493 --- /dev/null +++ b/tests/ui/attributes/path-inline-module.stderr @@ -0,0 +1,51 @@ +warning: unused attribute + --> $DIR/path-inline-module.rs:5:1 + | +LL | #[path = "foo.rs"] + | ^^^^^^^^^^^^^^^^^^ help: remove this attribute + | + = note: `#[path]` is unused on this inline module + = note: requested on the command line with `-W unused-attributes` + +warning: unused attribute + --> $DIR/path-inline-module.rs:9:5 + | +LL | #![path = "foo.rs"] + | ^^^^^^^^^^^^^^^^^^^ help: remove this attribute + | + = note: `#[path]` is unused on this inline module + +warning: unused attribute + --> $DIR/path-inline-module.rs:59:1 + | +LL | #[path = "auxiliary"] + | ^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute + | + = note: `#[path]` is unused on this inline module + +warning: unused attribute + --> $DIR/path-inline-module.rs:25:5 + | +LL | #[path = "foo.rs"] + | ^^^^^^^^^^^^^^^^^^ help: remove this attribute + | + = note: `#[path]` is unused on this inline module + +warning: unused attribute + --> $DIR/path-inline-module.rs:37:5 + | +LL | #[path = "foo.rs"] + | ^^^^^^^^^^^^^^^^^^ help: remove this attribute + | + = note: `#[path]` is unused on this inline module + +warning: unused attribute + --> $DIR/path-inline-module.rs:71:9 + | +LL | #[path = "foo.rs"] + | ^^^^^^^^^^^^^^^^^^ help: remove this attribute + | + = note: `#[path]` is unused on this inline module + +warning: 6 warnings emitted + diff --git a/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.rs b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.rs index 31677560a005a..adbf64e8b0f63 100644 --- a/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.rs +++ b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.rs @@ -253,7 +253,12 @@ mod macro_export { #[path = "3800"] mod path { - mod inner { #![path="3800"] } + mod inner { + #![path="3800"] + //~^ WARN unused attribute + //~| NOTE `#[path]` is unused on this inline module + //~| HELP remove this attribute + } #[path = "3800"] fn f() { } //~^ WARN attribute cannot be used on diff --git a/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr index f2c77b2e4808d..a677339551153 100644 --- a/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr +++ b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr @@ -1,5 +1,5 @@ warning: `#[macro_escape]` is a deprecated synonym for `#[macro_use]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:474:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:479:17 | LL | mod inner { #![macro_escape] } | ^^^^^^^^^^^^^^^^ @@ -7,7 +7,7 @@ LL | mod inner { #![macro_escape] } = help: try an outer attribute: `#[macro_use]` warning: `#[macro_escape]` is a deprecated synonym for `#[macro_use]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:471:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:476:1 | LL | #[macro_escape] | ^^^^^^^^^^^^^^^ @@ -194,19 +194,27 @@ LL | #![feature(rust1)] | = note: `#[warn(stable_features)]` on by default -warning: attribute should be applied to an `extern` block with non-Rust ABI - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:724:5 +warning: unused attribute + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:257:9 | -LL | #[link(name = "x")] extern "Rust" {} - | ^^^^^^^^^^^^^^^^^^^ +LL | #![path="3800"] + | ^^^^^^^^^^^^^^^ help: remove this attribute | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: `#[path]` is unused on this inline module note: the lint level is defined here --> $DIR/issue-43106-gating-of-builtin-attrs.rs:35:9 | LL | #![warn(unused_attributes, unknown_lints)] | ^^^^^^^^^^^^^^^^^ +warning: attribute should be applied to an `extern` block with non-Rust ABI + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:729:5 + | +LL | #[link(name = "x")] extern "Rust" {} + | ^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + warning: the `macro_use` attribute cannot be used on crates --> $DIR/issue-43106-gating-of-builtin-attrs.rs:45:4 | @@ -379,7 +387,7 @@ LL | #[macro_export] impl S { } = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: the `path` attribute cannot be used on functions - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:258:7 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:263:7 | LL | #[path = "3800"] fn f() { } | ^^^^ @@ -388,7 +396,7 @@ LL | #[path = "3800"] fn f() { } = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: the `path` attribute cannot be used on structs - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:264:7 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:269:7 | LL | #[path = "3800"] struct S; | ^^^^ @@ -397,7 +405,7 @@ LL | #[path = "3800"] struct S; = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: the `path` attribute cannot be used on type aliases - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:270:7 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:275:7 | LL | #[path = "3800"] type T = S; | ^^^^ @@ -406,7 +414,7 @@ LL | #[path = "3800"] type T = S; = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: the `path` attribute cannot be used on inherent impl blocks - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:276:7 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:281:7 | LL | #[path = "3800"] impl S { } | ^^^^ @@ -415,7 +423,7 @@ LL | #[path = "3800"] impl S { } = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: the `automatically_derived` attribute cannot be used on modules - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:283:3 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:288:3 | LL | #[automatically_derived] | ^^^^^^^^^^^^^^^^^^^^^ @@ -424,7 +432,7 @@ LL | #[automatically_derived] = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: the `automatically_derived` attribute cannot be used on modules - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:289:20 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:294:20 | LL | mod inner { #![automatically_derived] } | ^^^^^^^^^^^^^^^^^^^^^ @@ -433,7 +441,7 @@ LL | mod inner { #![automatically_derived] } = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: the `automatically_derived` attribute cannot be used on functions - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:295:7 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:300:7 | LL | #[automatically_derived] fn f() { } | ^^^^^^^^^^^^^^^^^^^^^ @@ -442,7 +450,7 @@ LL | #[automatically_derived] fn f() { } = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: the `automatically_derived` attribute cannot be used on structs - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:301:7 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:306:7 | LL | #[automatically_derived] struct S; | ^^^^^^^^^^^^^^^^^^^^^ @@ -451,7 +459,7 @@ LL | #[automatically_derived] struct S; = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: the `automatically_derived` attribute cannot be used on type aliases - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:307:7 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:312:7 | LL | #[automatically_derived] type T = S; | ^^^^^^^^^^^^^^^^^^^^^ @@ -460,7 +468,7 @@ LL | #[automatically_derived] type T = S; = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: the `automatically_derived` attribute cannot be used on traits - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:313:7 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:318:7 | LL | #[automatically_derived] trait W { } | ^^^^^^^^^^^^^^^^^^^^^ @@ -469,7 +477,7 @@ LL | #[automatically_derived] trait W { } = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: the `automatically_derived` attribute cannot be used on inherent impl blocks - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:319:7 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:324:7 | LL | #[automatically_derived] impl S { } | ^^^^^^^^^^^^^^^^^^^^^ @@ -478,7 +486,7 @@ LL | #[automatically_derived] impl S { } = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: the `no_mangle` attribute cannot be used on modules - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:328:3 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:333:3 | LL | #[no_mangle] | ^^^^^^^^^ @@ -487,7 +495,7 @@ LL | #[no_mangle] = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: the `no_mangle` attribute cannot be used on modules - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:334:20 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:339:20 | LL | mod inner { #![no_mangle] } | ^^^^^^^^^ @@ -496,7 +504,7 @@ LL | mod inner { #![no_mangle] } = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: the `no_mangle` attribute cannot be used on structs - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:342:7 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:347:7 | LL | #[no_mangle] struct S; | ^^^^^^^^^ @@ -505,7 +513,7 @@ LL | #[no_mangle] struct S; = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: the `no_mangle` attribute cannot be used on type aliases - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:348:7 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:353:7 | LL | #[no_mangle] type T = S; | ^^^^^^^^^ @@ -514,7 +522,7 @@ LL | #[no_mangle] type T = S; = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: the `no_mangle` attribute cannot be used on inherent impl blocks - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:354:7 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:359:7 | LL | #[no_mangle] impl S { } | ^^^^^^^^^ @@ -523,7 +531,7 @@ LL | #[no_mangle] impl S { } = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: the `should_panic` attribute cannot be used on modules - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:375:3 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:380:3 | LL | #[should_panic] | ^^^^^^^^^^^^ @@ -532,7 +540,7 @@ LL | #[should_panic] = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: the `should_panic` attribute cannot be used on modules - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:381:20 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:386:20 | LL | mod inner { #![should_panic] } | ^^^^^^^^^^^^ @@ -541,7 +549,7 @@ LL | mod inner { #![should_panic] } = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: the `should_panic` attribute cannot be used on structs - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:389:7 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:394:7 | LL | #[should_panic] struct S; | ^^^^^^^^^^^^ @@ -550,7 +558,7 @@ LL | #[should_panic] struct S; = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: the `should_panic` attribute cannot be used on type aliases - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:395:7 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:400:7 | LL | #[should_panic] type T = S; | ^^^^^^^^^^^^ @@ -559,7 +567,7 @@ LL | #[should_panic] type T = S; = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: the `should_panic` attribute cannot be used on inherent impl blocks - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:401:7 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:406:7 | LL | #[should_panic] impl S { } | ^^^^^^^^^^^^ @@ -568,7 +576,7 @@ LL | #[should_panic] impl S { } = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: the `ignore` attribute cannot be used on modules - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:408:3 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:413:3 | LL | #[ignore] | ^^^^^^ @@ -577,7 +585,7 @@ LL | #[ignore] = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: the `ignore` attribute cannot be used on modules - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:414:20 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:419:20 | LL | mod inner { #![ignore] } | ^^^^^^ @@ -586,7 +594,7 @@ LL | mod inner { #![ignore] } = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: the `ignore` attribute cannot be used on structs - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:422:7 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:427:7 | LL | #[ignore] struct S; | ^^^^^^ @@ -595,7 +603,7 @@ LL | #[ignore] struct S; = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: the `ignore` attribute cannot be used on type aliases - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:428:7 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:433:7 | LL | #[ignore] type T = S; | ^^^^^^ @@ -604,7 +612,7 @@ LL | #[ignore] type T = S; = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: the `ignore` attribute cannot be used on inherent impl blocks - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:434:7 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:439:7 | LL | #[ignore] impl S { } | ^^^^^^ @@ -613,7 +621,7 @@ LL | #[ignore] impl S { } = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: the `no_implicit_prelude` attribute cannot be used on functions - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:445:7 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:450:7 | LL | #[no_implicit_prelude] fn f() { } | ^^^^^^^^^^^^^^^^^^^ @@ -622,7 +630,7 @@ LL | #[no_implicit_prelude] fn f() { } = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: the `no_implicit_prelude` attribute cannot be used on structs - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:451:7 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:456:7 | LL | #[no_implicit_prelude] struct S; | ^^^^^^^^^^^^^^^^^^^ @@ -631,7 +639,7 @@ LL | #[no_implicit_prelude] struct S; = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: the `no_implicit_prelude` attribute cannot be used on type aliases - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:457:7 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:462:7 | LL | #[no_implicit_prelude] type T = S; | ^^^^^^^^^^^^^^^^^^^ @@ -640,7 +648,7 @@ LL | #[no_implicit_prelude] type T = S; = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: the `no_implicit_prelude` attribute cannot be used on inherent impl blocks - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:463:7 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:468:7 | LL | #[no_implicit_prelude] impl S { } | ^^^^^^^^^^^^^^^^^^^ @@ -649,7 +657,7 @@ LL | #[no_implicit_prelude] impl S { } = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: the `macro_escape` attribute cannot be used on functions - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:478:7 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:483:7 | LL | #[macro_escape] fn f() { } | ^^^^^^^^^^^^ @@ -658,7 +666,7 @@ LL | #[macro_escape] fn f() { } = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: the `macro_escape` attribute cannot be used on structs - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:484:7 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:489:7 | LL | #[macro_escape] struct S; | ^^^^^^^^^^^^ @@ -667,7 +675,7 @@ LL | #[macro_escape] struct S; = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: the `macro_escape` attribute cannot be used on type aliases - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:490:7 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:495:7 | LL | #[macro_escape] type T = S; | ^^^^^^^^^^^^ @@ -676,7 +684,7 @@ LL | #[macro_escape] type T = S; = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: the `macro_escape` attribute cannot be used on inherent impl blocks - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:496:7 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:501:7 | LL | #[macro_escape] impl S { } | ^^^^^^^^^^^^ @@ -685,13 +693,13 @@ LL | #[macro_escape] impl S { } = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![no_std]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:503:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:508:1 | LL | #[no_std] | ^^^^^^^^^ | note: this attribute does not have an `!`, which means it is applied to this module - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:505:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:510:1 | LL | / mod no_std { LL | | @@ -701,61 +709,61 @@ LL | | } | |_^ warning: the `#![no_std]` attribute can only be used at the crate root - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:507:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:512:17 | LL | mod inner { #![no_std] } | ^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![no_std]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:510:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:515:5 | LL | #[no_std] fn f() { } | ^^^^^^^^^ | note: this attribute does not have an `!`, which means it is applied to this function - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:510:15 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:515:15 | LL | #[no_std] fn f() { } | ^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![no_std]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:514:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:519:5 | LL | #[no_std] struct S; | ^^^^^^^^^ | note: this attribute does not have an `!`, which means it is applied to this struct - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:514:15 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:519:15 | LL | #[no_std] struct S; | ^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![no_std]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:518:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:523:5 | LL | #[no_std] type T = S; | ^^^^^^^^^ | note: this attribute does not have an `!`, which means it is applied to this type alias - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:518:15 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:523:15 | LL | #[no_std] type T = S; | ^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![no_std]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:522:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:527:5 | LL | #[no_std] impl S { } | ^^^^^^^^^ | note: this attribute does not have an `!`, which means it is applied to this implementation block - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:522:15 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:527:15 | LL | #[no_std] impl S { } | ^^^^^^^^^^ warning: the `cold` attribute cannot be used on modules - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:544:3 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:549:3 | LL | #[cold] | ^^^^ @@ -764,7 +772,7 @@ LL | #[cold] = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: the `cold` attribute cannot be used on modules - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:551:20 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:556:20 | LL | mod inner { #![cold] } | ^^^^ @@ -773,7 +781,7 @@ LL | mod inner { #![cold] } = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: the `cold` attribute cannot be used on structs - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:559:7 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:564:7 | LL | #[cold] struct S; | ^^^^ @@ -782,7 +790,7 @@ LL | #[cold] struct S; = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: the `cold` attribute cannot be used on type aliases - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:565:7 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:570:7 | LL | #[cold] type T = S; | ^^^^ @@ -791,7 +799,7 @@ LL | #[cold] type T = S; = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: the `cold` attribute cannot be used on inherent impl blocks - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:571:7 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:576:7 | LL | #[cold] impl S { } | ^^^^ @@ -800,7 +808,7 @@ LL | #[cold] impl S { } = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: the `link_name` attribute cannot be used on modules - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:578:3 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:583:3 | LL | #[link_name = "1900"] | ^^^^^^^^^ @@ -809,7 +817,7 @@ LL | #[link_name = "1900"] = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: the `link_name` attribute cannot be used on foreign modules - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:584:7 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:589:7 | LL | #[link_name = "1900"] | ^^^^^^^^^ @@ -818,7 +826,7 @@ LL | #[link_name = "1900"] = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: the `link_name` attribute cannot be used on modules - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:591:20 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:596:20 | LL | mod inner { #![link_name="1900"] } | ^^^^^^^^^ @@ -827,7 +835,7 @@ LL | mod inner { #![link_name="1900"] } = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: the `link_name` attribute cannot be used on functions - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:597:7 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:602:7 | LL | #[link_name = "1900"] fn f() { } | ^^^^^^^^^ @@ -836,7 +844,7 @@ LL | #[link_name = "1900"] fn f() { } = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: the `link_name` attribute cannot be used on structs - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:603:7 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:608:7 | LL | #[link_name = "1900"] struct S; | ^^^^^^^^^ @@ -845,7 +853,7 @@ LL | #[link_name = "1900"] struct S; = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: the `link_name` attribute cannot be used on type aliases - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:609:7 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:614:7 | LL | #[link_name = "1900"] type T = S; | ^^^^^^^^^ @@ -854,7 +862,7 @@ LL | #[link_name = "1900"] type T = S; = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: the `link_name` attribute cannot be used on inherent impl blocks - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:615:7 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:620:7 | LL | #[link_name = "1900"] impl S { } | ^^^^^^^^^ @@ -863,7 +871,7 @@ LL | #[link_name = "1900"] impl S { } = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: the `link_section` attribute cannot be used on modules - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:622:3 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:627:3 | LL | #[link_section = ",1800"] | ^^^^^^^^^^^^ @@ -872,7 +880,7 @@ LL | #[link_section = ",1800"] = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: the `link_section` attribute cannot be used on modules - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:628:20 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:633:20 | LL | mod inner { #![link_section=",1800"] } | ^^^^^^^^^^^^ @@ -881,7 +889,7 @@ LL | mod inner { #![link_section=",1800"] } = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: the `link_section` attribute cannot be used on structs - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:636:7 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:641:7 | LL | #[link_section = ",1800"] struct S; | ^^^^^^^^^^^^ @@ -890,7 +898,7 @@ LL | #[link_section = ",1800"] struct S; = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: the `link_section` attribute cannot be used on type aliases - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:642:7 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:647:7 | LL | #[link_section = ",1800"] type T = S; | ^^^^^^^^^^^^ @@ -899,7 +907,7 @@ LL | #[link_section = ",1800"] type T = S; = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: the `link_section` attribute cannot be used on inherent impl blocks - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:648:7 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:653:7 | LL | #[link_section = ",1800"] impl S { } | ^^^^^^^^^^^^ @@ -908,7 +916,7 @@ LL | #[link_section = ",1800"] impl S { } = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: the `link_section` attribute cannot be used on traits - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:654:7 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:659:7 | LL | #[link_section = ",1800"] | ^^^^^^^^^^^^ @@ -917,7 +925,7 @@ LL | #[link_section = ",1800"] = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: the `link` attribute cannot be used on modules - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:688:3 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:693:3 | LL | #[link(name = "x")] | ^^^^ @@ -926,7 +934,7 @@ LL | #[link(name = "x")] = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: the `link` attribute cannot be used on modules - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:694:20 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:699:20 | LL | mod inner { #![link(name = "x")] } | ^^^^ @@ -935,7 +943,7 @@ LL | mod inner { #![link(name = "x")] } = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: the `link` attribute cannot be used on functions - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:700:7 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:705:7 | LL | #[link(name = "x")] fn f() { } | ^^^^ @@ -944,7 +952,7 @@ LL | #[link(name = "x")] fn f() { } = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: the `link` attribute cannot be used on structs - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:706:7 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:711:7 | LL | #[link(name = "x")] struct S; | ^^^^ @@ -953,7 +961,7 @@ LL | #[link(name = "x")] struct S; = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: the `link` attribute cannot be used on type aliases - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:712:7 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:717:7 | LL | #[link(name = "x")] type T = S; | ^^^^ @@ -962,7 +970,7 @@ LL | #[link(name = "x")] type T = S; = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: the `link` attribute cannot be used on inherent impl blocks - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:718:7 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:723:7 | LL | #[link(name = "x")] impl S { } | ^^^^ @@ -971,7 +979,7 @@ LL | #[link(name = "x")] impl S { } = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: the `must_use` attribute cannot be used on modules - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:744:3 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:749:3 | LL | #[must_use] | ^^^^^^^^ @@ -980,7 +988,7 @@ LL | #[must_use] = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: the `must_use` attribute cannot be used on modules - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:749:20 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:754:20 | LL | mod inner { #![must_use] } | ^^^^^^^^ @@ -989,7 +997,7 @@ LL | mod inner { #![must_use] } = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: the `must_use` attribute cannot be used on type aliases - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:758:7 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:763:7 | LL | #[must_use] type T = S; | ^^^^^^^^ @@ -998,7 +1006,7 @@ LL | #[must_use] type T = S; = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: the `must_use` attribute cannot be used on inherent impl blocks - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:763:7 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:768:7 | LL | #[must_use] impl S { } | ^^^^^^^^ @@ -1007,13 +1015,13 @@ LL | #[must_use] impl S { } = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![windows_subsystem]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:769:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:774:1 | LL | #[windows_subsystem = "windows"] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: this attribute does not have an `!`, which means it is applied to this module - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:771:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:776:1 | LL | / mod windows_subsystem { LL | | @@ -1023,67 +1031,67 @@ LL | | } | |_^ warning: the `#![windows_subsystem]` attribute can only be used at the crate root - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:773:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:778:17 | LL | mod inner { #![windows_subsystem="windows"] } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![windows_subsystem]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:776:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:781:5 | LL | #[windows_subsystem = "windows"] fn f() { } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: this attribute does not have an `!`, which means it is applied to this function - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:776:38 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:781:38 | LL | #[windows_subsystem = "windows"] fn f() { } | ^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![windows_subsystem]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:780:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:785:5 | LL | #[windows_subsystem = "windows"] struct S; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: this attribute does not have an `!`, which means it is applied to this struct - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:780:38 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:785:38 | LL | #[windows_subsystem = "windows"] struct S; | ^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![windows_subsystem]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:784:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:789:5 | LL | #[windows_subsystem = "windows"] type T = S; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: this attribute does not have an `!`, which means it is applied to this type alias - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:784:38 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:789:38 | LL | #[windows_subsystem = "windows"] type T = S; | ^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![windows_subsystem]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:788:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:793:5 | LL | #[windows_subsystem = "windows"] impl S { } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: this attribute does not have an `!`, which means it is applied to this implementation block - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:788:38 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:793:38 | LL | #[windows_subsystem = "windows"] impl S { } | ^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![crate_name]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:795:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:800:1 | LL | #[crate_name = "0900"] | ^^^^^^^^^^^^^^^^^^^^^^ | note: this attribute does not have an `!`, which means it is applied to this module - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:797:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:802:1 | LL | / mod crate_name { LL | | @@ -1093,67 +1101,67 @@ LL | | } | |_^ warning: the `#![crate_name]` attribute can only be used at the crate root - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:799:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:804:17 | LL | mod inner { #![crate_name="0900"] } | ^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![crate_name]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:802:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:807:5 | LL | #[crate_name = "0900"] fn f() { } | ^^^^^^^^^^^^^^^^^^^^^^ | note: this attribute does not have an `!`, which means it is applied to this function - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:802:28 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:807:28 | LL | #[crate_name = "0900"] fn f() { } | ^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![crate_name]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:806:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:811:5 | LL | #[crate_name = "0900"] struct S; | ^^^^^^^^^^^^^^^^^^^^^^ | note: this attribute does not have an `!`, which means it is applied to this struct - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:806:28 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:811:28 | LL | #[crate_name = "0900"] struct S; | ^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![crate_name]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:810:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:815:5 | LL | #[crate_name = "0900"] type T = S; | ^^^^^^^^^^^^^^^^^^^^^^ | note: this attribute does not have an `!`, which means it is applied to this type alias - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:810:28 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:815:28 | LL | #[crate_name = "0900"] type T = S; | ^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![crate_name]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:814:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:819:5 | LL | #[crate_name = "0900"] impl S { } | ^^^^^^^^^^^^^^^^^^^^^^ | note: this attribute does not have an `!`, which means it is applied to this implementation block - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:814:28 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:819:28 | LL | #[crate_name = "0900"] impl S { } | ^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![crate_type]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:819:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:824:1 | LL | #[crate_type = "0800"] | ^^^^^^^^^^^^^^^^^^^^^^ | note: this attribute does not have an `!`, which means it is applied to this module - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:821:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:826:1 | LL | / mod crate_type { LL | | @@ -1163,67 +1171,67 @@ LL | | } | |_^ warning: the `#![crate_type]` attribute can only be used at the crate root - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:823:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:828:17 | LL | mod inner { #![crate_type="0800"] } | ^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![crate_type]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:826:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:831:5 | LL | #[crate_type = "0800"] fn f() { } | ^^^^^^^^^^^^^^^^^^^^^^ | note: this attribute does not have an `!`, which means it is applied to this function - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:826:28 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:831:28 | LL | #[crate_type = "0800"] fn f() { } | ^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![crate_type]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:830:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:835:5 | LL | #[crate_type = "0800"] struct S; | ^^^^^^^^^^^^^^^^^^^^^^ | note: this attribute does not have an `!`, which means it is applied to this struct - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:830:28 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:835:28 | LL | #[crate_type = "0800"] struct S; | ^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![crate_type]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:834:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:839:5 | LL | #[crate_type = "0800"] type T = S; | ^^^^^^^^^^^^^^^^^^^^^^ | note: this attribute does not have an `!`, which means it is applied to this type alias - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:834:28 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:839:28 | LL | #[crate_type = "0800"] type T = S; | ^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![crate_type]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:838:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:843:5 | LL | #[crate_type = "0800"] impl S { } | ^^^^^^^^^^^^^^^^^^^^^^ | note: this attribute does not have an `!`, which means it is applied to this implementation block - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:838:28 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:843:28 | LL | #[crate_type = "0800"] impl S { } | ^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![feature]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:843:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:848:1 | LL | #[feature(x0600)] | ^^^^^^^^^^^^^^^^^ | note: this attribute does not have an `!`, which means it is applied to this module - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:845:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:850:1 | LL | / mod feature { LL | | @@ -1233,67 +1241,67 @@ LL | | } | |_^ warning: the `#![feature]` attribute can only be used at the crate root - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:847:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:852:17 | LL | mod inner { #![feature(x0600)] } | ^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![feature]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:850:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:855:5 | LL | #[feature(x0600)] fn f() { } | ^^^^^^^^^^^^^^^^^ | note: this attribute does not have an `!`, which means it is applied to this function - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:850:23 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:855:23 | LL | #[feature(x0600)] fn f() { } | ^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![feature]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:854:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:859:5 | LL | #[feature(x0600)] struct S; | ^^^^^^^^^^^^^^^^^ | note: this attribute does not have an `!`, which means it is applied to this struct - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:854:23 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:859:23 | LL | #[feature(x0600)] struct S; | ^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![feature]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:858:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:863:5 | LL | #[feature(x0600)] type T = S; | ^^^^^^^^^^^^^^^^^ | note: this attribute does not have an `!`, which means it is applied to this type alias - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:858:23 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:863:23 | LL | #[feature(x0600)] type T = S; | ^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![feature]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:862:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:867:5 | LL | #[feature(x0600)] impl S { } | ^^^^^^^^^^^^^^^^^ | note: this attribute does not have an `!`, which means it is applied to this implementation block - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:862:23 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:867:23 | LL | #[feature(x0600)] impl S { } | ^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![no_main]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:868:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:873:1 | LL | #[no_main] | ^^^^^^^^^^ | note: this attribute does not have an `!`, which means it is applied to this module - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:870:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:875:1 | LL | / mod no_main_1 { LL | | @@ -1303,67 +1311,67 @@ LL | | } | |_^ warning: the `#![no_main]` attribute can only be used at the crate root - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:872:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:877:17 | LL | mod inner { #![no_main] } | ^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![no_main]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:875:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:880:5 | LL | #[no_main] fn f() { } | ^^^^^^^^^^ | note: this attribute does not have an `!`, which means it is applied to this function - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:875:16 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:880:16 | LL | #[no_main] fn f() { } | ^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![no_main]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:879:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:884:5 | LL | #[no_main] struct S; | ^^^^^^^^^^ | note: this attribute does not have an `!`, which means it is applied to this struct - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:879:16 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:884:16 | LL | #[no_main] struct S; | ^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![no_main]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:883:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:888:5 | LL | #[no_main] type T = S; | ^^^^^^^^^^ | note: this attribute does not have an `!`, which means it is applied to this type alias - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:883:16 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:888:16 | LL | #[no_main] type T = S; | ^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![no_main]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:887:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:892:5 | LL | #[no_main] impl S { } | ^^^^^^^^^^ | note: this attribute does not have an `!`, which means it is applied to this implementation block - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:887:16 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:892:16 | LL | #[no_main] impl S { } | ^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![no_builtins]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:892:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:897:1 | LL | #[no_builtins] | ^^^^^^^^^^^^^^ | note: this attribute does not have an `!`, which means it is applied to this module - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:894:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:899:1 | LL | / mod no_builtins { LL | | @@ -1373,67 +1381,67 @@ LL | | } | |_^ warning: the `#![no_builtins]` attribute can only be used at the crate root - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:896:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:901:17 | LL | mod inner { #![no_builtins] } | ^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![no_builtins]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:899:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:904:5 | LL | #[no_builtins] fn f() { } | ^^^^^^^^^^^^^^ | note: this attribute does not have an `!`, which means it is applied to this function - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:899:20 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:904:20 | LL | #[no_builtins] fn f() { } | ^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![no_builtins]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:903:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:908:5 | LL | #[no_builtins] struct S; | ^^^^^^^^^^^^^^ | note: this attribute does not have an `!`, which means it is applied to this struct - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:903:20 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:908:20 | LL | #[no_builtins] struct S; | ^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![no_builtins]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:907:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:912:5 | LL | #[no_builtins] type T = S; | ^^^^^^^^^^^^^^ | note: this attribute does not have an `!`, which means it is applied to this type alias - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:907:20 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:912:20 | LL | #[no_builtins] type T = S; | ^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![no_builtins]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:911:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:916:5 | LL | #[no_builtins] impl S { } | ^^^^^^^^^^^^^^ | note: this attribute does not have an `!`, which means it is applied to this implementation block - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:911:20 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:916:20 | LL | #[no_builtins] impl S { } | ^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![recursion_limit]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:916:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:921:1 | LL | #[recursion_limit="0200"] | ^^^^^^^^^^^^^^^^^^^^^^^^^ | note: this attribute does not have an `!`, which means it is applied to this module - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:918:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:923:1 | LL | / mod recursion_limit { LL | | @@ -1443,67 +1451,67 @@ LL | | } | |_^ warning: the `#![recursion_limit]` attribute can only be used at the crate root - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:920:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:925:17 | LL | mod inner { #![recursion_limit="0200"] } | ^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![recursion_limit]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:923:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:928:5 | LL | #[recursion_limit="0200"] fn f() { } | ^^^^^^^^^^^^^^^^^^^^^^^^^ | note: this attribute does not have an `!`, which means it is applied to this function - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:923:31 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:928:31 | LL | #[recursion_limit="0200"] fn f() { } | ^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![recursion_limit]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:927:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:932:5 | LL | #[recursion_limit="0200"] struct S; | ^^^^^^^^^^^^^^^^^^^^^^^^^ | note: this attribute does not have an `!`, which means it is applied to this struct - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:927:31 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:932:31 | LL | #[recursion_limit="0200"] struct S; | ^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![recursion_limit]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:931:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:936:5 | LL | #[recursion_limit="0200"] type T = S; | ^^^^^^^^^^^^^^^^^^^^^^^^^ | note: this attribute does not have an `!`, which means it is applied to this type alias - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:931:31 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:936:31 | LL | #[recursion_limit="0200"] type T = S; | ^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![recursion_limit]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:935:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:940:5 | LL | #[recursion_limit="0200"] impl S { } | ^^^^^^^^^^^^^^^^^^^^^^^^^ | note: this attribute does not have an `!`, which means it is applied to this implementation block - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:935:31 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:940:31 | LL | #[recursion_limit="0200"] impl S { } | ^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![type_length_limit]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:940:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:945:1 | LL | #[type_length_limit="0100"] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: this attribute does not have an `!`, which means it is applied to this module - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:942:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:947:1 | LL | / mod type_length_limit { LL | | @@ -1513,61 +1521,61 @@ LL | | } | |_^ warning: the `#![type_length_limit]` attribute can only be used at the crate root - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:944:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:949:17 | LL | mod inner { #![type_length_limit="0100"] } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![type_length_limit]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:947:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:952:5 | LL | #[type_length_limit="0100"] fn f() { } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: this attribute does not have an `!`, which means it is applied to this function - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:947:33 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:952:33 | LL | #[type_length_limit="0100"] fn f() { } | ^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![type_length_limit]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:951:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:956:5 | LL | #[type_length_limit="0100"] struct S; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: this attribute does not have an `!`, which means it is applied to this struct - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:951:33 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:956:33 | LL | #[type_length_limit="0100"] struct S; | ^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![type_length_limit]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:955:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:960:5 | LL | #[type_length_limit="0100"] type T = S; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: this attribute does not have an `!`, which means it is applied to this type alias - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:955:33 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:960:33 | LL | #[type_length_limit="0100"] type T = S; | ^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![type_length_limit]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:959:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:964:5 | LL | #[type_length_limit="0100"] impl S { } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: this attribute does not have an `!`, which means it is applied to this implementation block - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:959:33 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:964:33 | LL | #[type_length_limit="0100"] impl S { } | ^^^^^^^^^^ warning: the `no_mangle` attribute cannot be used on required trait methods - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:361:11 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:366:11 | LL | #[no_mangle] fn foo(); | ^^^^^^^^^ @@ -1576,7 +1584,7 @@ LL | #[no_mangle] fn foo(); = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: the `no_mangle` attribute cannot be used on provided trait methods - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:367:11 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:372:11 | LL | #[no_mangle] fn bar() {} | ^^^^^^^^^ @@ -1585,7 +1593,7 @@ LL | #[no_mangle] fn bar() {} = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: the `link_section` attribute cannot be used on required trait methods - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:660:11 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:665:11 | LL | #[link_section = ",1800"] | ^^^^^^^^^^^^ @@ -1593,5 +1601,5 @@ LL | #[link_section = ",1800"] = help: the `link_section` attribute can be applied to functions with a body and statics = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! -warning: 170 warnings emitted +warning: 171 warnings emitted