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:
@@ -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() {
|
||||
|
||||
@@ -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| {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -129,6 +129,7 @@ impl WidgetRects {
|
||||
infos,
|
||||
} = self;
|
||||
|
||||
#[expect(clippy::iter_over_hash_type)]
|
||||
for rects in by_layer.values_mut() {
|
||||
rects.clear();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user