about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.md4
-rw-r--r--book/src/lint_configuration.md30
-rw-r--r--clippy_config/src/conf.rs38
-rw-r--r--clippy_config/src/types.rs301
-rw-r--r--clippy_lints/src/arbitrary_source_item_ordering.rs531
-rw-r--r--clippy_lints/src/declared_lints.rs1
-rw-r--r--clippy_lints/src/lib.rs2
-rw-r--r--tests/ui-toml/arbitrary_source_item_ordering/bad_conf_1/clippy.toml1
-rw-r--r--tests/ui-toml/arbitrary_source_item_ordering/bad_conf_2/clippy.toml1
-rw-r--r--tests/ui-toml/arbitrary_source_item_ordering/bad_conf_3/clippy.toml1
-rw-r--r--tests/ui-toml/arbitrary_source_item_ordering/default/clippy.toml0
-rw-r--r--tests/ui-toml/arbitrary_source_item_ordering/default_exp/clippy.toml12
-rw-r--r--tests/ui-toml/arbitrary_source_item_ordering/only_enum/clippy.toml1
-rw-r--r--tests/ui-toml/arbitrary_source_item_ordering/only_impl/clippy.toml1
-rw-r--r--tests/ui-toml/arbitrary_source_item_ordering/only_trait/clippy.toml1
-rw-r--r--tests/ui-toml/arbitrary_source_item_ordering/ordering_good.bad_conf_1.stderr8
-rw-r--r--tests/ui-toml/arbitrary_source_item_ordering/ordering_good.bad_conf_2.stderr8
-rw-r--r--tests/ui-toml/arbitrary_source_item_ordering/ordering_good.bad_conf_3.stderr8
-rw-r--r--tests/ui-toml/arbitrary_source_item_ordering/ordering_good.rs186
-rw-r--r--tests/ui-toml/arbitrary_source_item_ordering/ordering_good_var_1.rs174
-rw-r--r--tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.default.stderr226
-rw-r--r--tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs185
-rw-r--r--tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.rs174
-rw-r--r--tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.var_1.stderr100
-rw-r--r--tests/ui-toml/arbitrary_source_item_ordering/ordering_only_enum.only_enum.stderr16
-rw-r--r--tests/ui-toml/arbitrary_source_item_ordering/ordering_only_enum.rs43
-rw-r--r--tests/ui-toml/arbitrary_source_item_ordering/ordering_only_impl.only_impl.stderr40
-rw-r--r--tests/ui-toml/arbitrary_source_item_ordering/ordering_only_impl.rs67
-rw-r--r--tests/ui-toml/arbitrary_source_item_ordering/ordering_only_trait.only_trait.stderr40
-rw-r--r--tests/ui-toml/arbitrary_source_item_ordering/ordering_only_trait.rs48
-rw-r--r--tests/ui-toml/arbitrary_source_item_ordering/var_1/clippy.toml1
-rw-r--r--tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr9
32 files changed, 2257 insertions, 1 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index f3a42083aa4..161fa630ed4 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -5331,6 +5331,7 @@ Released 2018-09-13
 [`almost_complete_range`]: https://rust-lang.github.io/rust-clippy/master/index.html#almost_complete_range
 [`almost_swapped`]: https://rust-lang.github.io/rust-clippy/master/index.html#almost_swapped
 [`approx_constant`]: https://rust-lang.github.io/rust-clippy/master/index.html#approx_constant
+[`arbitrary_source_item_ordering`]: https://rust-lang.github.io/rust-clippy/master/index.html#arbitrary_source_item_ordering
 [`arc_with_non_send_sync`]: https://rust-lang.github.io/rust-clippy/master/index.html#arc_with_non_send_sync
 [`arithmetic_side_effects`]: https://rust-lang.github.io/rust-clippy/master/index.html#arithmetic_side_effects
 [`as_conversions`]: https://rust-lang.github.io/rust-clippy/master/index.html#as_conversions
