1
0
mirror of https://github.com/emilk/egui.git synced 2026-09-02 06:40:06 -04:00

Enable clippy::iter_over_hash_type lint (#7421)

This helped discover a few things that _might_ have been buggy.
This commit is contained in:
Emil Ernerfeldt
2025-08-06 13:55:53 +02:00
committed by GitHub
parent d42ea3800f
commit 36a4981f29
22 changed files with 114 additions and 60 deletions

View File

@@ -2149,6 +2149,7 @@ impl Context {
self.write(|ctx| {
if ctx.memory.options.zoom_factor != zoom_factor {
ctx.new_zoom_factor = Some(zoom_factor);
#[expect(clippy::iter_over_hash_type)]
for viewport_id in ctx.all_viewport_ids() {
ctx.request_repaint(viewport_id, cause.clone());
}
@@ -2275,6 +2276,8 @@ impl Context {
/// Called at the end of the pass.
#[cfg(debug_assertions)]
fn debug_painting(&self) {
#![expect(clippy::iter_over_hash_type)] // ok to be sloppy in debug painting
let paint_widget = |widget: &WidgetRect, text: &str, color: Color32| {
let rect = widget.interact_rect;
if rect.is_positive() {

View File

@@ -3,7 +3,7 @@
use epaint::ColorImage;
use crate::{
Key, Theme, ViewportId, ViewportIdMap,
Key, OrderedViewportIdMap, Theme, ViewportId, ViewportIdMap,
emath::{Pos2, Rect, Vec2},
};
@@ -1132,7 +1132,11 @@ impl RawInput {
} = self;
ui.label(format!("Active viewport: {viewport_id:?}"));
for (id, viewport) in viewports {
let ordered_viewports = viewports
.iter()
.map(|(id, value)| (*id, value))
.collect::<OrderedViewportIdMap<_>>();
for (id, viewport) in ordered_viewports {
ui.group(|ui| {
ui.label(format!("Viewport {id:?}"));
ui.push_id(id, |ui| {

View File

@@ -1,6 +1,6 @@
//! All the data egui returns to the backend at the end of each frame.
use crate::{RepaintCause, ViewportIdMap, ViewportOutput, WidgetType};
use crate::{OrderedViewportIdMap, RepaintCause, ViewportOutput, WidgetType};
/// What egui emits each frame from [`crate::Context::run`].
///
@@ -32,12 +32,14 @@ pub struct FullOutput {
///
/// It is up to the integration to spawn a native window for each viewport,
/// and to close any window that no longer has a viewport in this map.
pub viewport_output: ViewportIdMap<ViewportOutput>,
pub viewport_output: OrderedViewportIdMap<ViewportOutput>,
}
impl FullOutput {
/// Add on new output.
pub fn append(&mut self, newer: Self) {
use std::collections::btree_map::Entry;
let Self {
platform_output,
textures_delta,
@@ -53,10 +55,10 @@ impl FullOutput {
for (id, new_viewport) in viewport_output {
match self.viewport_output.entry(id) {
std::collections::hash_map::Entry::Vacant(entry) => {
Entry::Vacant(entry) => {
entry.insert(new_viewport);
}
std::collections::hash_map::Entry::Occupied(mut entry) => {
Entry::Occupied(mut entry) => {
entry.get_mut().append(new_viewport);
}
}

View File

@@ -240,8 +240,7 @@ impl GraphicLayers {
if let Some(list) = order_map.get_mut(&layer_id.id) {
if let Some(to_global) = to_global.get(layer_id) {
for clipped_shape in &mut list.0 {
clipped_shape.clip_rect = *to_global * clipped_shape.clip_rect;
clipped_shape.shape.transform(*to_global);
clipped_shape.transform(*to_global);
}
}
all_shapes.append(&mut list.0);
@@ -250,13 +249,15 @@ impl GraphicLayers {
}
// Also draw areas that are missing in `area_order`:
// NOTE: We don't think we end up here in normal situations.
// This is just a safety net in case we have some bug somewhere.
#[expect(clippy::iter_over_hash_type)]
for (id, list) in order_map {
let layer_id = LayerId::new(order, *id);
if let Some(to_global) = to_global.get(&layer_id) {
for clipped_shape in &mut list.0 {
clipped_shape.clip_rect = *to_global * clipped_shape.clip_rect;
clipped_shape.shape.transform(*to_global);
clipped_shape.transform(*to_global);
}
}

View File

@@ -711,6 +711,8 @@ impl Focus {
let mut best_score = f32::INFINITY;
let mut best_id = None;
// iteration order should only matter in case of a tie, and that should be very rare
#[expect(clippy::iter_over_hash_type)]
for (candidate_id, candidate_rect) in &self.focus_widgets_cache {
if *candidate_id == current_focused.id {
continue;
@@ -959,6 +961,7 @@ impl Memory {
/// Forget window positions, sizes etc.
/// Can be used to auto-layout windows.
pub fn reset_areas(&mut self) {
#[expect(clippy::iter_over_hash_type)]
for area in self.areas.values_mut() {
*area = Default::default();
}
@@ -1324,12 +1327,14 @@ impl Areas {
wants_to_be_on_top.clear();
// For all layers with sublayers, put the sublayers directly after the parent layer:
let sublayers = std::mem::take(sublayers);
for (parent, children) in sublayers {
let mut moved_layers = vec![parent];
// (it doesn't matter in which order we replace parents with their children)
#[expect(clippy::iter_over_hash_type)]
for (parent, children) in std::mem::take(sublayers) {
let mut moved_layers = vec![parent]; // parent first…
order.retain(|l| {
if children.contains(l) {
moved_layers.push(*l);
moved_layers.push(*l); // …followed by children
false
} else {
true
@@ -1338,7 +1343,7 @@ impl Areas {
let Some(parent_pos) = order.iter().position(|l| l == &parent) else {
continue;
};
order.splice(parent_pos..=parent_pos, moved_layers);
order.splice(parent_pos..=parent_pos, moved_layers); // replace the parent with itself and its children
}
self.order_map = self

View File

@@ -574,6 +574,8 @@ struct PersistedMap(Vec<(u64, SerializedElement)>);
#[cfg(feature = "persistence")]
impl PersistedMap {
fn from_map(map: &IdTypeMap) -> Self {
#![expect(clippy::iter_over_hash_type)] // the serialized order doesn't matter
profiling::function_scope!();
use std::collections::BTreeMap;

View File

@@ -113,6 +113,20 @@ pub enum ViewportClass {
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
pub struct ViewportId(pub Id);
// We implement `PartialOrd` and `Ord` so we can use `ViewportId` in a `BTreeMap`,
// which allows predicatable iteration order, frame-to-frame.
impl PartialOrd for ViewportId {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
Some(self.cmp(other))
}
}
impl Ord for ViewportId {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
self.0.value().cmp(&other.0.value())
}
}
impl Default for ViewportId {
#[inline]
fn default() -> Self {
@@ -151,6 +165,9 @@ pub type ViewportIdSet = nohash_hasher::IntSet<ViewportId>;
/// A fast hash map from [`ViewportId`] to `T`.
pub type ViewportIdMap<T> = nohash_hasher::IntMap<ViewportId, T>;
/// An order map from [`ViewportId`] to `T`.
pub type OrderedViewportIdMap<T> = std::collections::BTreeMap<ViewportId, T>;
// ----------------------------------------------------------------------------
/// Image data for an application icon.

View File

@@ -129,6 +129,7 @@ impl WidgetRects {
infos,
} = self;
#[expect(clippy::iter_over_hash_type)]
for rects in by_layer.values_mut() {
rects.clear();
}