feat(useSortedClasses): order variants in sort_v4 - #11249
feat(useSortedClasses): order variants in sort_v4#11249johncarmack1984 wants to merge 8 commits into
Conversation
Wires jiwon79's variant engine into the current sort_v4 sort key: variant_bits sort outermost, resolved in a two-phase classify pass. Regenerates the v4 preset (variants + breakpoint/container value maps) and adds variant fixtures.
|
✅ Organic activityNo automation signals detected in the analyzed events. This is an automated analysis by AgentScan |
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
WalkthroughTailwind v4 variant metadata is extracted and generated as Rust maps for variants, breakpoints, and containers. The sorter parses static, functional, compound, and arbitrary variants. It groups recognised variants across the complete candidate list and compares variant weights before existing sort keys. Tests cover variant, responsive, compound, important, and arbitrary breakpoint ordering. Possibly related PRs
Suggested labels: Suggested reviewers: 🚥 Pre-merge checks | ✅ 4✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (8)
crates/biome_js_analyze/src/lint/nursery/use_sorted_classes/sort_v4_variants.rs (2)
74-110: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueConsider documenting the
bits_forNonecontract.
bits_forreturnsNonewhen a variant is missing fromgroups, andinto_sort_keyturns that intoSortKey::Unknown. In the production path this cannot happen, becauseVariantGroups::newreceives exactly the variants of everyKnownpending key. The fallback is therefore defensive, which is fine, but a reader has to reconstruct that reasoning.One line of rustdoc on
bits_forstating "returnsNoneif a variant was not part of the list the groups were built from" would save that effort.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@crates/biome_js_analyze/src/lint/nursery/use_sorted_classes/sort_v4_variants.rs` around lines 74 - 110, Document the `VariantGroups::bits_for` contract with one line of rustdoc stating that it returns `None` when any requested variant was not included in the variants used to construct the groups.
208-216: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueThe
Option<Option<VariantValue>>return can collapse toOption<VariantValue>.The outer
Optionmeans "this shape is acceptable" and the inner one means "a value is present". Every arm returns eitherNoneorSome(Some(_)), so the innerNoneis unreachable. The double wrapping makes the call site at Line 170 harder to read than the logic warrants.Proposed simplification
-fn variant_value_from_segments(segments: &[VariantSegment]) -> Option<Option<VariantValue>> { +fn variant_value_from_segments(segments: &[VariantSegment]) -> Option<VariantValue> { match segments { - [] => None, - [VariantSegment::Named(value)] => Some(Some(VariantValue::Named(value.clone()))), - [VariantSegment::Arbitrary(value)] => Some(Some(VariantValue::Arbitrary(value.clone()))), - [VariantSegment::CssVariable] => None, + [VariantSegment::Named(value)] => Some(VariantValue::Named(value.clone())), + [VariantSegment::Arbitrary(value)] => Some(VariantValue::Arbitrary(value.clone())), _ => None, } }The call site then becomes:
VariantKind::Functional => Some(VariantKey::Functional { root, - value: variant_value_from_segments(value_segments)?, + value: Some(variant_value_from_segments(value_segments)?), }),
VariantKey::Functional::valuestaysOption<VariantValue>, so the shape at rest is unchanged.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@crates/biome_js_analyze/src/lint/nursery/use_sorted_classes/sort_v4_variants.rs` around lines 208 - 216, Change variant_value_from_segments to return Option<VariantValue>, using None for unsupported or valueless segment shapes and Some for named or arbitrary values. Update its call site around VariantKey::Functional value construction to use the simplified result directly, while preserving the existing Option<VariantValue> field shape.crates/biome_js_analyze/src/lint/nursery/use_sorted_classes/tailwind_preset_v4_types.rs (1)
118-125: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winDocument the
compoundsandcompounds_withbitflag semantics.
kind,order, andcompareexplain themselves.compoundsandcompounds_withdo not. They carry Tailwind'sCompoundsbitflag values (StyleRules = 1,AtRules = 2), so a bare2in the generated map is unreadable. The siblingUtilityEntryandFunctionalEntryin this file already document their non-obvious fields, so this would match.Proposed rustdoc
pub struct VariantEntry { pub kind: VariantKind, pub order: u16, pub compare: VariantCompare, + /// Tailwind's `Compounds` bitflags for what this variant produces: + /// `1` = style rules, `2` = at-rules, `0` = neither. pub compounds: u8, + /// Tailwind's `Compounds` bitflags for what a compound variant + /// accepts as its nested variant. pub compounds_with: u8, }As per coding guidelines: "Use rustdoc documentation for documenting new features, rule changes, and rule/assist options in Rust code".
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@crates/biome_js_analyze/src/lint/nursery/use_sorted_classes/tailwind_preset_v4_types.rs` around lines 118 - 125, Update the Rustdoc for the VariantEntry fields compounds and compounds_with to describe their Tailwind Compounds bitflag semantics, including StyleRules = 1 and AtRules = 2, matching the documentation style used by UtilityEntry and FunctionalEntry. Leave the other fields unchanged.Source: Coding guidelines
packages/tailwindcss-config-analyzer/src/v4/render-rust.ts (1)
342-361: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueTwo small nits in the new renderers.
First, visibility. These two renderers emit
pub static, butrenderThemeKeysjust above emitspub(super) static. The only consumer issort_v4_variants, which is a descendant ofuse_sorted_classes, sopub(super)reaches it exactly as it reaches the theme-key sets. Matching the existing convention keeps the generated surface tight.Second, shadowing. Inside
renderThemeValueMap, the destructured{ name, value }shadows thenameparameter. The template happens to use the outernameoutside the callback, so it works today. A future edit that needs the map name inside the callback would silently pick up the entry name instead.Proposed fix
- return `pub static VARIANTS: phf::Map<&'static str, VariantEntry> = phf_map! { + return `pub(super) static VARIANTS: phf::Map<&'static str, VariantEntry> = phf_map! { ${lines.join("\n")} }; `; } -function renderThemeValueMap(name: string, values: ThemeValue[]): string { +function renderThemeValueMap(mapName: string, values: ThemeValue[]): string { const lines = values.map( ({ name, value }) => ` ${rustString(name)} => ${rustString(value)},`, ); - return `pub static ${name}: phf::Map<&'static str, &'static str> = phf_map! { + return `pub(super) static ${mapName}: phf::Map<&'static str, &'static str> = phf_map! { ${lines.join("\n")} }; `; }The generated
tailwind_preset_v4.rsneeds regenerating to match.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/tailwindcss-config-analyzer/src/v4/render-rust.ts` around lines 342 - 361, Update renderVariants and renderThemeValueMap to emit pub(super) static, matching renderThemeKeys and keeping the generated visibility limited to the required consumer. In renderThemeValueMap, rename the destructured theme entry name to avoid shadowing the name parameter while preserving the generated map name and values. Regenerate tailwind_preset_v4.rs so it reflects the updated visibility.crates/biome_js_analyze/tests/sort_v4/cases.jsonc (2)
219-236: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winAdd container-query fixtures.
ContainerAscandContainerDesccurrently have no coverage.The 13 new fixtures cover a good spread: pseudo-class, arbitrary, data, aria, nth, peer, group, has, not, responsive, and compound. Nice work on the breadth.
One whole comparison mode is missing though.
CONTAINER_VALUESand theContainerAscandContainerDescarms ofcompare_variant_valuesare new in this PR, and no fixture exercises them. Line 231 covers the breakpoint equivalents thoroughly, so the container side is the asymmetry.Suggested additional fixtures
"md:flex sm:flex flex max-lg:flex max-sm:flex min-lg:flex", + "`@lg`:flex `@sm`:flex flex `@max-lg`:flex `@max-sm`:flex `@min-lg`:flex", + "`@min-`[30rem]:flex `@lg`:flex flex", + "dark:flex hover:flex flex", "md:hover:flex hover:flex flex",The
dark:case is a smaller point, since the PR description lists dark mode as covered but no fixture names it.As per coding guidelines: "parser, formatter, and lint-rule changes must cover their required valid, invalid, or snapshot cases".
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@crates/biome_js_analyze/tests/sort_v4/cases.jsonc` around lines 219 - 236, Add container-query sorting fixtures to the variants section in cases.jsonc so both ContainerAsc and ContainerDesc paths in compare_variant_values are exercised, matching the existing responsive breakpoint coverage pattern. Include representative container variants, including a dark: case if applicable, while preserving the expected ordering format used by the surrounding fixtures.Source: Coding guidelines
219-222: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueThe section header does not match its contents.
The header at Line 219 says "variants + important suffix". Lines 224 to 232 carry no
!at all, and Lines 233, 235, and 236 carry no variant. Only Line 234 is genuinely both.Two headers would map cleanly onto the two groups, which helps the next person adding a case pick the right spot.
Also applies to: 233-236
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@crates/biome_js_analyze/tests/sort_v4/cases.jsonc` around lines 219 - 222, Split the misleading section header around the relevant test cases: use one header for the variant-ordering cases and another for the important-suffix cases, with a distinct header for the single case combining both if needed. Ensure the headers accurately describe the `!` and variant usage in cases 224–236.packages/tailwindcss-config-analyzer/src/v4/extract-variants.ts (1)
70-70: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick winUse a locale-independent comparator for the committed artefact.
localeComparewithout an explicit locale follows the host ICU collation. This generator writestailwind_preset_v4.rs, which is committed and diffed byte-wise. Two contributors on different locales can therefore produce two different files from the same Tailwind version.The variant names include punctuation (
*,**,@,@max,@min), and ICU treats punctuation quite unlike code-point order, so the tie-break at Line 70 is the most exposed.Proposed fix
- .sort((a, b) => a.order - b.order || a.name.localeCompare(b.name)); + .sort((a, b) => a.order - b.order || (a.name < b.name ? -1 : a.name > b.name ? 1 : 0));return [...ds.theme.namespace(namespace)] .map(([name, value]) => ({ name, value })) - .sort((a, b) => a.name.localeCompare(b.name)); + .sort((a, b) => (a.name < b.name ? -1 : a.name > b.name ? 1 : 0));Also applies to: 79-82
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/tailwindcss-config-analyzer/src/v4/extract-variants.ts` at line 70, Replace the locale-dependent tie-break comparator in the variant sorting logic with a deterministic locale-independent comparison, using code-point or equivalent stable ordering for variant names. Apply the same change to the additional sorting block around the related variant ordering logic, while preserving the primary order comparison.crates/biome_js_analyze/src/lint/nursery/use_sorted_classes/sort_v4.rs (1)
615-627: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winThe
classifyhelper cannot express variant-against-variant ordering.
classifybuildsVariantGroupsfrom one candidate, so each call gets its own group map. Any single variant lands in group 0 and produces bits[1].The consequence:
compare(&classify("sm:flex"), &classify("md:flex"))compares equal bits, then falls through to signature and name. The assertion would pass or fail for reasons unrelated to variant ordering. The test at Line 966 works only becauseflexhas no variants at all, so the length check incmp_numericdecides it.So the variant ordering that this PR is about is currently covered only by the
cases.jsoncsnapshots. A helper that shares one group map across several inputs would make the comparator directly testable, including the breakpoint ordering.Sketch of a list-wide helper
/// Classify a whole class list against one shared `VariantGroups`, /// the way `sort_class_list` does. fn classify_all(input: &str) -> Vec<SortKey> { let parsed = parse_tailwind(input); let pending: Vec<PendingSortKey> = parsed .tree() .candidates() .iter() .map(|candidate| PendingSortKey::from_candidate(&candidate)) .collect(); let groups = VariantGroups::new(pending.iter().flat_map(|key| match key { PendingSortKey::Known { variants, .. } => variants.as_slice(), PendingSortKey::Unknown => &[], })); pending .into_iter() .map(|key| key.into_sort_key(&groups)) .collect() }A test could then assert directly that
sm:flexprecedesmd:flex, and thatmax-lg:flexprecedesmax-sm:flex.As per coding guidelines: "All code changes must include appropriate tests".
Also applies to: 958-969
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@crates/biome_js_analyze/src/lint/nursery/use_sorted_classes/sort_v4.rs` around lines 615 - 627, Update the test helpers around classify and the affected assertions so variant ordering is evaluated with one shared VariantGroups across the entire class list, rather than constructing groups per candidate. Add a classify_all helper that parses all candidates, collects their variants, creates shared groups, and converts each PendingSortKey; use it to directly test breakpoint ordering such as sm:flex before md:flex and max-lg:flex before max-sm:flex, while preserving existing plain-utility comparisons.Source: Coding guidelines
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In
`@crates/biome_js_analyze/src/lint/nursery/use_sorted_classes/sort_v4_variants.rs`:
- Around line 267-314: Update variant_compare_value, used by
compare_variant_values, to return a fixed extreme numeric rank instead of None
when a breakpoint or container value cannot be parsed, while preserving normal
parsed-value ordering and the existing Default behavior. Ensure the resulting
comparator is total and cannot create input-order-dependent cycles, and add a
regression case covering mixed known, parseable arbitrary, and unparseable
breakpoint/container variants such as sm, min-[50rem], and min-[foo].
In `@packages/tailwindcss-config-analyzer/src/v4/extract-variants.ts`:
- Around line 52-55: Add a runtime shape guard around the design system loaded
by __unstable__loadDesignSystem before exporting variants, verifying
variants.variants, sort order, and compoundsWith are present with the expected
structure. If validation fails, use the existing fallback path instead of
accessing the private internals; avoid relying on the DesignSystemWithVariants
cast to validate renamed or missing fields.
---
Nitpick comments:
In
`@crates/biome_js_analyze/src/lint/nursery/use_sorted_classes/sort_v4_variants.rs`:
- Around line 74-110: Document the `VariantGroups::bits_for` contract with one
line of rustdoc stating that it returns `None` when any requested variant was
not included in the variants used to construct the groups.
- Around line 208-216: Change variant_value_from_segments to return
Option<VariantValue>, using None for unsupported or valueless segment shapes and
Some for named or arbitrary values. Update its call site around
VariantKey::Functional value construction to use the simplified result directly,
while preserving the existing Option<VariantValue> field shape.
In `@crates/biome_js_analyze/src/lint/nursery/use_sorted_classes/sort_v4.rs`:
- Around line 615-627: Update the test helpers around classify and the affected
assertions so variant ordering is evaluated with one shared VariantGroups across
the entire class list, rather than constructing groups per candidate. Add a
classify_all helper that parses all candidates, collects their variants, creates
shared groups, and converts each PendingSortKey; use it to directly test
breakpoint ordering such as sm:flex before md:flex and max-lg:flex before
max-sm:flex, while preserving existing plain-utility comparisons.
In
`@crates/biome_js_analyze/src/lint/nursery/use_sorted_classes/tailwind_preset_v4_types.rs`:
- Around line 118-125: Update the Rustdoc for the VariantEntry fields compounds
and compounds_with to describe their Tailwind Compounds bitflag semantics,
including StyleRules = 1 and AtRules = 2, matching the documentation style used
by UtilityEntry and FunctionalEntry. Leave the other fields unchanged.
In `@crates/biome_js_analyze/tests/sort_v4/cases.jsonc`:
- Around line 219-236: Add container-query sorting fixtures to the variants
section in cases.jsonc so both ContainerAsc and ContainerDesc paths in
compare_variant_values are exercised, matching the existing responsive
breakpoint coverage pattern. Include representative container variants,
including a dark: case if applicable, while preserving the expected ordering
format used by the surrounding fixtures.
- Around line 219-222: Split the misleading section header around the relevant
test cases: use one header for the variant-ordering cases and another for the
important-suffix cases, with a distinct header for the single case combining
both if needed. Ensure the headers accurately describe the `!` and variant usage
in cases 224–236.
In `@packages/tailwindcss-config-analyzer/src/v4/extract-variants.ts`:
- Line 70: Replace the locale-dependent tie-break comparator in the variant
sorting logic with a deterministic locale-independent comparison, using
code-point or equivalent stable ordering for variant names. Apply the same
change to the additional sorting block around the related variant ordering
logic, while preserving the primary order comparison.
In `@packages/tailwindcss-config-analyzer/src/v4/render-rust.ts`:
- Around line 342-361: Update renderVariants and renderThemeValueMap to emit
pub(super) static, matching renderThemeKeys and keeping the generated visibility
limited to the required consumer. In renderThemeValueMap, rename the
destructured theme entry name to avoid shadowing the name parameter while
preserving the generated map name and values. Regenerate tailwind_preset_v4.rs
so it reflects the updated visibility.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: 134adbc0-c6b5-4f9a-8394-8d25699f4091
⛔ Files ignored due to path filters (1)
crates/biome_js_analyze/tests/sort_v4/cases.snapis excluded by!**/*.snapand included by**
📒 Files selected for processing (9)
crates/biome_js_analyze/src/lint/nursery/use_sorted_classes.rscrates/biome_js_analyze/src/lint/nursery/use_sorted_classes/sort_v4.rscrates/biome_js_analyze/src/lint/nursery/use_sorted_classes/sort_v4_variants.rscrates/biome_js_analyze/src/lint/nursery/use_sorted_classes/tailwind_preset_v4.rscrates/biome_js_analyze/src/lint/nursery/use_sorted_classes/tailwind_preset_v4_types.rscrates/biome_js_analyze/tests/sort_v4/cases.jsoncpackages/tailwindcss-config-analyzer/src/v4/extract-variants.tspackages/tailwindcss-config-analyzer/src/v4/generate-tailwind-preset-v4.tspackages/tailwindcss-config-analyzer/src/v4/render-rust.ts
Merging this PR will degrade performance by 15.08%
Warning Please fix the performance issues or acknowledge them on CodSpeed. Performance Changes
Tip Investigate this regression by commenting Comparing Footnotes
|
- make the breakpoint/container value comparator total, so an unparseable arbitrary value ranks last instead of comparing equal to everything (which was non-transitive) - sort the variant codegen by code point rather than locale, keeping the generated preset deterministic across machines - limit the generated variant tables to pub(super) - collapse a redundant Option and document the Compounds bitflags - add dark-mode and variant-vs-variant test coverage
|
@codspeedbot this seems to be a layout artifact, no executed code was changed in this PR |
|
@codspeedbot done |
dyc3
left a comment
There was a problem hiding this comment.
I don't really understand the sorting logic going on here. can you explain it?
…strings - Rename VariantBits to VariantWeight; replace cmp_numeric with Ord/PartialOrd - Store registered variant roots as &'static str and named values as TokenText - Keep the variant-key grouping comparator a free function, documented - Add module and type docs explaining the two-pass variant weighting
There was a problem hiding this comment.
🧹 Nitpick comments (1)
crates/biome_js_analyze/src/lint/nursery/use_sorted_classes/sort_v4_variants.rs (1)
193-198: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueRemove the change-history wording from this comment.
The phrase “kept for now to preserve behavior” describes history, not an invariant. Remove it, or replace it with the semantic reason that requires the early lookup.
As per coding guidelines, “For developer-facing comments, explain behavior, invariants, panics, module rationale, or non-obvious rationale; do not narrate change history or address reviewers.”
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@crates/biome_js_analyze/src/lint/nursery/use_sorted_classes/sort_v4_variants.rs` around lines 193 - 198, Update the comment above raw in the expression lookup to remove the change-history wording about being “kept for now to preserve behavior”; retain only the semantic explanation for why the early check remains, or remove that sentence if no invariant or non-obvious rationale applies.Source: Coding guidelines
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In
`@crates/biome_js_analyze/src/lint/nursery/use_sorted_classes/sort_v4_variants.rs`:
- Around line 193-198: Update the comment above raw in the expression lookup to
remove the change-history wording about being “kept for now to preserve
behavior”; retain only the semantic explanation for why the early check remains,
or remove that sentence if no invariant or non-obvious rationale applies.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: 68389785-7cb6-4d76-b3f4-76fe3774e697
📒 Files selected for processing (2)
crates/biome_js_analyze/src/lint/nursery/use_sorted_classes/sort_v4.rscrates/biome_js_analyze/src/lint/nursery/use_sorted_classes/sort_v4_variants.rs
🚧 Files skipped from review as they are similar to previous changes (1)
- crates/biome_js_analyze/src/lint/nursery/use_sorted_classes/sort_v4.rs
Replace the compare_variant_keys free function with an Ord/PartialOrd impl on VariantKey, and simplify VariantGroups::new to variants.sort().
|
Note GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer. |
|
Fine time for GitHub Actions to have an outage ^_^ afaik everything but codspeed should pass, an 'acknowledge' on codspeed and a re-run post-incident should turn the checks green, meanwhile happy to address any other feedback on the changes :) |
…ions Store the variant weight inline in a SmallVec so the common case does not heap-allocate, and rank variants with a sorted Vec + binary search instead of building a HashMap per class list.
Summary
Finishing touches to @jiwon79 's branch codex/use-sorted-classes-v4-variants from June.
This PR adds variant-prefixed classes (
hover:,sm:/md:,dark:,data-[...]:,[&:hover]:,has-[...]:, compounds likemd:hover:) tosort_v4. Previously, any variant made the candidateUnknownand floated it to the front in input order. Variant weight is the outermost sort key, places variantless utilities first; variants group in Tailwind's canonical order. This necessitates a two-phase sort: classify, then gather every variant in the list into theVariantGroups, then assign each aVariantBits, then sort. A variant's rank is relative to the whole list.Followup to #10880, #11016, #11041, #11076, and #11120. As with those, AI tools were used to identify the next step in useSortedClasses nursery promotion and brainstorm idiomatic solutions based on the previous work from jiwon. This implementation was chosen for its performance, integration of previous feedback, adherence to repo conventions, and inclusion of new snapshots to test updated functionality.
No user-facing behavior change, therefore no changeset;
sort_v4is (for now) unwired.Test Plan
Docs
No rule, rustdoc, or website change (no user-facing behavior as sort_v4 is as-yet unwired).
Planned follow-up PRs: