From 98d3012ed9fa2a812968fe1dc034670cfb571680 Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Mon, 21 Aug 2023 00:37:06 -0700 Subject: [PATCH] Use version-sorting for all sorting Add a description of a version-sorting algorithm. (This algorithm does not precisely match `strverscmp`; it's intentionally simpler in its handling of leading zeroes, and produces a result easier for humans to easily understand and do by hand.) Change all references to sorting to use version-sorting. Change all references to "ASCIIbetically" to instead say "sort non-lowercase before lowercase". --- src/doc/style-guide/src/README.md | 36 +++++++++++++++++++++++++++++ src/doc/style-guide/src/cargo.md | 6 ++--- src/doc/style-guide/src/editions.md | 2 ++ src/doc/style-guide/src/items.md | 23 +++++++++++------- 4 files changed, 56 insertions(+), 11 deletions(-) diff --git a/src/doc/style-guide/src/README.md b/src/doc/style-guide/src/README.md index f4d759673700..dd80966d15c1 100644 --- a/src/doc/style-guide/src/README.md +++ b/src/doc/style-guide/src/README.md @@ -99,6 +99,42 @@ fn bar() {} fn baz() {} ``` +### Sorting + +In various cases, the default Rust style specifies to sort things. If not +otherwise specified, such sorting should be "version sorting", which ensures +that (for instance) `x8` comes before `x16` even though the character `1` comes +before the character `8`. (If not otherwise specified, version-sorting is +lexicographical.) + +For the purposes of the Rust style, to compare two strings for version-sorting: + +- Compare the strings by (Unicode) character as normal, finding the index of + the first differing character. (If the two strings do not have the same + length, this may be the end of the shorter string.) +- For both strings, determine the sequence of ASCII digits containing either + that character or the character before. (If either string doesn't have such a + sequence of ASCII digits, fall back to comparing the strings as normal.) +- Compare the numeric values of the number specified by the sequence of digits. + (Note that an implementation of this algorithm can easily check this without + accumulating copies of the digits or converting to a number: longer sequences + of digits are larger numbers, equal-length sequences can be sorted + lexicographically.) +- If the numbers have the same numeric value, the one with more leading zeroes + comes first. + +Note that there exist various algorithms called "version sorting", which differ +most commonly in their handling of numbers with leading zeroes. This algorithm +does not purport to precisely match the behavior of any particular other +algorithm, only to produce a simple and satisfying result for Rust formatting. +(In particular, this algorithm aims to produce a satisfying result for a set of +symbols that have the same number of leading zeroes, and an acceptable and +easily understandable result for a set of symbols that has varying numbers of +leading zeroes.) + +As an example, version-sorting will sort the following symbols in the order +given: `x000`, `x00`, `x0`, `x01`, `x1`, `x09`, `x9`, `x010`, `x10`. + ### [Module-level items](items.md) ### [Statements](statements.md) diff --git a/src/doc/style-guide/src/cargo.md b/src/doc/style-guide/src/cargo.md index d3b67ae45825..d47d04642280 100644 --- a/src/doc/style-guide/src/cargo.md +++ b/src/doc/style-guide/src/cargo.md @@ -8,11 +8,11 @@ Put a blank line between the last key-value pair in a section and the header of the next section. Do not place a blank line between section headers and the key-value pairs in that section, or between key-value pairs in a section. -Sort key names alphabetically within each section, with the exception of the +Version-sort key names within each section, with the exception of the `[package]` section. Put the `[package]` section at the top of the file; put the `name` and `version` keys in that order at the top of that section, -followed by the remaining keys other than `description` in alphabetical order, -followed by the `description` at the end of that section. +followed by the remaining keys other than `description` in order, followed by +the `description` at the end of that section. Don't use quotes around any standard key names; use bare keys. Only use quoted keys for non-standard keys whose names require them, and avoid introducing such diff --git a/src/doc/style-guide/src/editions.md b/src/doc/style-guide/src/editions.md index 5c67a185b8ff..19e62c4867c9 100644 --- a/src/doc/style-guide/src/editions.md +++ b/src/doc/style-guide/src/editions.md @@ -37,6 +37,8 @@ history of the style guide. Notable changes in the Rust 2024 style edition include: - Miscellaneous `rustfmt` bugfixes. +- Use version-sort (sort `x8`, `x16`, `x32`, `x64`, `x128` in that order). +- Change "ASCIIbetical" sort to Unicode-aware "non-lowercase before lowercase". ## Rust 2015/2018/2021 style edition diff --git a/src/doc/style-guide/src/items.md b/src/doc/style-guide/src/items.md index a6d941f6d045..e00e5a990381 100644 --- a/src/doc/style-guide/src/items.md +++ b/src/doc/style-guide/src/items.md @@ -9,8 +9,8 @@ an item appears at module level or within another item. alphabetically. `use` statements, and module *declarations* (`mod foo;`, not `mod { ... }`) -must come before other items. Put imports before module declarations. Sort each -alphabetically, except that `self` and `super` must come before any other +must come before other items. Put imports before module declarations. +Version-sort each, except that `self` and `super` must come before any other names. Don't automatically move module declarations annotated with `#[macro_use]`, @@ -441,8 +441,10 @@ foo::{ A *group* of imports is a set of imports on the same or sequential lines. One or more blank lines or other items (e.g., a function) separate groups of imports. -Within a group of imports, imports must be sorted ASCIIbetically (uppercase -before lowercase). Groups of imports must not be merged or re-ordered. +Within a group of imports, imports must be version-sorted, except that +non-lowercase characters (characters that can start an `UpperCamelCase` +identifier) must be sorted before lowercase characters. Groups of imports must +not be merged or re-ordered. E.g., input: @@ -469,10 +471,15 @@ re-ordering. ### Ordering list import -Names in a list import must be sorted ASCIIbetically, but with `self` and -`super` first, and groups and glob imports last. This applies recursively. For -example, `a::*` comes before `b::a` but `a::b` comes before `a::*`. E.g., -`use foo::bar::{a, b::c, b::d, b::d::{x, y, z}, b::{self, r, s}};`. +Names in a list import must be version-sorted, except that: +- `self` and `super` always come first if present, +- non-lowercase characters (characters that can start an `UpperCamelCase` + identifier) must be sorted before lowercase characters, and +- groups and glob imports always come last if present. + +This applies recursively. For example, `a::*` comes before `b::a` but `a::b` +comes before `a::*`. E.g., `use foo::bar::{a, b::c, b::d, b::d::{x, y, z}, +b::{self, r, s}};`. ### Normalisation