@@ -6208,12 +6209,14 @@ Released 2018-09-13
 [`max-trait-bounds`]: https://doc.rust-lang.org/clippy/lint_configuration.html#max-trait-bounds
 [`min-ident-chars-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#min-ident-chars-threshold
 [`missing-docs-in-crate-items`]: https://doc.rust-lang.org/clippy/lint_configuration.html#missing-docs-in-crate-items
+[`module-item-order-groupings`]: https://doc.rust-lang.org/clippy/lint_configuration.html#module-item-order-groupings
 [`msrv`]: https://doc.rust-lang.org/clippy/lint_configuration.html#msrv
 [`pass-by-value-size-limit`]: https://doc.rust-lang.org/clippy/lint_configuration.html#pass-by-value-size-limit
 [`pub-underscore-fields-behavior`]: https://doc.rust-lang.org/clippy/lint_configuration.html#pub-underscore-fields-behavior
 [`semicolon-inside-block-ignore-singleline`]: https://doc.rust-lang.org/clippy/lint_configuration.html#semicolon-inside-block-ignore-singleline
 [`semicolon-outside-block-ignore-multiline`]: https://doc.rust-lang.org/clippy/lint_configuration.html#semicolon-outside-block-ignore-multiline
 [`single-char-binding-names-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#single-char-binding-names-threshold
+[`source-item-ordering`]: https://doc.rust-lang.org/clippy/lint_configuration.html#source-item-ordering
 [`stack-size-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#stack-size-threshold
 [`standard-macro-braces`]: https://doc.rust-lang.org/clippy/lint_configuration.html#standard-macro-braces
 [`struct-field-name-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#struct-field-name-threshold
@@ -6221,6 +6224,7 @@ Released 2018-09-13
 [`too-large-for-stack`]: https://doc.rust-lang.org/clippy/lint_configuration.html#too-large-for-stack
 [`too-many-arguments-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#too-many-arguments-threshold
 [`too-many-lines-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#too-many-lines-threshold
+[`trait-assoc-item-kinds-order`]: https://doc.rust-lang.org/clippy/lint_configuration.html#trait-assoc-item-kinds-order
 [`trivial-copy-size-limit`]: https://doc.rust-lang.org/clippy/lint_configuration.html#trivial-copy-size-limit
 [`type-complexity-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#type-complexity-threshold
 [`unnecessary-box-size`]: https://doc.rust-lang.org/clippy/lint_configuration.html#unnecessary-box-size
diff --git a/book/src/lint_configuration.md b/book/src/lint_configuration.md
index c1ede651fc5..0973acfee2d 100644
--- a/book/src/lint_configuration.md
+++ b/book/src/lint_configuration.md
@@ -666,6 +666,16 @@ crate. For example, `pub(crate)` items.
 * [`missing_docs_in_private_items`](https://rust-lang.github.io/rust-clippy/master/index.html#missing_docs_in_private_items)
 
 
+## `module-item-order-groupings`
+The named groupings of different source item kinds within modules.
+
+**Default Value:** `[["modules", ["extern_crate", "mod", "foreign_mod"]], ["use", ["use"]], ["macros", ["macro"]], ["global_asm", ["global_asm"]], ["UPPER_SNAKE_CASE", ["static", "const"]], ["PascalCase", ["ty_alias", "enum", "struct", "union", "trait", "trait_alias", "impl"]], ["lower_snake_case", ["fn"]]]`
+
+---
+**Affected lints:**
+* [`arbitrary_source_item_ordering`](https://rust-lang.github.io/rust-clippy/master/index.html#arbitrary_source_item_ordering)
+
+
 ## `msrv`
 The minimum rust version that the project supports. Defaults to the `rust-version` field in `Cargo.toml`
 
@@ -784,6 +794,16 @@ The maximum number of single char bindings a scope may have
 * [`many_single_char_names`](https://rust-lang.github.io/rust-clippy/master/index.html#many_single_char_names)
 
 
+## `source-item-ordering`
+Which kind of elements should be ordered internally, possible values being `enum`, `impl`, `module`, `struct`, `trait`.
+
+**Default Value:** `["enum", "impl", "module", "struct", "trait"]`
+
+---
+**Affected lints:**
+* [`arbitrary_source_item_ordering`](https://rust-lang.github.io/rust-clippy/master/index.html#arbitrary_source_item_ordering)
+
+
 ## `stack-size-threshold`
 The maximum allowed stack size for functions in bytes
 
@@ -863,6 +883,16 @@ The maximum number of lines a function or method can have
 * [`too_many_lines`](https://rust-lang.github.io/rust-clippy/master/index.html#too_many_lines)
 
 
+## `trait-assoc-item-kinds-order`
+The order of associated items in traits.
+
+**Default Value:** `["const", "type", "fn"]`
+
+---
+**Affected lints:**
+* [`arbitrary_source_item_ordering`](https://rust-lang.github.io/rust-clippy/master/index.html#arbitrary_source_item_ordering)
+
+
 ## `trivial-copy-size-limit`
 The maximum size (in bytes) to consider a `Copy` type for passing by value instead of by
 reference. By default there is no limit
diff --git a/clippy_config/src/conf.rs b/clippy_config/src/conf.rs
index 26f156a0bbc..428318a1dd0 100644
--- a/clippy_config/src/conf.rs
+++ b/clippy_config/src/conf.rs
@@ -1,6 +1,10 @@
 use crate::ClippyConfiguration;
 use crate::msrvs::Msrv;
-use crate::types::{DisallowedPath, MacroMatcher, MatchLintBehaviour, PubUnderscoreFieldsBehaviour, Rename};
+use crate::types::{
+    DisallowedPath, MacroMatcher, MatchLintBehaviour, PubUnderscoreFieldsBehaviour, Rename, SourceItemOrdering,
+    SourceItemOrderingCategory, SourceItemOrderingModuleItemGroupings, SourceItemOrderingModuleItemKind,
+    SourceItemOrderingTraitAssocItemKind, SourceItemOrderingTraitAssocItemKinds,
+};
 use rustc_errors::Applicability;
 use rustc_session::Session;
 use rustc_span::edit_distance::edit_distance;
@@ -47,6 +51,29 @@ const DEFAULT_ALLOWED_IDENTS_BELOW_MIN_CHARS: &[&str] = &["i", "j", "x", "y", "z
 const DEFAULT_ALLOWED_PREFIXES: &[&str] = &["to", "as", "into", "from", "try_into", "try_from"];
 const DEFAULT_ALLOWED_TRAITS_WITH_RENAMED_PARAMS: &[&str] =
     &["core::convert::From", "core::convert::TryFrom", "core::str::FromStr"];
+const DEFAULT_MODULE_ITEM_ORDERING_GROUPS: &[(&str, &[SourceItemOrderingModuleItemKind])] = {
+    #[allow(clippy::enum_glob_use)] // Very local glob use for legibility.
+    use SourceItemOrderingModuleItemKind::*;
+    &[
+        ("modules", &[ExternCrate, Mod, ForeignMod]),
+        ("use", &[Use]),
+        ("macros", &[Macro]),
+        ("global_asm", &[GlobalAsm]),
+        ("UPPER_SNAKE_CASE", &[Static, Const]),
+        ("PascalCase", &[TyAlias, Enum, Struct, Union, Trait, TraitAlias, Impl]),
+        ("lower_snake_case", &[Fn]),
+    ]
+};
+const DEFAULT_TRAIT_ASSOC_ITEM_KINDS_ORDER: &[SourceItemOrderingTraitAssocItemKind] = {
+    #[allow(clippy::enum_glob_use)] // Very local glob use for legibility.
+    use SourceItemOrderingTraitAssocItemKind::*;
+    &[Const, Type, Fn]
+};
+const DEFAULT_SOURCE_ITEM_ORDERING: &[SourceItemOrderingCategory] = {
+    #[allow(clippy::enum_glob_use)] // Very local glob use for legibility.
+    use SourceItemOrderingCategory::*;
+    &[Enum, Impl, Module, Struct, Trait]
+};
 
 /// Conf with parse errors
 #[derive(Default)]
@@ -533,6 +560,9 @@ define_Conf! {
     /// crate. For example, `pub(crate)` items.
     #[lints(missing_docs_in_private_items)]
     missing_docs_in_crate_items: bool = false,
+    /// The named groupings of different source item kinds within modules.
+    #[lints(arbitrary_source_item_ordering)]
+    module_item_order_groupings: SourceItemOrderingModuleItemGroupings = DEFAULT_MODULE_ITEM_ORDERING_GROUPS.into(),
     /// The minimum rust version that the project supports. Defaults to the `rust-version` field in `Cargo.toml`
     #[default_text = "current version"]
     #[lints(
@@ -612,6 +642,9 @@ define_Conf! {
     /// The maximum number of single char bindings a scope may have
     #[lints(many_single_char_names)]
     single_char_binding_names_threshold: u64 = 4,
+    /// Which kind of elements should be ordered internally, possible values being `enum`, `impl`, `module`, `struct`, `trait`.
+    #[lints(arbitrary_source_item_ordering)]
+    source_item_ordering: SourceItemOrdering = DEFAULT_SOURCE_ITEM_ORDERING.into(),
     /// The maximum allowed stack size for functions in bytes
     #[lints(large_stack_frames)]
     stack_size_threshold: u64 = 512_000,
@@ -641,6 +674,9 @@ define_Conf! {
     /// The maximum number of lines a function or method can have
     #[lints(too_many_lines)]
     too_many_lines_threshold: u64 = 100,
+    /// The order of associated items in traits.
+    #[lints(arbitrary_source_item_ordering)]
+    trait_assoc_item_kinds_order: SourceItemOrderingTraitAssocItemKinds = DEFAULT_TRAIT_ASSOC_ITEM_KINDS_ORDER.into(),
     /// The maximum size (in bytes) to consider a `Copy` type for passing by value instead of by
     /// reference. By default there is no limit
     #[default_text = "target_pointer_width * 2"]
diff --git a/clippy_config/src/types.rs b/clippy_config/src/types.rs
index bab63911182..fe576424148 100644
--- a/clippy_config/src/types.rs
+++ b/clippy_config/src/types.rs
@@ -1,5 +1,6 @@
 use serde::de::{self, Deserializer, Visitor};
 use serde::{Deserialize, Serialize, ser};
+use std::collections::HashMap;
 use std::fmt;
 
 #[derive(Debug, Deserialize)]
@@ -102,6 +103,306 @@ impl<'de> Deserialize<'de> for MacroMatcher {
     }
 }
 
+/// Represents the item categories that can be ordered by the source ordering lint.
+#[derive(Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
+#[serde(rename_all = "snake_case")]
+pub enum SourceItemOrderingCategory {
+    Enum,
+    Impl,
+    Module,
+    Struct,
+    Trait,
+}
+
+/// Represents which item categories are enabled for ordering.
+///
+/// The [`Deserialize`] implementation checks that there are no duplicates in
+/// the user configuration.
+pub struct SourceItemOrdering(Vec<SourceItemOrderingCategory>);
+
+impl SourceItemOrdering {
+    pub fn contains(&self, category: &SourceItemOrderingCategory) -> bool {
+        self.0.contains(category)
+    }
+}
+
+impl<T> From<T> for SourceItemOrdering
+where
+    T: Into<Vec<SourceItemOrderingCategory>>,
+{
+    fn from(value: T) -> Self {
+        Self(value.into())
+    }
+}
+
+impl core::fmt::Debug for SourceItemOrdering {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        self.0.fmt(f)
+    }
+}
+
+impl<'de> Deserialize<'de> for SourceItemOrdering {
+    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
+    where
+        D: Deserializer<'de>,
+    {
+        let items = Vec::<SourceItemOrderingCategory>::deserialize(deserializer)?;
+        let mut items_set = std::collections::HashSet::new();
+
+        for item in &items {
+            if items_set.contains(item) {
+                return Err(de::Error::custom(format!(
+                    "The category \"{item:?}\" was enabled more than once in the source ordering configuration."
+                )));
+            }
+            items_set.insert(item);
+        }
+
+        Ok(Self(items))
+    }
+}
+
+impl Serialize for SourceItemOrdering {
+    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
+    where
+        S: ser::Serializer,
+    {
+        self.0.serialize(serializer)
+    }
+}
+
+/// Represents the items that can occur within a module.
+#[derive(Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
+#[serde(rename_all = "snake_case")]
+pub enum SourceItemOrderingModuleItemKind {
+    ExternCrate,
+    Mod,
+    ForeignMod,
+    Use,
+    Macro,
+    GlobalAsm,
+    Static,
+    Const,
+    TyAlias,
+    Enum,
+    Struct,
+    Union,
+    Trait,
+    TraitAlias,
+    Impl,
+    Fn,
+}
+
+impl SourceItemOrderingModuleItemKind {
+    pub fn all_variants() -> Vec<Self> {
+        #[allow(clippy::enum_glob_use)] // Very local glob use for legibility.
+        use SourceItemOrderingModuleItemKind::*;
+        vec![
+            ExternCrate,
+            Mod,
+            ForeignMod,
+            Use,
+            Macro,
+            GlobalAsm,
+            Static,
+            Const,
+            TyAlias,
+            Enum,
+            Struct,
+            Union,
+            Trait,
+            TraitAlias,
+            Impl,
+            Fn,
+        ]
+    }
+}
+
+/// Represents the configured ordering of items within a module.
+///
+/// The [`Deserialize`] implementation checks that no item kinds have been
+/// omitted and that there are no duplicates in the user configuration.
+#[derive(Clone)]
+pub struct SourceItemOrderingModuleItemGroupings {
+    groups: Vec<(String, Vec<SourceItemOrderingModuleItemKind>)>,
+    lut: HashMap<SourceItemOrderingModuleItemKind, usize>,
+}
+
+impl SourceItemOrderingModuleItemGroupings {
+    fn build_lut(
+        groups: &[(String, Vec<SourceItemOrderingModuleItemKind>)],
+    ) -> HashMap<SourceItemOrderingModuleItemKind, usize> {
+        let mut lut = HashMap::new();
+        for (group_index, (_, items)) in groups.iter().enumerate() {
+            for item in items {
+                lut.insert(item.clone(), group_index);
+            }
+        }
+        lut
+    }
+
+    pub fn module_level_order_of(&self, item: &SourceItemOrderingModuleItemKind) -> Option<usize> {
+        self.lut.get(item).copied()
+    }
+}
+
+impl From<&[(&str, &[SourceItemOrderingModuleItemKind])]> for SourceItemOrderingModuleItemGroupings {
+    fn from(value: &[(&str, &[SourceItemOrderingModuleItemKind])]) -> Self {
+        let groups: Vec<(String, Vec<SourceItemOrderingModuleItemKind>)> =
+            value.iter().map(|item| (item.0.to_string(), item.1.to_vec())).collect();
+        let lut = Self::build_lut(&groups);
+        Self { groups, lut }
+    }
+}
+
+impl core::fmt::Debug for SourceItemOrderingModuleItemGroupings {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        self.groups.fmt(f)
+    }
+}
+
+impl<'de> Deserialize<'de> for SourceItemOrderingModuleItemGroupings {
+    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
+    where
+        D: Deserializer<'de>,
+    {
+        let groups = Vec::<(String, Vec<SourceItemOrderingModuleItemKind>)>::deserialize(deserializer)?;
+        let items_total: usize = groups.iter().map(|(_, v)| v.len()).sum();
+        let lut = Self::build_lut(&groups);
+
+        let mut expected_items = SourceItemOrderingModuleItemKind::all_variants();
+        for item in lut.keys() {
+            expected_items.retain(|i| i != item);
+        }
+
+        let all_items = SourceItemOrderingModuleItemKind::all_variants();
+        if expected_items.is_empty() && items_total == all_items.len() {
+            let Some(use_group_index) = lut.get(&SourceItemOrderingModuleItemKind::Use) else {
+                return Err(de::Error::custom("Error in internal LUT."));
+            };
+            let Some((_, use_group_items)) = groups.get(*use_group_index) else {
+                return Err(de::Error::custom("Error in internal LUT."));
+            };
+            if use_group_items.len() > 1 {
+                return Err(de::Error::custom(
+                    "The group containing the \"use\" item kind may not contain any other item kinds. \
+                    The \"use\" items will (generally) be sorted by rustfmt already. \
+                    Therefore it makes no sense to implement linting rules that may conflict with rustfmt.",
+                ));
+            }
+
+            Ok(Self { groups, lut })
+        } else if items_total != all_items.len() {
+            Err(de::Error::custom(format!(
+                "Some module item kinds were configured more than once, or were missing, in the source ordering configuration. \
+                The module item kinds are: {all_items:?}"
+            )))
+        } else {
+            Err(de::Error::custom(format!(
+                "Not all module item kinds were part of the configured source ordering rule. \
+                All item kinds must be provided in the config, otherwise the required source ordering would remain ambiguous. \
+                The module item kinds are: {all_items:?}"
+            )))
+        }
+    }
+}
+
+impl Serialize for SourceItemOrderingModuleItemGroupings {
+    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
+    where
+        S: ser::Serializer,
+    {
+        self.groups.serialize(serializer)
+    }
+}
+
+/// Represents all kinds of trait associated items.
+#[derive(Clone, Debug, Deserialize, PartialEq, PartialOrd, Serialize)]
+#[serde(rename_all = "snake_case")]
+pub enum SourceItemOrderingTraitAssocItemKind {
+    Const,
+    Fn,
+    Type,
+}
+
+impl SourceItemOrderingTraitAssocItemKind {
+    pub fn all_variants() -> Vec<Self> {
+        #[allow(clippy::enum_glob_use)] // Very local glob use for legibility.
+        use SourceItemOrderingTraitAssocItemKind::*;
+        vec![Const, Fn, Type]
+    }
+}
+
+/// Represents the order in which associated trait items should be ordered.
+///
+/// The reason to wrap a `Vec` in a newtype is to be able to implement
+/// [`Deserialize`]. Implementing `Deserialize` allows for implementing checks
+/// on configuration completeness at the time of loading the clippy config,
+/// letting the user know if there's any issues with the config (e.g. not
+/// listing all item kinds that should be sorted).
+#[derive(Clone)]
+pub struct SourceItemOrderingTraitAssocItemKinds(Vec<SourceItemOrderingTraitAssocItemKind>);
+
+impl SourceItemOrderingTraitAssocItemKinds {
+    pub fn index_of(&self, item: &SourceItemOrderingTraitAssocItemKind) -> Option<usize> {
+        self.0.iter().position(|i| i == item)
+    }
+}
+
+impl<T> From<T> for SourceItemOrderingTraitAssocItemKinds
+where
+    T: Into<Vec<SourceItemOrderingTraitAssocItemKind>>,
+{
+    fn from(value: T) -> Self {
+        Self(value.into())
+    }
+}
+
+impl core::fmt::Debug for SourceItemOrderingTraitAssocItemKinds {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        self.0.fmt(f)
+    }
+}
+
+impl<'de> Deserialize<'de> for SourceItemOrderingTraitAssocItemKinds {
+    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
+    where
+        D: Deserializer<'de>,
+    {
+        let items = Vec::<SourceItemOrderingTraitAssocItemKind>::deserialize(deserializer)?;
+
+        let mut expected_items = SourceItemOrderingTraitAssocItemKind::all_variants();
+        for item in &items {
+            expected_items.retain(|i| i != item);
+        }
+
+        let all_items = SourceItemOrderingTraitAssocItemKind::all_variants();
+        if expected_items.is_empty() && items.len() == all_items.len() {
+            Ok(Self(items))
+        } else if items.len() != all_items.len() {
+            Err(de::Error::custom(format!(
+                "Some trait associated item kinds were configured more than once, or were missing, in the source ordering configuration. \
+                The trait associated item kinds are: {all_items:?}",
+            )))
+        } else {
+            Err(de::Error::custom(format!(
+                "Not all trait associated item kinds were part of the configured source ordering rule. \
+                All item kinds must be provided in the config, otherwise the required source ordering would remain ambiguous. \
+                The trait associated item kinds are: {all_items:?}"
+            )))
+        }
+    }
+}
+
+impl Serialize for SourceItemOrderingTraitAssocItemKinds {
+    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
+    where
+        S: ser::Serializer,
+    {
+        self.0.serialize(serializer)
+    }
+}
+
 // these impls are never actually called but are used by the various config options that default to
 // empty lists
 macro_rules! unimplemented_serialize {
diff --git a/clippy_lints/src/arbitrary_source_item_ordering.rs b/clippy_lints/src/arbitrary_source_item_ordering.rs
new file mode 100644
index 00000000000..8719f61a890
--- /dev/null
+++ b/clippy_lints/src/arbitrary_source_item_ordering.rs
@@ -0,0 +1,531 @@
+use clippy_config::Conf;
+use clippy_config::types::{
+    SourceItemOrderingCategory, SourceItemOrderingModuleItemGroupings, SourceItemOrderingModuleItemKind,
+    SourceItemOrderingTraitAssocItemKind, SourceItemOrderingTraitAssocItemKinds,
+};
+use clippy_utils::diagnostics::span_lint_and_note;
+use rustc_hir::{
+    AssocItemKind, FieldDef, HirId, ImplItemRef, IsAuto, Item, ItemKind, Mod, QPath, TraitItemRef, TyKind, UseKind,
+    Variant, VariantData,
+};
+use rustc_lint::{LateContext, LateLintPass, LintContext};
+use rustc_middle::lint::in_external_macro;
+use rustc_session::impl_lint_pass;
+
+declare_clippy_lint! {
+    /// ### What it does
+    ///
+    /// Confirms that items are sorted in source files as per configuration.
+    ///
+    /// ### Why restrict this?
+    ///
+    /// Keeping a consistent ordering throughout the codebase helps with working
+    /// as a team, and possibly improves maintainability of the codebase. The
+    /// idea is that by defining a consistent and enforceable rule for how
+    /// source files are structured, less time will be wasted during reviews on
+    /// a topic that is (under most circumstances) not relevant to the logic
+    /// implemented in the code. Sometimes this will be referred to as
+    /// "bikeshedding".
+    ///
+    /// ### Default Ordering and Configuration
+    ///
+    /// As there is no generally applicable rule, and each project may have
+    /// different requirements, the lint can be configured with high
+    /// granularity. The configuration is split into two stages:
+    ///
+    /// 1. Which item kinds that should have an internal order enforced.
+    /// 2. Individual ordering rules per item kind.
+    ///
+    /// The item kinds that can be linted are:
+    /// - Module (with customized groupings, alphabetical within)
+    /// - Trait (with customized order of associated items, alphabetical within)
+    /// - Enum, Impl, Struct (purely alphabetical)
+    ///
+    /// #### Module Item Order
+    ///
+    /// Due to the large variation of items within modules, the ordering can be
+    /// configured on a very granular level. Item kinds can be grouped together
+    /// arbitrarily, items within groups will be ordered alphabetically. The
+    /// following table shows the default groupings:
+    ///
+    /// | Group              | Item Kinds           |
+    /// |--------------------|----------------------|
+    /// | `modules`          | "mod", "foreign_mod" |
+    /// | `use`              | "use"                |
+    /// | `macros`           | "macro"              |
+    /// | `global_asm`       | "global_asm"         |
+    /// | `UPPER_SNAKE_CASE` | "static", "const"    |
+    /// | `PascalCase`       | "ty_alias", "opaque_ty", "enum", "struct", "union", "trait", "trait_alias", "impl" |
+    /// | `lower_snake_case` | "fn"                 |
+    ///
+    /// All item kinds must be accounted for to create an enforceable linting
+    /// rule set.
+    ///
+    /// ### Known Problems
+    ///
+    /// #### Performance Impact
+    ///
+    /// Keep in mind, that ordering source code alphabetically can lead to
+    /// reduced performance in cases where the most commonly used enum variant
+    /// isn't the first entry anymore, and similar optimizations that can reduce
+    /// branch misses, cache locality and such. Either don't use this lint if
+    /// that's relevant, or disable the lint in modules or items specifically
+    /// where it matters. Other solutions can be to use profile guided
+    /// optimization (PGO), post-link optimization (e.g. using BOLT for LLVM),
+    /// or other advanced optimization methods. A good starting point to dig
+    /// into optimization is [cargo-pgo][cargo-pgo].
+    ///
+    /// #### Lints on a Contains basis
+    ///
+    /// The lint can be disabled only on a "contains" basis, but not per element
+    /// within a "container", e.g. the lint works per-module, per-struct,
+    /// per-enum, etc. but not for "don't order this particular enum variant".
+    ///
+    /// #### Module documentation
+    ///
+    /// Module level rustdoc comments are not part of the resulting syntax tree
+    /// and as such cannot be linted from within `check_mod`. Instead, the
+    /// `rustdoc::missing_documentation` lint may be used.
+    ///
+    /// #### Module Tests
+    ///
+    /// This lint does not implement detection of module tests (or other feature
+    /// dependent elements for that matter). To lint the location of mod tests,
+    /// the lint `items_after_test_module` can be used instead.
+    ///
+    /// ### Example
+    ///
+    /// ```no_run
+    /// trait TraitUnordered {
+    ///     const A: bool;
+    ///     const C: bool;
+    ///     const B: bool;
+    ///
+    ///     type SomeType;
+    ///
+    ///     fn a();
+    ///     fn c();
+    ///     fn b();
+    /// }
+    /// ```
+    ///
+    /// Use instead:
+    /// ```no_run
+    /// trait TraitOrdered {
+    ///     const A: bool;
+    ///     const B: bool;
+    ///     const C: bool;
+    ///
+    ///     type SomeType;
+    ///
+    ///     fn a();
+    ///     fn b();
+    ///     fn c();
+    /// }
+    /// ```
+    ///
+    /// [cargo-pgo]: https://github.com/Kobzol/cargo-pgo/blob/main/README.md
+    ///
+    #[clippy::version = "1.82.0"]
+    pub ARBITRARY_SOURCE_ITEM_ORDERING,
+    restriction,
+    "arbitrary source item ordering"
+}
+
+impl_lint_pass!(ArbitrarySourceItemOrdering => [ARBITRARY_SOURCE_ITEM_ORDERING]);
+
+#[derive(Debug)]
+#[allow(clippy::struct_excessive_bools)] // Bools are cached feature flags.
+pub struct ArbitrarySourceItemOrdering {
+    assoc_types_order: SourceItemOrderingTraitAssocItemKinds,
+    enable_ordering_for_enum: bool,
+    enable_ordering_for_impl: bool,
+    enable_ordering_for_module: bool,
+    enable_ordering_for_struct: bool,
+    enable_ordering_for_trait: bool,
+    module_item_order_groupings: SourceItemOrderingModuleItemGroupings,
+}
+
+impl ArbitrarySourceItemOrdering {
+    pub fn new(conf: &'static Conf) -> Self {
+        #[allow(clippy::enum_glob_use)] // Very local glob use for legibility.
+        use SourceItemOrderingCategory::*;
+        Self {
+            assoc_types_order: conf.trait_assoc_item_kinds_order.clone(),
+            enable_ordering_for_enum: conf.source_item_ordering.contains(&Enum),
+            enable_ordering_for_impl: conf.source_item_ordering.contains(&Impl),
+            enable_ordering_for_module: conf.source_item_ordering.contains(&Module),
+            enable_ordering_for_struct: conf.source_item_ordering.contains(&Struct),
+            enable_ordering_for_trait: conf.source_item_ordering.contains(&Trait),
+            module_item_order_groupings: conf.module_item_order_groupings.clone(),
+        }
+    }
+
+    /// Produces a linting warning for incorrectly ordered impl items.
+    fn lint_impl_item<T: LintContext>(&self, cx: &T, item: &ImplItemRef, before_item: &ImplItemRef) {
+        span_lint_and_note(
+            cx,
+            ARBITRARY_SOURCE_ITEM_ORDERING,
+            item.span,
+            format!(
+                "incorrect ordering of impl items (defined order: {:?})",
+                self.assoc_types_order
+            ),
+            Some(before_item.span),
+            format!("should be placed before `{}`", before_item.ident.as_str(),),
+        );
+    }
+
+    /// Produces a linting warning for incorrectly ordered item members.
+    fn lint_member_name<T: LintContext>(
+        cx: &T,
+        ident: &rustc_span::symbol::Ident,
+        before_ident: &rustc_span::symbol::Ident,
+    ) {
+        span_lint_and_note(
+            cx,
+            ARBITRARY_SOURCE_ITEM_ORDERING,
+            ident.span,
+            "incorrect ordering of items (must be alphabetically ordered)",
+            Some(before_ident.span),
+            format!("should be placed before `{}`", before_ident.as_str(),),
+        );
+    }
+
+    fn lint_member_item<T: LintContext>(cx: &T, item: &Item<'_>, before_item: &Item<'_>) {
+        let span = if item.ident.as_str().is_empty() {
+            &item.span
+        } else {
+            &item.ident.span
+        };
+
+        let (before_span, note) = if before_item.ident.as_str().is_empty() {
+            (
+                &before_item.span,
+                "should be placed before the following item".to_owned(),
+            )
+        } else {
+            (
+                &before_item.ident.span,
+                format!("should be placed before `{}`", before_item.ident.as_str(),),
+            )
+        };
+
+        // This catches false positives where generated code gets linted.
+        if span == before_span {
+            return;
+        }
+
+        span_lint_and_note(
+            cx,
+            ARBITRARY_SOURCE_ITEM_ORDERING,
+            *span,
+            "incorrect ordering of items (must be alphabetically ordered)",
+            Some(*before_span),
+            note,
+        );
+    }
+
+    /// Produces a linting warning for incorrectly ordered trait items.
+    fn lint_trait_item<T: LintContext>(&self, cx: &T, item: &TraitItemRef, before_item: &TraitItemRef) {
+        span_lint_and_note(
+            cx,
+            ARBITRARY_SOURCE_ITEM_ORDERING,
+            item.span,
+            format!(
+                "incorrect ordering of trait items (defined order: {:?})",
+                self.assoc_types_order
+            ),
+            Some(before_item.span),
+            format!("should be placed before `{}`", before_item.ident.as_str(),),
+        );
+    }
+}
+
+impl<'tcx> LateLintPass<'tcx> for ArbitrarySourceItemOrdering {
+    fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) {
+        match &item.kind {
+            ItemKind::Enum(enum_def, _generics) if self.enable_ordering_for_enum => {
+                let mut cur_v: Option<&Variant<'_>> = None;
+                for variant in enum_def.variants {
+                    if in_external_macro(cx.sess(), variant.span) {
+                        continue;
+                    }
+
+                    if let Some(cur_v) = cur_v {
+                        if cur_v.ident.name.as_str() > variant.ident.name.as_str() && cur_v.span != variant.span {
+                            Self::lint_member_name(cx, &variant.ident, &cur_v.ident);
+                        }
+                    }
+                    cur_v = Some(variant);
+                }
+            },
+            ItemKind::Struct(VariantData::Struct { fields, .. }, _generics) if self.enable_ordering_for_struct => {
+                let mut cur_f: Option<&FieldDef<'_>> = None;
+                for field in *fields {
+                    if in_external_macro(cx.sess(), field.span) {
+                        continue;
+                    }
+
+                    if let Some(cur_f) = cur_f {
+                        if cur_f.ident.name.as_str() > field.ident.name.as_str() && cur_f.span != field.span {
+                            Self::lint_member_name(cx, &field.ident, &cur_f.ident);
+                        }
+                    }
+                    cur_f = Some(field);
+                }
+            },
+            ItemKind::Trait(is_auto, _safety, _generics, _generic_bounds, item_ref)
+                if self.enable_ordering_for_trait && *is_auto == IsAuto::No =>
+            {
+                let mut cur_t: Option<&TraitItemRef> = None;
+
+                for item in *item_ref {
+                    if in_external_macro(cx.sess(), item.span) {
+                        continue;
+                    }
+
+                    if let Some(cur_t) = cur_t {
+                        let cur_t_kind = convert_assoc_item_kind(cur_t.kind);
+                        let cur_t_kind_index = self.assoc_types_order.index_of(&cur_t_kind);
+                        let item_kind = convert_assoc_item_kind(item.kind);
+                        let item_kind_index = self.assoc_types_order.index_of(&item_kind);
+
+                        if cur_t_kind == item_kind && cur_t.ident.name.as_str() > item.ident.name.as_str() {
+                            Self::lint_member_name(cx, &item.ident, &cur_t.ident);
+                        } else if cur_t_kind_index > item_kind_index {
+                            self.lint_trait_item(cx, item, cur_t);
+                        }
+                    }
+                    cur_t = Some(item);
+                }
+            },
+            ItemKind::Impl(trait_impl) if self.enable_ordering_for_impl => {
+                let mut cur_t: Option<&ImplItemRef> = None;
+
+                for item in trait_impl.items {
+                    if in_external_macro(cx.sess(), item.span) {
+                        continue;
+                    }
+
+                    if let Some(cur_t) = cur_t {
+                        let cur_t_kind = convert_assoc_item_kind(cur_t.kind);
+                        let cur_t_kind_index = self.assoc_types_order.index_of(&cur_t_kind);
+                        let item_kind = convert_assoc_item_kind(item.kind);
+                        let item_kind_index = self.assoc_types_order.index_of(&item_kind);
+
+                        if cur_t_kind == item_kind && cur_t.ident.name.as_str() > item.ident.name.as_str() {
+                            Self::lint_member_name(cx, &item.ident, &cur_t.ident);
+                        } else if cur_t_kind_index > item_kind_index {
+                            self.lint_impl_item(cx, item, cur_t);
+                        }
+                    }
+                    cur_t = Some(item);
+                }
+            },
+            _ => {}, // Catch-all for `ItemKinds` that don't have fields.
+        }
+    }
+
+    fn check_mod(&mut self, cx: &LateContext<'tcx>, module: &'tcx Mod<'tcx>, _: HirId) {
+        struct CurItem<'a> {
+            item: &'a Item<'a>,
+            order: usize,
+            name: String,
+        }
+        let mut cur_t: Option<CurItem<'_>> = None;
+
+        if !self.enable_ordering_for_module {
+            return;
+        }
+
+        let items = module.item_ids.iter().map(|&id| cx.tcx.hir().item(id));
+
+        // Iterates over the items within a module.
+        //
+        // As of 2023-05-09, the Rust compiler will hold the entries in the same
+        // order as they appear in the source code, which is convenient for us,
+        // as no sorting by source map/line of code has to be applied.
+        //
+        for item in items {
+            if in_external_macro(cx.sess(), item.span) {
+                continue;
+            }
+
+            // The following exceptions (skipping with `continue;`) may not be
+            // complete, edge cases have not been explored further than what
+            // appears in the existing code base.
+            if item.ident.name == rustc_span::symbol::kw::Empty {
+                if let ItemKind::Impl(_) = item.kind {
+                    // Sorting trait impls for unnamed types makes no sense.
+                    if get_item_name(item).is_empty() {
+                        continue;
+                    }
+                } else if let ItemKind::ForeignMod { .. } = item.kind {
+                    continue;
+                } else if let ItemKind::GlobalAsm(_) = item.kind {
+                    continue;
+                } else if let ItemKind::Use(path, use_kind) = item.kind {
+                    if path.segments.is_empty() {
+                        // Use statements that contain braces get caught here.
+                        // They will still be linted internally.
+                        continue;
+                    } else if path.segments.len() >= 2
+                        && (path.segments[0].ident.name == rustc_span::sym::std
+                            || path.segments[0].ident.name == rustc_span::sym::core)
+                        && path.segments[1].ident.name == rustc_span::sym::prelude
+                    {
+                        // Filters the autogenerated prelude use statement.
+                        // e.g. `use std::prelude::rustc_2021`
+                    } else if use_kind == UseKind::Glob {
+                        // Filters glob kinds of uses.
+                        // e.g. `use std::sync::*`
+                    } else {
+                        // This can be used for debugging.
+                        // println!("Unknown autogenerated use statement: {:?}", item);
+                    }
+                    continue;
+                }
+            }
+
+            if item.ident.name.as_str().starts_with('_') {
+                // Filters out unnamed macro-like impls for various derives,
+                // e.g. serde::Serialize or num_derive::FromPrimitive.
+                continue;
+            }
+
+            if item.ident.name == rustc_span::sym::std && item.span.is_dummy() {
+                if let ItemKind::ExternCrate(None) = item.kind {
+                    // Filters the auto-included Rust standard library.
+                    continue;
+                }
+                println!("Unknown item: {item:?}");
+            }
+
+            let item_kind = convert_module_item_kind(&item.kind);
+            let module_level_order = self
+                .module_item_order_groupings
+                .module_level_order_of(&item_kind)
+                .unwrap_or_default();
+
+            if let Some(cur_t) = cur_t.as_ref() {
+                use std::cmp::Ordering; // Better legibility.
+                match module_level_order.cmp(&cur_t.order) {
+                    Ordering::Less => {
+                        Self::lint_member_item(cx, item, cur_t.item);
+                    },
+                    Ordering::Equal if item_kind == SourceItemOrderingModuleItemKind::Use => {
+                        // Skip ordering use statements, as these should be ordered by rustfmt.
+                    },
+                    Ordering::Equal if cur_t.name > get_item_name(item) => {
+                        Self::lint_member_item(cx, item, cur_t.item);
+                    },
+                    Ordering::Equal | Ordering::Greater => {
+                        // Nothing to do in this case, they're already in the right order.
+                    },
+                }
+            }
+
+            // Makes a note of the current item for comparison with the next.
+            cur_t = Some(CurItem {
+                order: module_level_order,
+                item,
+                name: get_item_name(item),
+            });
+        }
+    }
+}
+
+/// Converts a [`rustc_hir::AssocItemKind`] to a
+/// [`SourceItemOrderingTraitAssocItemKind`].
+///
+/// This is implemented here because `rustc_hir` is not a dependency of
+/// `clippy_config`.
+fn convert_assoc_item_kind(value: AssocItemKind) -> SourceItemOrderingTraitAssocItemKind {
+    #[allow(clippy::enum_glob_use)] // Very local glob use for legibility.
+    use SourceItemOrderingTraitAssocItemKind::*;
+    match value {
+        AssocItemKind::Const { .. } => Const,
+        AssocItemKind::Type { .. } => Type,
+        AssocItemKind::Fn { .. } => Fn,
+    }
+}
+
+/// Converts a [`rustc_hir::ItemKind`] to a
+/// [`SourceItemOrderingModuleItemKind`].
+///
+/// This is implemented here because `rustc_hir` is not a dependency of
+/// `clippy_config`.
+fn convert_module_item_kind(value: &ItemKind<'_>) -> SourceItemOrderingModuleItemKind {
+    #[allow(clippy::enum_glob_use)] // Very local glob use for legibility.
+    use SourceItemOrderingModuleItemKind::*;
+    match value {
+        ItemKind::ExternCrate(..) => ExternCrate,
+        ItemKind::Use(..) => Use,
+        ItemKind::Static(..) => Static,
+        ItemKind::Const(..) => Const,
+        ItemKind::Fn(..) => Fn,
+        ItemKind::Macro(..) => Macro,
+        ItemKind::Mod(..) => Mod,
+        ItemKind::ForeignMod { .. } => ForeignMod,
+        ItemKind::GlobalAsm(..) => GlobalAsm,
+        ItemKind::TyAlias(..) => TyAlias,
+        ItemKind::Enum(..) => Enum,
+        ItemKind::Struct(..) => Struct,
+        ItemKind::Union(..) => Union,
+        ItemKind::Trait(..) => Trait,
+        ItemKind::TraitAlias(..) => TraitAlias,
+        ItemKind::Impl(..) => Impl,
+    }
+}
+
+/// Gets the item name for sorting purposes, which in the general case is
+/// `item.ident.name`.
+///
+/// For trait impls, the name used for sorting will be the written path of
+/// `item.self_ty` plus the written path of `item.of_trait`, joined with
+/// exclamation marks. Exclamation marks are used because they are the first
+/// printable ASCII character.
+///
+/// Trait impls generated using a derive-macro will have their path rewritten,
+/// such that for example `Default` is `$crate::default::Default`, and
+/// `std::clone::Clone` is `$crate::clone::Clone`. This behaviour is described
+/// further in the [Rust Reference, Paths Chapter][rust_ref].
+///
+/// [rust_ref]: https://doc.rust-lang.org/reference/paths.html#crate-1
+fn get_item_name(item: &Item<'_>) -> String {
+    match item.kind {
+        ItemKind::Impl(im) => {
+            if let TyKind::Path(path) = im.self_ty.kind {
+                match path {
+                    QPath::Resolved(_, path) => {
+                        let segs = path.segments.iter();
+                        let mut segs: Vec<String> = segs.map(|s| s.ident.name.as_str().to_owned()).collect();
+
+                        if let Some(of_trait) = im.of_trait {
+                            let mut trait_segs: Vec<String> = of_trait
+                                .path
+                                .segments
+                                .iter()
+                                .map(|s| s.ident.name.as_str().to_owned())
+                                .collect();
+                            segs.append(&mut trait_segs);
+                        }
+
+                        segs.push(String::new());
+                        segs.join("!!")
+                    },
+                    QPath::TypeRelative(_, _path_seg) => {
+                        // This case doesn't exist in the clippy tests codebase.
+                        String::new()
+                    },
+                    QPath::LangItem(_, _) => String::new(),
+                }
+            } else {
+                // Impls for anything that isn't a named type can be skipped.
+                String::new()
+            }
+        },
+        _ => item.ident.name.as_str().to_owned(),
+    }
+}
diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs
index f065f6115dc..edb52851e0c 100644
--- a/clippy_lints/src/declared_lints.rs
+++ b/clippy_lints/src/declared_lints.rs
@@ -36,6 +36,7 @@ pub static LINTS: &[&crate::LintInfo] = &[
     crate::absolute_paths::ABSOLUTE_PATHS_INFO,
     crate::almost_complete_range::ALMOST_COMPLETE_RANGE_INFO,
     crate::approx_const::APPROX_CONSTANT_INFO,
+    crate::arbitrary_source_item_ordering::ARBITRARY_SOURCE_ITEM_ORDERING_INFO,
     crate::arc_with_non_send_sync::ARC_WITH_NON_SEND_SYNC_INFO,
     crate::as_conversions::AS_CONVERSIONS_INFO,
     crate::asm_syntax::INLINE_ASM_X86_ATT_SYNTAX_INFO,
diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs
index a0ff8316d5c..b92da0e62cf 100644
--- a/clippy_lints/src/lib.rs
+++ b/clippy_lints/src/lib.rs
@@ -72,6 +72,7 @@ pub mod deprecated_lints;
 mod absolute_paths;
 mod almost_complete_range;
 mod approx_const;
+mod arbitrary_source_item_ordering;
 mod arc_with_non_send_sync;
 mod as_conversions;
 mod asm_syntax;
@@ -949,5 +950,6 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) {
     store.register_late_pass(move |_| Box::new(unused_trait_names::UnusedTraitNames::new(conf)));
     store.register_late_pass(|_| Box::new(manual_ignore_case_cmp::ManualIgnoreCaseCmp));
     store.register_late_pass(|_| Box::new(unnecessary_literal_bound::UnnecessaryLiteralBound));
+    store.register_late_pass(move |_| Box::new(arbitrary_source_item_ordering::ArbitrarySourceItemOrdering::new(conf)));
     // add lints here, do not remove this comment, it's used in `new_lint`
 }
diff --git a/tests/ui-toml/arbitrary_source_item_ordering/bad_conf_1/clippy.toml b/tests/ui-toml/arbitrary_source_item_ordering/bad_conf_1/clippy.toml
new file mode 100644
index 00000000000..fbdb0c9c37d
--- /dev/null
+++ b/tests/ui-toml/arbitrary_source_item_ordering/bad_conf_1/clippy.toml
@@ -0,0 +1 @@
+trait-assoc-item-kinds-order = ["fn", "type", "const", "type"]
diff --git a/tests/ui-toml/arbitrary_source_item_ordering/bad_conf_2/clippy.toml b/tests/ui-toml/arbitrary_source_item_ordering/bad_conf_2/clippy.toml
new file mode 100644
index 00000000000..720655e5cce
--- /dev/null
+++ b/tests/ui-toml/arbitrary_source_item_ordering/bad_conf_2/clippy.toml
@@ -0,0 +1 @@
+trait-assoc-item-kinds-order = ["const", "type"]
diff --git a/tests/ui-toml/arbitrary_source_item_ordering/bad_conf_3/clippy.toml b/tests/ui-toml/arbitrary_source_item_ordering/bad_conf_3/clippy.toml
new file mode 100644
index 00000000000..0dd5407be10
--- /dev/null
+++ b/tests/ui-toml/arbitrary_source_item_ordering/bad_conf_3/clippy.toml
@@ -0,0 +1 @@
+source-item-ordering = ["enum", "impl", "module", "struct", "trait", "struct"]
diff --git a/tests/ui-toml/arbitrary_source_item_ordering/default/clippy.toml b/tests/ui-toml/arbitrary_source_item_ordering/default/clippy.toml
new file mode 100644
index 00000000000..e69de29bb2d
--- /dev/null
+++ b/tests/ui-toml/arbitrary_source_item_ordering/default/clippy.toml
diff --git a/tests/ui-toml/arbitrary_source_item_ordering/default_exp/clippy.toml b/tests/ui-toml/arbitrary_source_item_ordering/default_exp/clippy.toml
new file mode 100644
index 00000000000..ddca5cfa577
--- /dev/null
+++ b/tests/ui-toml/arbitrary_source_item_ordering/default_exp/clippy.toml
@@ -0,0 +1,12 @@
+trait-assoc-item-kinds-order = ["const", "type", "fn"]
+source-item-ordering = ["enum", "impl", "module", "struct", "trait"]
+module-item-order-groupings = [
+    ["modules", ["extern_crate", "mod", "foreign_mod"]],
+    ["use", ["use"]],
+    ["macros", ["macro"]],
+    ["global_asm", ["global_asm"]],
+    ["UPPER_SNAKE_CASE", ["static", "const"]],
+    ["PascalCase", ["ty_alias", "enum", "struct", "union", "trait", "trait_alias", "impl"]],
+    ["lower_snake_case", ["fn"]]
+]
+
diff --git a/tests/ui-toml/arbitrary_source_item_ordering/only_enum/clippy.toml b/tests/ui-toml/arbitrary_source_item_ordering/only_enum/clippy.toml
new file mode 100644
index 00000000000..2144bdc9a0c
--- /dev/null
+++ b/tests/ui-toml/arbitrary_source_item_ordering/only_enum/clippy.toml
@@ -0,0 +1 @@
+source-item-ordering = ["enum"]
diff --git a/tests/ui-toml/arbitrary_source_item_ordering/only_impl/clippy.toml b/tests/ui-toml/arbitrary_source_item_ordering/only_impl/clippy.toml
new file mode 100644
index 00000000000..54b6727fabf
--- /dev/null
+++ b/tests/ui-toml/arbitrary_source_item_ordering/only_impl/clippy.toml
@@ -0,0 +1 @@
+source-item-ordering = ["impl"]
diff --git a/tests/ui-toml/arbitrary_source_item_ordering/only_trait/clippy.toml b/tests/ui-toml/arbitrary_source_item_ordering/only_trait/clippy.toml
new file mode 100644
index 00000000000..b551611c35e
--- /dev/null
+++ b/tests/ui-toml/arbitrary_source_item_ordering/only_trait/clippy.toml
@@ -0,0 +1 @@
+source-item-ordering = ["trait"]
diff --git a/tests/ui-toml/arbitrary_source_item_ordering/ordering_good.bad_conf_1.stderr b/tests/ui-toml/arbitrary_source_item_ordering/ordering_good.bad_conf_1.stderr
new file mode 100644
index 00000000000..e441c7c1241
--- /dev/null
+++ b/tests/ui-toml/arbitrary_source_item_ordering/ordering_good.bad_conf_1.stderr
@@ -0,0 +1,8 @@
+error: error reading Clippy's configuration file: Some trait associated item kinds were configured more than once, or were missing, in the source ordering configuration. The trait associated item kinds are: [Const, Fn, Type]
+  --> $DIR/tests/ui-toml/arbitrary_source_item_ordering/bad_conf_1/clippy.toml:1:32
+   |
+LL | trait-assoc-item-kinds-order = ["fn", "type", "const", "type"]
+   |                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui-toml/arbitrary_source_item_ordering/ordering_good.bad_conf_2.stderr b/tests/ui-toml/arbitrary_source_item_ordering/ordering_good.bad_conf_2.stderr
new file mode 100644
index 00000000000..183f0b03319
--- /dev/null
+++ b/tests/ui-toml/arbitrary_source_item_ordering/ordering_good.bad_conf_2.stderr
@@ -0,0 +1,8 @@
+error: error reading Clippy's configuration file: Some trait associated item kinds were configured more than once, or were missing, in the source ordering configuration. The trait associated item kinds are: [Const, Fn, Type]
+  --> $DIR/tests/ui-toml/arbitrary_source_item_ordering/bad_conf_2/clippy.toml:1:32
+   |
+LL | trait-assoc-item-kinds-order = ["const", "type"]
+   |                                ^^^^^^^^^^^^^^^^^
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui-toml/arbitrary_source_item_ordering/ordering_good.bad_conf_3.stderr b/tests/ui-toml/arbitrary_source_item_ordering/ordering_good.bad_conf_3.stderr
new file mode 100644
index 00000000000..abf58dbd110
--- /dev/null
+++ b/tests/ui-toml/arbitrary_source_item_ordering/ordering_good.bad_conf_3.stderr
@@ -0,0 +1,8 @@
+error: error reading Clippy's configuration file: The category "Struct" was enabled more than once in the source ordering configuration.
+  --> $DIR/tests/ui-toml/arbitrary_source_item_ordering/bad_conf_3/clippy.toml:1:24
+   |
+LL | source-item-ordering = ["enum", "impl", "module", "struct", "trait", "struct"]
+   |                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui-toml/arbitrary_source_item_ordering/ordering_good.rs b/tests/ui-toml/arbitrary_source_item_ordering/ordering_good.rs
new file mode 100644
index 00000000000..e9bcc30c15e
--- /dev/null
+++ b/tests/ui-toml/arbitrary_source_item_ordering/ordering_good.rs
@@ -0,0 +1,186 @@
+//@aux-build:../../ui/auxiliary/proc_macros.rs
+//@revisions: default default_exp bad_conf_1 bad_conf_2 bad_conf_3
+//@[default] rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/arbitrary_source_item_ordering/default
+//@[default_exp] rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/arbitrary_source_item_ordering/default_exp
+//@[bad_conf_1] rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/arbitrary_source_item_ordering/bad_conf_1
+//@[bad_conf_2] rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/arbitrary_source_item_ordering/bad_conf_2
+//@[bad_conf_3] rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/arbitrary_source_item_ordering/bad_conf_3
+
+#![allow(dead_code)]
+#![warn(clippy::arbitrary_source_item_ordering)]
+
+/// This module gets linted before clippy gives up.
+mod i_am_just_right {
+    const AFTER: i8 = 0;
+
+    const BEFORE: i8 = 0;
+}
+
+/// Since the upper module passes linting, the lint now recurses into this module.
+mod this_is_in_the_wrong_position {
+    const A: i8 = 1;
+    const C: i8 = 0;
+}
+
+// Use statements should not be linted internally - this is normally auto-sorted using rustfmt.
+use std::rc::{Rc, Weak};
+use std::sync::{Arc, Barrier, RwLock};
+
+const SNAKE_CASE: &str = "zzzzzzzz";
+
+const ZIS_SHOULD_BE_EVEN_EARLIER: () = ();
+
+const ZIS_SHOULD_BE_REALLY_EARLY: () = ();
+
+trait BasicEmptyTrait {}
+
+trait CloneSelf {
+    fn clone_self(&self) -> Self;
+}
+
+enum EnumOrdered {
+    A,
+    B,
+    C,
+}
+
+enum EnumUnordered {
+    A,
+    B,
+    C,
+}
+
+#[allow(clippy::arbitrary_source_item_ordering)]
+enum EnumUnorderedAllowed {
+    A,
+    B,
+    C,
+}
+
+struct StructOrdered {
+    a: bool,
+    b: bool,
+    c: bool,
+}
+
+impl BasicEmptyTrait for StructOrdered {}
+
+impl CloneSelf for StructOrdered {
+    fn clone_self(&self) -> Self {
+        Self {
+            a: true,
+            b: true,
+            c: true,
+        }
+    }
+}
+
+impl Default for StructOrdered {
+    fn default() -> Self {
+        Self {
+            a: true,
+            b: true,
+            c: true,
+        }
+    }
+}
+
+impl std::clone::Clone for StructOrdered {
+    fn clone(&self) -> Self {
+        Self {
+            a: true,
+            b: true,
+            c: true,
+        }
+    }
+}
+
+#[derive(Clone, Default)]
+struct StructUnordered {
+    a: bool,
+    b: bool,
+    c: bool,
+    d: bool,
+}
+
+impl TraitUnordered for StructUnordered {
+    const A: bool = false;
+    const B: bool = false;
+    const C: bool = false;
+
+    type SomeType = ();
+
+    fn a() {}
+    fn b() {}
+    fn c() {}
+}
+
+impl TraitUnorderedItemKinds for StructUnordered {
+    const A: bool = false;
+    const B: bool = false;
+    const C: bool = false;
+
+    type SomeType = ();
+
+    fn a() {}
+    fn b() {}
+    fn c() {}
+}
+
+struct StructUnorderedGeneric<T> {
+    _1: std::marker::PhantomData<T>,
+    a: bool,
+    b: bool,
+    c: bool,
+    d: bool,
+}
+
+trait TraitOrdered {
+    const A: bool;
+    const B: bool;
+    const C: bool;
+
+    type SomeType;
+
+    fn a();
+    fn b();
+    fn c();
+}
+
+trait TraitUnordered {
+    const A: bool;
+    const B: bool;
+    const C: bool;
+
+    type SomeType;
+
+    fn a();
+    fn b();
+    fn c();
+}
+
+trait TraitUnorderedItemKinds {
+    const A: bool;
+    const B: bool;
+    const C: bool;
+
+    type SomeType;
+
+    fn a();
+    fn b();
+    fn c();
+}
+
+#[derive(std::clone::Clone, Default)]
+struct ZisShouldBeBeforeZeMainFn;
+
+fn main() {
+    // test code goes here
+}
+
+#[cfg(test)]
+mod test {
+    const B: i8 = 1;
+
+    const A: i8 = 0;
+}
diff --git a/tests/ui-toml/arbitrary_source_item_ordering/ordering_good_var_1.rs b/tests/ui-toml/arbitrary_source_item_ordering/ordering_good_var_1.rs
new file mode 100644
index 00000000000..0fccbd4790b
--- /dev/null
+++ b/tests/ui-toml/arbitrary_source_item_ordering/ordering_good_var_1.rs
@@ -0,0 +1,174 @@
+//@aux-build:../../ui/auxiliary/proc_macros.rs
+//@revisions: var_1
+//@[var_1] rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/arbitrary_source_item_ordering/var_1
+
+#![allow(dead_code)]
+#![warn(clippy::arbitrary_source_item_ordering)]
+
+/// This module gets linted before clippy gives up.
+mod i_am_just_right {
+    const AFTER: i8 = 0;
+
+    const BEFORE: i8 = 0;
+}
+
+/// Since the upper module passes linting, the lint now recurses into this module.
+mod this_is_in_the_wrong_position {
+    const A: i8 = 1;
+    const C: i8 = 0;
+}
+
+// Use statements should not be linted internally - this is normally auto-sorted using rustfmt.
+use std::rc::{Rc, Weak};
+use std::sync::{Arc, Barrier, RwLock};
+
+const SNAKE_CASE: &str = "zzzzzzzz";
+
+const ZIS_SHOULD_BE_EVEN_EARLIER: () = ();
+
+const ZIS_SHOULD_BE_REALLY_EARLY: () = ();
+
+trait BasicEmptyTrait {}
+
+trait CloneSelf {
+    fn clone_self(&self) -> Self;
+}
+
+enum EnumOrdered {
+    A,
+    B,
+    C,
+}
+
+enum EnumUnordered {
+    A,
+    B,
+    C,
+}
+
+#[allow(clippy::arbitrary_source_item_ordering)]
+enum EnumUnorderedAllowed {
+    A,
+    B,
+    C,
+}
+
+struct StructOrdered {
+    a: bool,
+    b: bool,
+    c: bool,
+}
+
+impl BasicEmptyTrait for StructOrdered {}
+
+impl CloneSelf for StructOrdered {
+    fn clone_self(&self) -> Self {
+        Self {
+            a: true,
+            b: true,
+            c: true,
+        }
+    }
+}
+
+impl Default for StructOrdered {
+    fn default() -> Self {
+        Self {
+            a: true,
+            b: true,
+            c: true,
+        }
+    }
+}
+
+impl std::clone::Clone for StructOrdered {
+    fn clone(&self) -> Self {
+        Self {
+            a: true,
+            b: true,
+            c: true,
+        }
+    }
+}
+
+#[derive(Clone, Default)]
+struct StructUnordered {
+    a: bool,
+    b: bool,
+    c: bool,
+    d: bool,
+}
+
+impl TraitUnordered for StructUnordered {
+    fn a() {}
+    fn b() {}
+    fn c() {}
+
+    type SomeType = ();
+
+    const A: bool = false;
+    const B: bool = false;
+    const C: bool = false;
+}
+
+impl TraitUnorderedItemKinds for StructUnordered {
+    fn a() {}
+
+    type SomeType = ();
+
+    const A: bool = false;
+}
+
+struct StructUnorderedGeneric<T> {
+    _1: std::marker::PhantomData<T>,
+    a: bool,
+    b: bool,
+    c: bool,
+    d: bool,
+}
+
+trait TraitOrdered {
+    fn a();
+    fn b();
+    fn c();
+
+    type SomeType;
+
+    const A: bool;
+    const B: bool;
+    const C: bool;
+}
+
+trait TraitUnordered {
+    fn a();
+    fn b();
+    fn c();
+
+    type SomeType;
+
+    const A: bool;
+    const B: bool;
+    const C: bool;
+}
+
+trait TraitUnorderedItemKinds {
+    fn a();
+
+    type SomeType;
+
+    const A: bool;
+}
+
+#[derive(std::clone::Clone, Default)]
+struct ZisShouldBeBeforeZeMainFn;
+
+fn main() {
+    // test code goes here
+}
+
+#[cfg(test)]
+mod test {
+    const B: i8 = 1;
+
+    const A: i8 = 0;
+}
diff --git a/tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.default.stderr b/tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.default.stderr
new file mode 100644
index 00000000000..062bf25ea62
--- /dev/null
+++ b/tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.default.stderr
@@ -0,0 +1,226 @@
+error: incorrect ordering of items (must be alphabetically ordered)
+  --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:21:14
+   |
+LL | use std::rc::Weak;
+   |              ^^^^
+   |
+note: should be placed before `SNAKE_CASE`
+  --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:19:7
+   |
+LL | const SNAKE_CASE: &str = "zzzzzzzz";
+   |       ^^^^^^^^^^
+   = note: `-D clippy::arbitrary-source-item-ordering` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::arbitrary_source_item_ordering)]`
+
+error: incorrect ordering of items (must be alphabetically ordered)
+  --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:64:1
+   |
+LL | / impl CloneSelf for StructOrdered {
+LL | |     fn clone_self(&self) -> Self {
+LL | |         Self {
+LL | |             a: true,
+...  |
+LL | |     }
+LL | | }
+   | |_^
+   |
+note: should be placed before the following item
+  --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:54:1
+   |
+LL | / impl Default for StructOrdered {
+LL | |     fn default() -> Self {
+LL | |         Self {
+LL | |             a: true,
+...  |
+LL | |     }
+LL | | }
+   | |_^
+
+error: incorrect ordering of items (must be alphabetically ordered)
+  --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:136:7
+   |
+LL | const ZIS_SHOULD_BE_REALLY_EARLY: () = ();
+   |       ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: should be placed before `TraitUnorderedItemKinds`
+  --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:124:7
+   |
+LL | trait TraitUnorderedItemKinds {
+   |       ^^^^^^^^^^^^^^^^^^^^^^^
+
+error: incorrect ordering of items (must be alphabetically ordered)
+  --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:151:1
+   |
+LL | impl BasicEmptyTrait for StructOrdered {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: should be placed before the following item
+  --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:138:1
+   |
+LL | / impl TraitUnordered for StructUnordered {
+LL | |     const A: bool = false;
+LL | |     const C: bool = false;
+LL | |     const B: bool = false;
+...  |
+LL | |     fn b() {}
+LL | | }
+   | |_^
+
+error: incorrect ordering of items (must be alphabetically ordered)
+  --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:170:5
+   |
+LL | mod this_is_in_the_wrong_position {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: should be placed before `main`
+  --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:165:4
+   |
+LL | fn main() {
+   |    ^^^^
+
+error: incorrect ordering of items (must be alphabetically ordered)
+  --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:178:7
+   |
+LL | const ZIS_SHOULD_BE_EVEN_EARLIER: () = ();
+   |       ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: should be placed before `ZisShouldBeBeforeZeMainFn`
+  --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:176:8
+   |
+LL | struct ZisShouldBeBeforeZeMainFn;
+   |        ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: incorrect ordering of items (must be alphabetically ordered)
+  --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:12:11
+   |
+LL |     const AFTER: i8 = 0;
+   |           ^^^^^
+   |
+note: should be placed before `BEFORE`
+  --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:10:11
+   |
+LL |     const BEFORE: i8 = 0;
+   |           ^^^^^^
+
+error: incorrect ordering of items (must be alphabetically ordered)
+  --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:38:5
+   |
+LL |     B,
+   |     ^
+   |
+note: should be placed before `C`
+  --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:37:5
+   |
+LL |     C,
+   |     ^
+
+error: incorrect ordering of items (must be alphabetically ordered)
+  --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:88:5
+   |
+LL |     b: bool,
+   |     ^
+   |
+note: should be placed before `c`
+  --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:87:5
+   |
+LL |     c: bool,
+   |     ^
+
+error: incorrect ordering of items (must be alphabetically ordered)
+  --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:96:5
+   |
+LL |     b: bool,
+   |     ^
+   |
+note: should be placed before `c`
+  --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:95:5
+   |
+LL |     c: bool,
+   |     ^
+
+error: incorrect ordering of items (must be alphabetically ordered)
+  --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:115:11
+   |
+LL |     const B: bool;
+   |           ^
+   |
+note: should be placed before `C`
+  --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:114:11
+   |
+LL |     const C: bool;
+   |           ^
+
+error: incorrect ordering of items (must be alphabetically ordered)
+  --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:121:8
+   |
+LL |     fn b();
+   |        ^
+   |
+note: should be placed before `c`
+  --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:120:8
+   |
+LL |     fn c();
+   |        ^
+
+error: incorrect ordering of trait items (defined order: [Const, Type, Fn])
+  --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:127:5
+   |
+LL |     const A: bool;
+   |     ^^^^^^^^^^^^^^
+   |
+note: should be placed before `SomeType`
+  --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:125:5
+   |
+LL |     type SomeType;
+   |     ^^^^^^^^^^^^^^
+
+error: incorrect ordering of items (must be alphabetically ordered)
+  --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:141:11
+   |
+LL |     const B: bool = false;
+   |           ^
+   |
+note: should be placed before `C`
+  --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:140:11
+   |
+LL |     const C: bool = false;
+   |           ^
+
+error: incorrect ordering of items (must be alphabetically ordered)
+  --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:147:8
+   |
+LL |     fn b() {}
+   |        ^
+   |
+note: should be placed before `c`
+  --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:146:8
+   |
+LL |     fn c() {}
+   |        ^
+
+error: incorrect ordering of impl items (defined order: [Const, Type, Fn])
+  --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:156:5
+   |
+LL |     const A: bool = false;
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: should be placed before `SomeType`
+  --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:154:5
+   |
+LL |     type SomeType = ();
+   |     ^^^^^^^^^^^^^^^^^^^
+
+error: incorrect ordering of items (must be alphabetically ordered)
+  --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:172:11
+   |
+LL |     const A: i8 = 1;
+   |           ^
+   |
+note: should be placed before `C`
+  --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:171:11
+   |
+LL |     const C: i8 = 0;
+   |           ^
+
+error: aborting due to 17 previous errors
+
diff --git a/tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs b/tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs
new file mode 100644
index 00000000000..2765bf935b7
--- /dev/null
+++ b/tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs
@@ -0,0 +1,185 @@
+//@aux-build:../../ui/auxiliary/proc_macros.rs
+//@revisions: default
+//@[default] rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/arbitrary_source_item_ordering/default
+
+#![allow(dead_code)]
+#![warn(clippy::arbitrary_source_item_ordering)]
+
+/// This module gets linted before clippy gives up.
+mod i_am_just_right {
+    const BEFORE: i8 = 0;
+
+    const AFTER: i8 = 0;
+}
+
+// Use statements should not be linted internally - this is normally auto-sorted using rustfmt.
+use std::rc::Rc;
+use std::sync::{Arc, Barrier, RwLock};
+
+const SNAKE_CASE: &str = "zzzzzzzz";
+
+use std::rc::Weak;
+
+trait BasicEmptyTrait {}
+
+trait CloneSelf {
+    fn clone_self(&self) -> Self;
+}
+
+enum EnumOrdered {
+    A,
+    B,
+    C,
+}
+
+enum EnumUnordered {
+    A,
+    C,
+    B,
+}
+
+#[allow(clippy::arbitrary_source_item_ordering)]
+enum EnumUnorderedAllowed {
+    A,
+    C,
+    B,
+}
+
+struct StructOrdered {
+    a: bool,
+    b: bool,
+    c: bool,
+}
+
+impl Default for StructOrdered {
+    fn default() -> Self {
+        Self {
+            a: true,
+            b: true,
+            c: true,
+        }
+    }
+}
+
+impl CloneSelf for StructOrdered {
+    fn clone_self(&self) -> Self {
+        Self {
+            a: true,
+            b: true,
+            c: true,
+        }
+    }
+}
+
+impl std::clone::Clone for StructOrdered {
+    fn clone(&self) -> Self {
+        Self {
+            a: true,
+            b: true,
+            c: true,
+        }
+    }
+}
+
+#[derive(Default, Clone)]
+struct StructUnordered {
+    a: bool,
+    c: bool,
+    b: bool,
+    d: bool,
+}
+
+struct StructUnorderedGeneric<T> {
+    _1: std::marker::PhantomData<T>,
+    a: bool,
+    c: bool,
+    b: bool,
+    d: bool,
+}
+
+trait TraitOrdered {
+    const A: bool;
+    const B: bool;
+    const C: bool;
+
+    type SomeType;
+
+    fn a();
+    fn b();
+    fn c();
+}
+
+trait TraitUnordered {
+    const A: bool;
+    const C: bool;
+    const B: bool;
+
+    type SomeType;
+
+    fn a();
+    fn c();
+    fn b();
+}
+
+trait TraitUnorderedItemKinds {
+    type SomeType;
+
+    const A: bool;
+    const B: bool;
+    const C: bool;
+
+    fn a();
+    fn b();
+    fn c();
+}
+
+const ZIS_SHOULD_BE_REALLY_EARLY: () = ();
+
+impl TraitUnordered for StructUnordered {
+    const A: bool = false;
+    const C: bool = false;
+    const B: bool = false;
+
+    type SomeType = ();
+
+    fn a() {}
+    fn c() {}
+    fn b() {}
+}
+
+// Trait impls should be located just after the type they implement it for.
+impl BasicEmptyTrait for StructOrdered {}
+
+impl TraitUnorderedItemKinds for StructUnordered {
+    type SomeType = ();
+
+    const A: bool = false;
+    const B: bool = false;
+    const C: bool = false;
+
+    fn a() {}
+    fn b() {}
+    fn c() {}
+}
+
+fn main() {
+    // test code goes here
+}
+
+/// Note that the linting pass is stopped before recursing into this module.
+mod this_is_in_the_wrong_position {
+    const C: i8 = 0;
+    const A: i8 = 1;
+}
+
+#[derive(Default, std::clone::Clone)]
+struct ZisShouldBeBeforeZeMainFn;
+
+const ZIS_SHOULD_BE_EVEN_EARLIER: () = ();
+
+#[cfg(test)]
+mod test {
+    const B: i8 = 1;
+
+    const A: i8 = 0;
+}
diff --git a/tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.rs b/tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.rs
new file mode 100644
index 00000000000..44902336573
--- /dev/null
+++ b/tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.rs
@@ -0,0 +1,174 @@
+//@aux-build:../../ui/auxiliary/proc_macros.rs
+//@revisions: var_1
+//@[var_1] rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/arbitrary_source_item_ordering/var_1
+
+#![allow(dead_code)]
+#![warn(clippy::arbitrary_source_item_ordering)]
+
+/// This module gets linted before clippy gives up.
+mod i_am_just_right {
+    const AFTER: i8 = 0;
+
+    const BEFORE: i8 = 0;
+}
+
+/// Since the upper module passes linting, the lint now recurses into this module.
+mod this_is_in_the_wrong_position {
+    const A: i8 = 1;
+    const C: i8 = 0;
+}
+
+// Use statements should not be linted internally - this is normally auto-sorted using rustfmt.
+use std::rc::{Rc, Weak};
+use std::sync::{Arc, Barrier, RwLock};
+
+const SNAKE_CASE: &str = "zzzzzzzz";
+
+const ZIS_SHOULD_BE_EVEN_EARLIER: () = ();
+
+const ZIS_SHOULD_BE_REALLY_EARLY: () = ();
+
+trait BasicEmptyTrait {}
+
+trait CloneSelf {
+    fn clone_self(&self) -> Self;
+}
+
+enum EnumOrdered {
+    A,
+    B,
+    C,
+}
+
+enum EnumUnordered {
+    A,
+    B,
+    C,
+}
+
+#[allow(clippy::arbitrary_source_item_ordering)]
+enum EnumUnorderedAllowed {
+    A,
+    B,
+    C,
+}
+
+struct StructOrdered {
+    a: bool,
+    b: bool,
+    c: bool,
+}
+
+impl BasicEmptyTrait for StructOrdered {}
+
+impl CloneSelf for StructOrdered {
+    fn clone_self(&self) -> Self {
+        Self {
+            a: true,
+            b: true,
+            c: true,
+        }
+    }
+}
+
+impl Default for StructOrdered {
+    fn default() -> Self {
+        Self {
+            a: true,
+            b: true,
+            c: true,
+        }
+    }
+}
+
+impl std::clone::Clone for StructOrdered {
+    fn clone(&self) -> Self {
+        Self {
+            a: true,
+            b: true,
+            c: true,
+        }
+    }
+}
+
+#[derive(Clone, Default)]
+struct StructUnordered {
+    a: bool,
+    b: bool,
+    c: bool,
+    d: bool,
+}
+
+impl TraitUnordered for StructUnordered {
+    fn a() {}
+    fn c() {}
+    fn b() {}
+
+    type SomeType = ();
+
+    const A: bool = false;
+    const C: bool = false;
+    const B: bool = false;
+}
+
+impl TraitUnorderedItemKinds for StructUnordered {
+    const A: bool = false;
+
+    type SomeType = ();
+
+    fn a() {}
+}
+
+struct StructUnorderedGeneric<T> {
+    _1: std::marker::PhantomData<T>,
+    a: bool,
+    b: bool,
+    c: bool,
+    d: bool,
+}
+
+trait TraitOrdered {
+    fn a();
+    fn b();
+    fn c();
+
+    type SomeType;
+
+    const A: bool;
+    const B: bool;
+    const C: bool;
+}
+
+trait TraitUnordered {
+    fn a();
+    fn c();
+    fn b();
+
+    type SomeType;
+
+    const A: bool;
+    const C: bool;
+    const B: bool;
+}
+
+trait TraitUnorderedItemKinds {
+    const A: bool;
+
+    type SomeType;
+
+    fn a();
+}
+
+#[derive(std::clone::Clone, Default)]
+struct ZisShouldBeBeforeZeMainFn;
+
+fn main() {
+    // test code goes here
+}
+
+#[cfg(test)]
+mod test {
+    const B: i8 = 1;
+
+    const A: i8 = 0;
+}
diff --git a/tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.var_1.stderr b/tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.var_1.stderr
new file mode 100644
index 00000000000..f31f7f68c17
--- /dev/null
+++ b/tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.var_1.stderr
@@ -0,0 +1,100 @@
+error: incorrect ordering of items (must be alphabetically ordered)
+  --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.rs:105:8
+   |
+LL |     fn b() {}
+   |        ^
+   |
+note: should be placed before `c`
+  --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.rs:104:8
+   |
+LL |     fn c() {}
+   |        ^
+   = note: `-D clippy::arbitrary-source-item-ordering` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::arbitrary_source_item_ordering)]`
+
+error: incorrect ordering of items (must be alphabetically ordered)
+  --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.rs:111:11
+   |
+LL |     const B: bool = false;
+   |           ^
+   |
+note: should be placed before `C`
+  --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.rs:110:11
+   |
+LL |     const C: bool = false;
+   |           ^
+
+error: incorrect ordering of impl items (defined order: [Fn, Type, Const])
+  --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.rs:117:5
+   |
+LL |     type SomeType = ();
+   |     ^^^^^^^^^^^^^^^^^^^
+   |
+note: should be placed before `A`
+  --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.rs:115:5
+   |
+LL |     const A: bool = false;
+   |     ^^^^^^^^^^^^^^^^^^^^^^
+
+error: incorrect ordering of impl items (defined order: [Fn, Type, Const])
+  --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.rs:119:5
+   |
+LL |     fn a() {}
+   |     ^^^^^^^^^
+   |
+note: should be placed before `SomeType`
+  --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.rs:117:5
+   |
+LL |     type SomeType = ();
+   |     ^^^^^^^^^^^^^^^^^^^
+
+error: incorrect ordering of items (must be alphabetically ordered)
+  --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.rs:145:8
+   |
+LL |     fn b();
+   |        ^
+   |
+note: should be placed before `c`
+  --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.rs:144:8
+   |
+LL |     fn c();
+   |        ^
+
+error: incorrect ordering of items (must be alphabetically ordered)
+  --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.rs:151:11
+   |
+LL |     const B: bool;
+   |           ^
+   |
+note: should be placed before `C`
+  --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.rs:150:11
+   |
+LL |     const C: bool;
+   |           ^
+
+error: incorrect ordering of trait items (defined order: [Fn, Type, Const])
+  --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.rs:157:5
+   |
+LL |     type SomeType;
+   |     ^^^^^^^^^^^^^^
+   |
+note: should be placed before `A`
+  --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.rs:155:5
+   |
+LL |     const A: bool;
+   |     ^^^^^^^^^^^^^^
+
+error: incorrect ordering of trait items (defined order: [Fn, Type, Const])
+  --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.rs:159:5
+   |
+LL |     fn a();
+   |     ^^^^^^^
+   |
+note: should be placed before `SomeType`
+  --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.rs:157:5
+   |
+LL |     type SomeType;
+   |     ^^^^^^^^^^^^^^
+
+error: aborting due to 8 previous errors
+
diff --git a/tests/ui-toml/arbitrary_source_item_ordering/ordering_only_enum.only_enum.stderr b/tests/ui-toml/arbitrary_source_item_ordering/ordering_only_enum.only_enum.stderr
new file mode 100644
index 00000000000..57069fd8fee
--- /dev/null
+++ b/tests/ui-toml/arbitrary_source_item_ordering/ordering_only_enum.only_enum.stderr
@@ -0,0 +1,16 @@
+error: incorrect ordering of items (must be alphabetically ordered)
+  --> tests/ui-toml/arbitrary_source_item_ordering/ordering_only_enum.rs:22:5
+   |
+LL |     A,
+   |     ^
+   |
+note: should be placed before `B`
+  --> tests/ui-toml/arbitrary_source_item_ordering/ordering_only_enum.rs:21:5
+   |
+LL |     B,
+   |     ^
+   = note: `-D clippy::arbitrary-source-item-ordering` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::arbitrary_source_item_ordering)]`
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui-toml/arbitrary_source_item_ordering/ordering_only_enum.rs b/tests/ui-toml/arbitrary_source_item_ordering/ordering_only_enum.rs
new file mode 100644
index 00000000000..e8002c4a163
--- /dev/null
+++ b/tests/ui-toml/arbitrary_source_item_ordering/ordering_only_enum.rs
@@ -0,0 +1,43 @@
+//@aux-build:../../ui/auxiliary/proc_macros.rs
+//@revisions: only_enum
+//@[only_enum] rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/arbitrary_source_item_ordering/only_enum
+
+#![allow(dead_code)]
+#![warn(clippy::arbitrary_source_item_ordering)]
+
+fn main() {}
+
+struct StructUnordered {
+    b: bool,
+    a: bool,
+}
+
+enum EnumOrdered {
+    A,
+    B,
+}
+
+enum EnumUnordered {
+    B,
+    A,
+}
+
+trait TraitUnordered {
+    const B: bool;
+    const A: bool;
+
+    type SomeType;
+
+    fn b();
+    fn a();
+}
+
+trait TraitUnorderedItemKinds {
+    type SomeType;
+
+    const A: bool;
+
+    fn a();
+}
+
+const ZIS_SHOULD_BE_AT_THE_TOP: () = ();
diff --git a/tests/ui-toml/arbitrary_source_item_ordering/ordering_only_impl.only_impl.stderr b/tests/ui-toml/arbitrary_source_item_ordering/ordering_only_impl.only_impl.stderr
new file mode 100644
index 00000000000..40348ecbdae
--- /dev/null
+++ b/tests/ui-toml/arbitrary_source_item_ordering/ordering_only_impl.only_impl.stderr
@@ -0,0 +1,40 @@
+error: incorrect ordering of items (must be alphabetically ordered)
+  --> tests/ui-toml/arbitrary_source_item_ordering/ordering_only_impl.rs:43:8
+   |
+LL |     fn a() {}
+   |        ^
+   |
+note: should be placed before `b`
+  --> tests/ui-toml/arbitrary_source_item_ordering/ordering_only_impl.rs:42:8
+   |
+LL |     fn b() {}
+   |        ^
+   = note: `-D clippy::arbitrary-source-item-ordering` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::arbitrary_source_item_ordering)]`
+
+error: incorrect ordering of impl items (defined order: [Const, Type, Fn])
+  --> tests/ui-toml/arbitrary_source_item_ordering/ordering_only_impl.rs:45:5
+   |
+LL |     type SomeType = i8;
+   |     ^^^^^^^^^^^^^^^^^^^
+   |
+note: should be placed before `a`
+  --> tests/ui-toml/arbitrary_source_item_ordering/ordering_only_impl.rs:43:5
+   |
+LL |     fn a() {}
+   |     ^^^^^^^^^
+
+error: incorrect ordering of impl items (defined order: [Const, Type, Fn])
+  --> tests/ui-toml/arbitrary_source_item_ordering/ordering_only_impl.rs:47:5
+   |
+LL |     const A: bool = true;
+   |     ^^^^^^^^^^^^^^^^^^^^^
+   |
+note: should be placed before `SomeType`
+  --> tests/ui-toml/arbitrary_source_item_ordering/ordering_only_impl.rs:45:5
+   |
+LL |     type SomeType = i8;
+   |     ^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 3 previous errors
+
diff --git a/tests/ui-toml/arbitrary_source_item_ordering/ordering_only_impl.rs b/tests/ui-toml/arbitrary_source_item_ordering/ordering_only_impl.rs
new file mode 100644
index 00000000000..bd969c865b5
--- /dev/null
+++ b/tests/ui-toml/arbitrary_source_item_ordering/ordering_only_impl.rs
@@ -0,0 +1,67 @@
+//@aux-build:../../ui/auxiliary/proc_macros.rs
+//@revisions: only_impl
+//@[only_impl] rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/arbitrary_source_item_ordering/only_impl
+
+#![allow(dead_code)]
+#![warn(clippy::arbitrary_source_item_ordering)]
+
+fn main() {}
+
+struct StructUnordered {
+    b: bool,
+    a: bool,
+}
+
+struct BasicStruct {}
+
+trait BasicTrait {
+    const A: bool;
+
+    type SomeType;
+
+    fn b();
+    fn a();
+}
+
+enum EnumUnordered {
+    B,
+    A,
+}
+
+trait TraitUnordered {
+    const B: bool;
+    const A: bool;
+
+    type SomeType;
+
+    fn b();
+    fn a();
+}
+
+impl BasicTrait for StructUnordered {
+    fn b() {}
+    fn a() {}
+
+    type SomeType = i8;
+
+    const A: bool = true;
+}
+
+trait TraitUnorderedItemKinds {
+    type SomeType;
+
+    const A: bool;
+
+    fn a();
+}
+
+const ZIS_SHOULD_BE_AT_THE_TOP: () = ();
+
+impl BasicTrait for BasicStruct {
+    const A: bool = true;
+
+    type SomeType = i8;
+
+    fn a() {}
+    fn b() {}
+}
diff --git a/tests/ui-toml/arbitrary_source_item_ordering/ordering_only_trait.only_trait.stderr b/tests/ui-toml/arbitrary_source_item_ordering/ordering_only_trait.only_trait.stderr
new file mode 100644
index 00000000000..9b86ebd48e3
--- /dev/null
+++ b/tests/ui-toml/arbitrary_source_item_ordering/ordering_only_trait.only_trait.stderr
@@ -0,0 +1,40 @@
+error: incorrect ordering of items (must be alphabetically ordered)
+  --> tests/ui-toml/arbitrary_source_item_ordering/ordering_only_trait.rs:32:11
+   |
+LL |     const A: bool;
+   |           ^
+   |
+note: should be placed before `B`
+  --> tests/ui-toml/arbitrary_source_item_ordering/ordering_only_trait.rs:31:11
+   |
+LL |     const B: bool;
+   |           ^
+   = note: `-D clippy::arbitrary-source-item-ordering` implied by `-D warnings`
+   = help: to override `-D warnings` add `#[allow(clippy::arbitrary_source_item_ordering)]`
+
+error: incorrect ordering of items (must be alphabetically ordered)
+  --> tests/ui-toml/arbitrary_source_item_ordering/ordering_only_trait.rs:37:8
+   |
+LL |     fn a();
+   |        ^
+   |
+note: should be placed before `b`
+  --> tests/ui-toml/arbitrary_source_item_ordering/ordering_only_trait.rs:36:8
+   |
+LL |     fn b();
+   |        ^
+
+error: incorrect ordering of trait items (defined order: [Const, Type, Fn])
+  --> tests/ui-toml/arbitrary_source_item_ordering/ordering_only_trait.rs:43:5
+   |
+LL |     const A: bool;
+   |     ^^^^^^^^^^^^^^
+   |
+note: should be placed before `SomeType`
+  --> tests/ui-toml/arbitrary_source_item_ordering/ordering_only_trait.rs:41:5
+   |
+LL |     type SomeType;
+   |     ^^^^^^^^^^^^^^
+
+error: aborting due to 3 previous errors
+
diff --git a/tests/ui-toml/arbitrary_source_item_ordering/ordering_only_trait.rs b/tests/ui-toml/arbitrary_source_item_ordering/ordering_only_trait.rs
new file mode 100644
index 00000000000..979a52ecb10
--- /dev/null
+++ b/tests/ui-toml/arbitrary_source_item_ordering/ordering_only_trait.rs
@@ -0,0 +1,48 @@
+//@aux-build:../../ui/auxiliary/proc_macros.rs
+//@revisions: only_trait
+//@[only_trait] rustc-env:CLIPPY_CONF_DIR=tests/ui-toml/arbitrary_source_item_ordering/only_trait
+
+#![allow(dead_code)]
+#![warn(clippy::arbitrary_source_item_ordering)]
+
+fn main() {}
+
+struct StructUnordered {
+    b: bool,
+    a: bool,
+}
+
+trait TraitOrdered {
+    const A: bool;
+    const B: bool;
+
+    type SomeType;
+
+    fn a();
+    fn b();
+}
+
+enum EnumUnordered {
+    B,
+    A,
+}
+
+trait TraitUnordered {
+    const B: bool;
+    const A: bool;
+
+    type SomeType;
+
+    fn b();
+    fn a();
+}
+
+trait TraitUnorderedItemKinds {
+    type SomeType;
+
+    const A: bool;
+
+    fn a();
+}
+
+const ZIS_SHOULD_BE_AT_THE_TOP: () = ();
diff --git a/tests/ui-toml/arbitrary_source_item_ordering/var_1/clippy.toml b/tests/ui-toml/arbitrary_source_item_ordering/var_1/clippy.toml
new file mode 100644
index 00000000000..bede035e388
--- /dev/null
+++ b/tests/ui-toml/arbitrary_source_item_ordering/var_1/clippy.toml
@@ -0,0 +1 @@
+trait-assoc-item-kinds-order = ["fn", "type", "const"]
diff --git a/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr b/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr
index 5cf9c0fb271..6fa583fc041 100644
--- a/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr
+++ b/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr
@@ -54,12 +54,14 @@ error: error reading Clippy's configuration file: unknown field `foobar`, expect
            max-trait-bounds
            min-ident-chars-threshold
            missing-docs-in-crate-items
