Skip to content

fix: Rust 1.81+ sort_by total order compliance#2

Merged
StarTuz merged 2 commits intoStarTuz:mainfrom
mmaechtel:fix/rust-1.81-sort-compat
Feb 23, 2026
Merged

fix: Rust 1.81+ sort_by total order compliance#2
StarTuz merged 2 commits intoStarTuz:mainfrom
mmaechtel:fix/rust-1.81-sort-compat

Conversation

@mmaechtel
Copy link
Contributor

Summary

Rust 1.81+ enforces strict total ordering checks in sort_by() comparators, causing runtime panics in two locations:

  • sorter.rs — The SimHeaven tiebreaker violated transitivity: comparing a SimHeaven pack to a non-SimHeaven pack at the same score tier returned Equal, but two SimHeaven packs with different layers returned Less/Greater. Fixed by adding else-branches for the mixed case (+4 lines).
  • iced_graphics::damage::group() — Uses partial_cmp().unwrap_or(Equal) on f32 distances, which breaks transitivity when NaN values appear. This is a known upstream issue (iced-rs/iced#2650), fixed in iced 0.14 via PR #2651. Backported here as a local [patch.crates-io] vendor under patches/iced_graphics/ — the only change is partial_cmp(...).unwrap_or(Equal)total_cmp(...) in damage.rs. Remove this patch when upgrading to iced 0.14+.

Test plan

  • All 167 cargo test tests pass
  • GUI starts and completes full scenery scan (1480 packs) without panic
  • Verified on Rust 1.92, NVIDIA RTX 4090, Wayland (GL fallback path)

🤖 Generated with Claude Code

Rust 1.81+ enforces strict total ordering checks in sort_by(). The
SimHeaven tiebreaker violated transitivity: when comparing a SimHeaven
pack to a non-SimHeaven pack at the same score tier, Equal was returned,
but two SimHeaven packs with different layers returned Less/Greater.
This caused a panic at runtime.

Add else-branches for the mixed case (one SimHeaven, one not) to group
SimHeaven packs before non-SimHeaven at the same score tier.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@qodo-code-review
Copy link

Review Summary by Qodo

Fix Rust 1.81+ sort_by total order compliance in sorter and damage region sorting

🐞 Bug fix

Grey Divider

Walkthroughs

Description
• Fixed Rust 1.81+ strict total ordering compliance in two critical locations that caused runtime
  panics
• **sorter.rs**: Resolved SimHeaven tiebreaker transitivity violation by adding else-branches
  for mixed SimHeaven/non-SimHeaven pack comparisons at the same score tier
• **patches/iced_graphics/src/damage.rs**: Fixed NaN handling in damage region sorting by
  replacing partial_cmp().unwrap_or(Equal) with total_cmp() for f32 distance comparisons
• Added complete local iced_graphics 0.13.0 patch under patches/iced_graphics/ as a workaround
  for upstream issue (iced-rs/iced#2650), to be removed when upgrading to iced 0.14+
• All 167 tests pass; GUI successfully completes full scenery scan (1480 packs) without panic
Diagram
flowchart LR
  A["Rust 1.81+ strict<br/>total ordering checks"]
  B["sorter.rs<br/>SimHeaven comparator"]
  C["iced_graphics damage.rs<br/>f32 distance sorting"]
  D["Add else-branches<br/>for mixed cases"]
  E["Replace partial_cmp<br/>with total_cmp"]
  F["Compliance achieved<br/>No panics"]
  
  A --> B
  A --> C
  B --> D
  C --> E
  D --> F
  E --> F
Loading

Grey Divider

File Changes

1. crates/x-adox-core/src/scenery/sorter.rs 🐞 Bug fix +4/-0

Fix SimHeaven comparator transitivity for Rust 1.81+

• Fixed transitivity violation in SimHeaven tiebreaker comparator by adding else-branches for
 mixed SimHeaven/non-SimHeaven pack comparisons
• Ensures total ordering compliance required by Rust 1.81+ sort_by() strict checks
• Prevents runtime panics when comparing packs at the same score tier

crates/x-adox-core/src/scenery/sorter.rs


2. patches/iced_graphics/src/text/editor.rs ✨ Enhancement +781/-0

Add iced_graphics text editor module implementation

• Added complete text editor implementation with multi-line support and cosmic_text integration
• Implements cursor positioning, selection, text editing (insert, delete, backspace), and motion
 operations
• Supports syntax highlighting, text wrapping, and font system integration

patches/iced_graphics/src/text/editor.rs


3. patches/iced_graphics/src/text/paragraph.rs ✨ Enhancement +430/-0

Add iced_graphics paragraph text rendering module

• Added paragraph text rendering with support for plain and rich text (spans)
• Implements text measurement, hit testing, span bounds calculation, and grapheme positioning
• Integrates with cosmic_text buffer and font system for text layout

patches/iced_graphics/src/text/paragraph.rs


View more (29)
4. patches/iced_graphics/src/text.rs ✨ Enhancement +324/-0

Add iced_graphics text system and font management

• Added core text module with font system management and text primitive types
• Implements FontSystem for loading fonts and managing versions
• Provides conversion utilities for font attributes, shaping, wrapping, and color to cosmic_text
 types

patches/iced_graphics/src/text.rs


5. patches/iced_graphics/src/geometry/frame.rs ✨ Enhancement +290/-0

Add iced_graphics geometry frame drawing abstraction

• Added frame abstraction for drawing geometry with transformation and clipping support
• Implements path stroking/filling, text rendering, image/SVG drawing, and transform stack
 management
• Provides Backend trait for renderer implementations

patches/iced_graphics/src/geometry/frame.rs


6. patches/iced_graphics/src/geometry/path/builder.rs ✨ Enhancement +261/-0

Add iced_graphics path builder for 2D shapes

• Added path builder for constructing 2D shapes (lines, arcs, curves, rectangles, circles)
• Implements Bézier curves, arc-to operations, and rounded rectangle support
• Uses lyon_path for underlying path construction

patches/iced_graphics/src/geometry/path/builder.rs


7. patches/iced_graphics/src/gradient.rs ✨ Enhancement +191/-0

Add iced_graphics gradient fill support

• Added linear gradient support with color stops and packing for shader code
• Implements gradient creation, color stop management, and binary packing for GPU use
• Supports up to 8 color stops per gradient

patches/iced_graphics/src/gradient.rs


8. patches/iced_graphics/src/compositor.rs ✨ Enhancement +216/-0

Add iced_graphics compositor window management

• Added compositor trait for managing renderer initialization and window surfaces
• Defines surface error types and graphics information reporting
• Provides font loading and screenshot capabilities

patches/iced_graphics/src/compositor.rs


9. patches/iced_graphics/src/geometry/text.rs ✨ Enhancement +200/-0

Add iced_graphics canvas text drawing support

• Added text drawing for canvas with glyph outline and raster support
• Implements text positioning with alignment (horizontal/vertical)
• Integrates with cosmic_text for glyph rendering and swash caching

patches/iced_graphics/src/geometry/text.rs


10. patches/iced_graphics/src/cache.rs ✨ Enhancement +190/-0

Add iced_graphics generic caching infrastructure

• Added generic cache implementation with state tracking and group management
• Implements Cached trait for cacheable types
• Supports cache groups for batching and optimization hints

patches/iced_graphics/src/cache.rs


11. patches/iced_graphics/src/layer.rs ✨ Enhancement +144/-0

Add iced_graphics layer stacking system

• Added layer abstraction for stacking graphical primitives
• Implements Stack for managing multiple layers with transformation and clipping
• Supports layer flushing and bounds management

patches/iced_graphics/src/layer.rs


12. patches/iced_graphics/src/mesh.rs ✨ Enhancement +148/-0

Add iced_graphics triangle mesh rendering

• Added mesh primitive for rendering triangles with solid colors or gradients
• Defines vertex types (SolidVertex2D, GradientVertex2D) and indexed buffer structure
• Provides attribute counting utilities for mesh batching

patches/iced_graphics/src/mesh.rs


13. patches/iced_graphics/src/text/cache.rs ✨ Enhancement +143/-0

Add iced_graphics text caching system

• Added text caching system with key hashing and alias management
• Implements LRU-style trimming to remove unused cached text entries
• Supports multiple cache keys mapping to same buffer

patches/iced_graphics/src/text/cache.rs


14. patches/iced_graphics/src/image.rs ✨ Enhancement +136/-0

Add iced_graphics image loading with EXIF support

• Added image loading with EXIF orientation support
• Handles both raster and vector (SVG) images with rotation
• Implements JPEG orientation transformations (flip, rotate)

patches/iced_graphics/src/image.rs


15. patches/iced_graphics/src/geometry/cache.rs ✨ Enhancement +116/-0

Add iced_graphics geometry caching system

• Added geometry caching to avoid recomputation of drawn shapes
• Implements bounds-aware caching with previous geometry reuse
• Integrates with Cached trait for renderer-specific cache formats

patches/iced_graphics/src/geometry/cache.rs


16. patches/iced_graphics/src/geometry/stroke.rs ✨ Enhancement +98/-0

Add iced_graphics stroke styling options

• Added stroke styling with line cap, line join, and dash pattern support
• Defines LineCap (Butt, Square, Round) and LineJoin (Miter, Round, Bevel) enums
• Provides builder methods for stroke configuration

patches/iced_graphics/src/geometry/stroke.rs


17. patches/iced_graphics/src/geometry/path.rs ✨ Enhancement +80/-0

Add iced_graphics path abstraction layer

• Added path abstraction wrapping lyon_path for 2D shape construction
• Provides convenience methods for common shapes (line, rectangle, circle, rounded rectangle)
• Supports path transformation via lyon transforms

patches/iced_graphics/src/geometry/path.rs


18. patches/iced_graphics/src/damage.rs 🐞 Bug fix +78/-0

Fix NaN handling in damage region sorting

• Adds new damage module with functions to compute damage regions between frames
• Implements group() function that sorts damage rectangles using total_cmp() instead of
 partial_cmp().unwrap_or(Equal) to ensure total ordering compliance with Rust 1.81+
• Provides diff() and list() helper functions for computing damage regions

patches/iced_graphics/src/damage.rs


19. patches/iced_graphics/src/geometry/fill.rs ✨ Enhancement +75/-0

Add geometry fill style and rule types

• Adds new Fill struct with style and rule fields for geometry fill configuration
• Implements Default, From<Color>, From<Gradient>, and From<gradient::Linear> trait
 implementations
• Defines Rule enum with NonZero and EvenOdd variants for SVG fill rule support

patches/iced_graphics/src/geometry/fill.rs


20. patches/iced_graphics/src/viewport.rs ✨ Enhancement +56/-0

Add viewport abstraction for graphics rendering

• Adds new Viewport struct to represent a viewing region for graphics rendering
• Implements accessor methods for physical size, logical size, scale factor, and projection
 transformation
• Provides with_physical_size() constructor for creating viewports with physical dimensions

patches/iced_graphics/src/viewport.rs


21. patches/iced_graphics/src/geometry/path/arc.rs ✨ Enhancement +42/-0

Add arc and elliptical arc geometry types

• Adds Arc struct for circular arc segments with center, radius, and angle properties
• Adds Elliptical struct for elliptical arc segments with extended properties
• Implements From<Arc> conversion to Elliptical for circular-to-elliptical arc conversion

patches/iced_graphics/src/geometry/path/arc.rs


22. patches/iced_graphics/src/lib.rs ✨ Enhancement +42/-0

Add iced_graphics library root module

• Establishes main library module for iced_graphics with documentation and module declarations
• Exports public types including Viewport, Antialiasing, Cache, Compositor, Error,
 Gradient, Image, Layer, Mesh, Settings, and Text
• Re-exports iced_core and iced_futures for downstream use

patches/iced_graphics/src/lib.rs


23. patches/iced_graphics/src/error.rs ✨ Enhancement +42/-0

Add graphics error types and handling

• Defines Error enum for graphics context creation failures with variants for version, pixel
 format, adapter, and backend errors
• Defines Reason enum for graphics adapter not found scenarios
• Uses thiserror crate for error display implementations

patches/iced_graphics/src/error.rs


24. patches/iced_graphics/src/geometry.rs ✨ Enhancement +48/-0

Add geometry rendering trait and module structure

• Establishes geometry module with submodules for fill, frame, path, and stroke
• Defines Renderer trait for drawing geometry with frame creation and drawing methods
• Provides debug implementation for unit type renderer

patches/iced_graphics/src/geometry.rs


25. patches/iced_graphics/src/color.rs ✨ Enhancement +46/-0

Add color packing utilities with gamma correction

• Adds Packed struct for RGBA color representation as 4 floats
• Implements pack() function with conditional gamma correction based on feature flags
• Supports both linear gamma correction and web-colors modes

patches/iced_graphics/src/color.rs


26. patches/iced_graphics/src/image/storage.rs ✨ Enhancement +31/-0

Add image storage abstraction traits

• Defines Storage trait for managing cached image data with upload and removal operations
• Defines Entry trait for storage entries with size information
• Provides abstraction for image storage backends

patches/iced_graphics/src/image/storage.rs


27. patches/iced_graphics/src/antialiasing.rs ✨ Enhancement +24/-0

Add antialiasing strategy enumeration

• Adds Antialiasing enum with MSAA variants (2x, 4x, 8x, 16x samples)
• Implements sample_count() method to retrieve sample count for each antialiasing strategy

patches/iced_graphics/src/antialiasing.rs


28. patches/iced_graphics/src/settings.rs ✨ Enhancement +29/-0

Add renderer settings configuration

• Defines Settings struct for renderer configuration with default font, text size, and
 antialiasing options
• Implements Default trait with sensible defaults (16.0px text size, no antialiasing)

patches/iced_graphics/src/settings.rs


29. patches/iced_graphics/src/geometry/style.rs ✨ Enhancement +24/-0

Add geometry style enumeration

• Adds Style enum for drawing coloring with Solid and Gradient variants
• Implements From<Color> and From<Gradient> trait conversions

patches/iced_graphics/src/geometry/style.rs


30. patches/iced_graphics/Cargo.toml ⚙️ Configuration changes +133/-0

Add iced_graphics crate manifest and dependencies

• Adds complete Cargo manifest for iced_graphics 0.13.0 with all dependencies and features
• Configures features for geometry, image, svg, web-colors, and fira-sans support
• Defines strict linting rules for clippy, rust, and rustdoc

patches/iced_graphics/Cargo.toml


31. patches/iced_graphics/Cargo.toml.orig ⚙️ Configuration changes +49/-0

Add iced_graphics original manifest template

• Adds original Cargo manifest template for iced_graphics using workspace inheritance
• Defines optional features and workspace-managed dependencies

patches/iced_graphics/Cargo.toml.orig


32. Cargo.toml Dependencies +3/-0

Add local iced_graphics patch override

• Adds [patch.crates-io] section to override iced_graphics with local patched version from
 patches/iced_graphics
• Enables local patch to fix Rust 1.81+ sort ordering compliance issues in upstream iced library

Cargo.toml


Grey Divider

Qodo Logo

@qodo-code-review
Copy link

qodo-code-review bot commented Feb 23, 2026

Code Review by Qodo

🐞 Bugs (1) 📘 Rule violations (1) 📎 Requirement gaps (0)

Grey Divider


Action required

1. Paragraph logs full text 📘 Rule violation ⛨ Security
Description
Paragraph::with_text logs the entire paragraph content at trace level, which can leak sensitive
user-provided data into logs. This violates the requirement to avoid sensitive data in logs and to
keep logs suitable for auditing.
Code

patches/iced_graphics/src/text/paragraph.rs[R64-65]

+        log::trace!("Allocating plain paragraph: {}", text.content);
+
Evidence
The secure logging rule forbids sensitive data in logs; the added trace log includes text.content
(user-provided text) verbatim.

Rule 5: Generic: Secure Logging Practices
patches/iced_graphics/src/text/paragraph.rs[64-65]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
A newly-added `log::trace!` statement logs full paragraph contents (`text.content`), which can leak sensitive user data to logs.

## Issue Context
This code is vendored under `patches/iced_graphics/` and will run in-process as part of the patched `iced_graphics` crate.

## Fix Focus Areas
- patches/iced_graphics/src/text/paragraph.rs[64-65]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

2. Unpinned patched dependency 🐞 Bug ⛯ Reliability
Description
The workspace globally patches iced_graphics to a local crate versioned 0.13.0, while Cargo.lock
is ignored and iced is allowed to float within 0.13.x, which can make builds non-reproducible and
potentially incompatible if upstream patch releases adjust the iced_* version matrix.
Code

Cargo.toml[R33-35]

+[patch.crates-io]
+iced_graphics = { path = "patches/iced_graphics" }
+
Evidence
The PR introduces a crates-io patch to force iced_graphics to a local path. However, the repo
explicitly ignores Cargo.lock, and the GUI crate depends on iced = "0.13" (a floating
patch-range), while the patched crate declares version = "0.13.0". Together, this increases the
chance of CI/user builds resolving different upstream iced patch versions than the vendored
iced_graphics was taken from, reducing reproducibility and raising compatibility risk.

Cargo.toml[33-35]
.gitignore[1-7]
crates/x-adox-gui/Cargo.toml[10-12]
patches/iced_graphics/Cargo.toml[12-16]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The repo patches `iced_graphics` to a vendored path crate (versioned `0.13.0`), but it also ignores `Cargo.lock` and uses `iced = &quot;0.13&quot;` (floating within `0.13.x`). This combination can lead to non-reproducible builds and increases the risk that a future upstream `iced` patch release expects a different `iced_graphics` version than the vendored one.

## Issue Context
- The `[patch.crates-io]` override applies workspace-wide.
- `.gitignore` excludes `Cargo.lock`, so dependency resolution can vary between environments and over time.
- The vendored `iced_graphics` crate is explicitly versioned `0.13.0`.

## Fix Focus Areas
- Cargo.toml[33-35]
- crates/x-adox-gui/Cargo.toml[10-12]
- patches/iced_graphics/Cargo.toml[12-16]
- .gitignore[1-7]

## Suggested fix approach
Choose one:
1. **Preferred for apps**: Stop ignoring and commit `Cargo.lock` (remove `Cargo.lock` from `.gitignore`) so CI/users build with the same resolved `iced` patch version.
2. **If lockfiles must stay ignored**: Pin the `iced` dependency to the exact patch version you vendored against (e.g., `version = &quot;=0.13.0&quot;` or `&quot;0.13.0&quot;`), and ensure the vendored `iced_graphics`/`iced_core`/`iced_futures` versions align with that exact `iced` release.

Add a short comment near `[patch.crates-io]` indicating which `iced` version this patch is intended to match and when it can be removed (on upgrade to iced 0.14+).

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

ⓘ The new review experience is currently in Beta. Learn more

Grey Divider

Qodo Logo

Backport of iced-rs/iced#2651 (merged into iced 0.14).

Since Rust 1.81, sort_by() panics when the comparator violates total
ordering. iced_graphics 0.13's damage::group() uses partial_cmp() on
f32 distances with unwrap_or(Equal), which breaks transitivity when
NaN values appear. This crashes the app on the tiny_skia fallback
renderer path (GL backend / Wayland dmabuf failures).

Fix: replace partial_cmp().unwrap_or(Equal) with total_cmp() in
patches/iced_graphics/src/damage.rs (line 53-55). This is the exact
same fix as upstream PR #2651.

The patched crate is vendored under patches/iced_graphics/ and
referenced via [patch.crates-io] in the workspace Cargo.toml.
Remove this patch when upgrading to iced 0.14+.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@mmaechtel mmaechtel force-pushed the fix/rust-1.81-sort-compat branch from cc75db5 to fb29698 Compare February 23, 2026 12:03
@StarTuz StarTuz merged commit 68ff76c into StarTuz:main Feb 23, 2026
StarTuz added a commit that referenced this pull request Feb 23, 2026
Includes PR #2 from @mmaechtel: sorter.rs total-order fix and
iced_graphics 0.13 total_cmp() backport from iced 0.14.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@StarTuz
Copy link
Owner

StarTuz commented Feb 23, 2026

Summary

Rust 1.81+ enforces strict total ordering checks in sort_by() comparators, causing runtime panics in two locations:

  • sorter.rs — The SimHeaven tiebreaker violated transitivity: comparing a SimHeaven pack to a non-SimHeaven pack at the same score tier returned Equal, but two SimHeaven packs with different layers returned Less/Greater. Fixed by adding else-branches for the mixed case (+4 lines).
  • iced_graphics::damage::group() — Uses partial_cmp().unwrap_or(Equal) on f32 distances, which breaks transitivity when NaN values appear. This is a known upstream issue (iced-rs/iced#2650), fixed in iced 0.14 via PR #2651. Backported here as a local [patch.crates-io] vendor under patches/iced_graphics/ — the only change is partial_cmp(...).unwrap_or(Equal)total_cmp(...) in damage.rs. Remove this patch when upgrading to iced 0.14+.

Test plan

  • All 167 cargo test tests pass
  • GUI starts and completes full scenery scan (1480 packs) without panic
  • Verified on Rust 1.92, NVIDIA RTX 4090, Wayland (GL fallback path)

🤖 Generated with Claude Code

Thank you for this! Really appreciate the assistance.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants