Skip inner ordering checking in presence of #[repr(…)] (#14610)

A representation attribute `#[repr(…)]` might indicate that the ordering
of the fields or the variants is dictated by the API the code is
interfacing with. Better not lint with `arbitrary_source_item_ordering`
in this case.

changelog: [`arbitrary_source_item_ordering`]: do not lint inside items
with `#[repr]` attribute
This commit is contained in:
Samuel Tardieu 2025-05-16 19:34:32 +00:00 committed by GitHub
commit dcd8bb6d7e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 192 additions and 77 deletions

View file

@ -6,9 +6,10 @@ use clippy_config::types::{
};
use clippy_utils::diagnostics::span_lint_and_note;
use clippy_utils::is_cfg_test;
use rustc_attr_parsing::AttributeKind;
use rustc_hir::{
AssocItemKind, FieldDef, HirId, ImplItemRef, IsAuto, Item, ItemKind, Mod, QPath, TraitItemRef, TyKind, Variant,
VariantData,
AssocItemKind, Attribute, FieldDef, HirId, ImplItemRef, IsAuto, Item, ItemKind, Mod, QPath, TraitItemRef, TyKind,
Variant, VariantData,
};
use rustc_lint::{LateContext, LateLintPass, LintContext};
use rustc_session::impl_lint_pass;
@ -28,6 +29,11 @@ declare_clippy_lint! {
/// implemented in the code. Sometimes this will be referred to as
/// "bikeshedding".
///
/// The content of items with a representation clause attribute, such as
/// `#[repr(C)]` will not be checked, as the order of their fields or
/// variants might be dictated by an external API (application binary
/// interface).
///
/// ### Default Ordering and Configuration
///
/// As there is no generally applicable rule, and each project may have
@ -256,6 +262,15 @@ impl ArbitrarySourceItemOrdering {
impl<'tcx> LateLintPass<'tcx> for ArbitrarySourceItemOrdering {
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) {
if cx
.tcx
.hir_attrs(item.hir_id())
.iter()
.any(|attr| matches!(attr, Attribute::Parsed(AttributeKind::Repr(..))))
{
// Do not lint items with a `#[repr]` attribute as their layout may be imposed by an external API.
return;
}
match &item.kind {
ItemKind::Enum(_, enum_def, _generics) if self.enable_ordering_for_enum => {
let mut cur_v: Option<&Variant<'_>> = None;