+           module-item-order-groupings
            msrv
            pass-by-value-size-limit
            pub-underscore-fields-behavior
            semicolon-inside-block-ignore-singleline
            semicolon-outside-block-ignore-multiline
            single-char-binding-names-threshold
+           source-item-ordering
            stack-size-threshold
            standard-macro-braces
            struct-field-name-threshold
@@ -68,6 +70,7 @@ error: error reading Clippy's configuration file: unknown field `foobar`, expect
            too-large-for-stack
            too-many-arguments-threshold
            too-many-lines-threshold
+           trait-assoc-item-kinds-order
            trivial-copy-size-limit
            type-complexity-threshold
            unnecessary-box-size
@@ -138,12 +141,14 @@ error: error reading Clippy's configuration file: unknown field `barfoo`, expect
            max-trait-bounds
            min-ident-chars-threshold
            missing-docs-in-crate-items
+           module-item-order-groupings
            msrv
            pass-by-value-size-limit
            pub-underscore-fields-behavior
            semicolon-inside-block-ignore-singleline
            semicolon-outside-block-ignore-multiline
            single-char-binding-names-threshold
+           source-item-ordering
            stack-size-threshold
            standard-macro-braces
            struct-field-name-threshold
@@ -152,6 +157,7 @@ error: error reading Clippy's configuration file: unknown field `barfoo`, expect
            too-large-for-stack
            too-many-arguments-threshold
            too-many-lines-threshold
+           trait-assoc-item-kinds-order
            trivial-copy-size-limit
            type-complexity-threshold
            unnecessary-box-size
@@ -222,12 +228,14 @@ error: error reading Clippy's configuration file: unknown field `allow_mixed_uni
            max-trait-bounds
            min-ident-chars-threshold
            missing-docs-in-crate-items
+           module-item-order-groupings
            msrv
            pass-by-value-size-limit
            pub-underscore-fields-behavior
            semicolon-inside-block-ignore-singleline
            semicolon-outside-block-ignore-multiline
            single-char-binding-names-threshold
+           source-item-ordering
            stack-size-threshold
            standard-macro-braces
            struct-field-name-threshold
@@ -236,6 +244,7 @@ error: error reading Clippy's configuration file: unknown field `allow_mixed_uni
            too-large-for-stack
            too-many-arguments-threshold
            too-many-lines-threshold
+           trait-assoc-item-kinds-order
            trivial-copy-size-limit
            type-complexity-threshold
            unnecessary-box-size