1
0
mirror of https://github.com/emilk/egui.git synced 2026-06-26 14:49:06 -04:00

Enable a few more clippy lints (#8064)

Enable these new clippy lints and fix all warnings:

* `format_push_string` — use `write!` instead of `s += &format!(…)` to
avoid extra allocations
* `ignored_unit_patterns` — use `()` instead of `_` when matching unit
* `missing_fields_in_debug` — ensure manual `Debug` impls account for
all fields
* `needless_raw_string_hashes` — remove unnecessary `r#` on string
literals
* `ref_option` — prefer `Option<&T>` over `&Option<T>` in function
signatures
This commit is contained in:
Emil Ernerfeldt
2026-04-04 16:20:29 +02:00
committed by GitHub
parent 8ada641ee2
commit 4a09782fce
17 changed files with 100 additions and 53 deletions

View File

@@ -218,10 +218,12 @@ flat_map_option = "warn"
float_cmp_const = "warn" float_cmp_const = "warn"
fn_params_excessive_bools = "warn" fn_params_excessive_bools = "warn"
fn_to_numeric_cast_any = "warn" fn_to_numeric_cast_any = "warn"
format_push_string = "warn"
from_iter_instead_of_collect = "warn" from_iter_instead_of_collect = "warn"
get_unwrap = "warn" get_unwrap = "warn"
if_let_mutex = "warn" if_let_mutex = "warn"
ignore_without_reason = "warn" ignore_without_reason = "warn"
ignored_unit_patterns = "warn"
implicit_clone = "warn" implicit_clone = "warn"
implied_bounds_in_impls = "warn" implied_bounds_in_impls = "warn"
imprecise_flops = "warn" imprecise_flops = "warn"
@@ -270,6 +272,7 @@ mismatching_type_param_order = "warn"
missing_assert_message = "warn" missing_assert_message = "warn"
missing_enforced_import_renames = "warn" missing_enforced_import_renames = "warn"
missing_errors_doc = "warn" missing_errors_doc = "warn"
missing_fields_in_debug = "warn"
missing_safety_doc = "warn" missing_safety_doc = "warn"
mixed_attributes_style = "warn" mixed_attributes_style = "warn"
mut_mut = "warn" mut_mut = "warn"
@@ -279,6 +282,7 @@ needless_continue = "warn"
needless_for_each = "warn" needless_for_each = "warn"
needless_pass_by_ref_mut = "warn" needless_pass_by_ref_mut = "warn"
needless_pass_by_value = "warn" needless_pass_by_value = "warn"
needless_raw_string_hashes = "warn"
negative_feature_names = "warn" negative_feature_names = "warn"
non_std_lazy_statics = "warn" non_std_lazy_statics = "warn"
non_zero_suggestions = "warn" non_zero_suggestions = "warn"
@@ -299,6 +303,7 @@ rc_mutex = "warn"
readonly_write_lock = "warn" readonly_write_lock = "warn"
redundant_type_annotations = "warn" redundant_type_annotations = "warn"
ref_as_ptr = "warn" ref_as_ptr = "warn"
ref_option = "warn"
ref_option_ref = "warn" ref_option_ref = "warn"
ref_patterns = "warn" ref_patterns = "warn"
rest_pat_in_fully_bound_structs = "warn" rest_pat_in_fully_bound_structs = "warn"

View File

@@ -207,7 +207,7 @@ fn save_to_disk(file_path: &PathBuf, kv: &HashMap<String, String>) {
profiling::scope!("ron::serialize"); profiling::scope!("ron::serialize");
if let Err(err) = ron::Options::default() if let Err(err) = ron::Options::default()
.to_io_writer_pretty(&mut writer, &kv, config) .to_io_writer_pretty(&mut writer, &kv, config)
.and_then(|_| writer.flush().map_err(|err| err.into())) .and_then(|()| writer.flush().map_err(|err| err.into()))
{ {
log::warn!("Failed to serialize app state: {err}"); log::warn!("Failed to serialize app state: {err}");
} else { } else {

View File

@@ -427,37 +427,52 @@ pub fn adapter_info_summary(info: &wgpu::AdapterInfo) -> String {
// > name: "Apple M1 Pro", device_type: IntegratedGpu, backend: Metal, driver: "", driver_info: "" // > name: "Apple M1 Pro", device_type: IntegratedGpu, backend: Metal, driver: "", driver_info: ""
// > name: "ANGLE (Apple, Apple M1 Pro, OpenGL 4.1)", device_type: IntegratedGpu, backend: Gl, driver: "", driver_info: "" // > name: "ANGLE (Apple, Apple M1 Pro, OpenGL 4.1)", device_type: IntegratedGpu, backend: Gl, driver: "", driver_info: ""
use std::fmt::Write as _;
let mut summary = format!("backend: {backend:?}, device_type: {device_type:?}"); let mut summary = format!("backend: {backend:?}, device_type: {device_type:?}");
if !name.is_empty() { if !name.is_empty() {
summary += &format!(", name: {name:?}"); write!(summary, ", name: {name:?}").ok();
} }
if !driver.is_empty() { if !driver.is_empty() {
summary += &format!(", driver: {driver:?}"); write!(summary, ", driver: {driver:?}").ok();
} }
if !driver_info.is_empty() { if !driver_info.is_empty() {
summary += &format!(", driver_info: {driver_info:?}"); write!(summary, ", driver_info: {driver_info:?}").ok();
} }
if *vendor != 0 { if *vendor != 0 {
#[cfg(not(target_arch = "wasm32"))] #[cfg(not(target_arch = "wasm32"))]
{ {
summary += &format!(", vendor: {} (0x{vendor:04X})", parse_vendor_id(*vendor)); write!(
summary,
", vendor: {} (0x{vendor:04X})",
parse_vendor_id(*vendor)
)
.ok();
} }
#[cfg(target_arch = "wasm32")] #[cfg(target_arch = "wasm32")]
{ {
summary += &format!(", vendor: 0x{vendor:04X}"); write!(summary, ", vendor: 0x{vendor:04X}").ok();
} }
} }
if *device != 0 { if *device != 0 {
summary += &format!(", device: 0x{device:02X}"); write!(summary, ", device: 0x{device:02X}").ok();
} }
if !device_pci_bus_id.is_empty() { if !device_pci_bus_id.is_empty() {
summary += &format!(", pci_bus_id: {device_pci_bus_id:?}"); write!(summary, ", pci_bus_id: {device_pci_bus_id:?}").ok();
} }
if *subgroup_min_size != 0 || *subgroup_max_size != 0 { if *subgroup_min_size != 0 || *subgroup_max_size != 0 {
summary += &format!(", subgroup_size: {subgroup_min_size}..={subgroup_max_size}"); write!(
summary,
", subgroup_size: {subgroup_min_size}..={subgroup_max_size}"
)
.ok();
} }
summary += &format!(", transient_saves_memory: {transient_saves_memory}"); write!(
summary,
", transient_saves_memory: {transient_saves_memory}"
)
.ok();
summary summary
} }

View File

@@ -296,15 +296,22 @@ impl Clone for WgpuSetupCreateNew {
impl std::fmt::Debug for WgpuSetupCreateNew { impl std::fmt::Debug for WgpuSetupCreateNew {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let Self {
instance_descriptor,
display_handle,
power_preference,
native_adapter_selector,
device_descriptor: _,
} = self;
f.debug_struct("WgpuSetupCreateNew") f.debug_struct("WgpuSetupCreateNew")
.field("instance_descriptor", &self.instance_descriptor) .field("instance_descriptor", instance_descriptor)
.field("display_handle", &self.display_handle) .field("display_handle", display_handle)
.field("power_preference", &self.power_preference) .field("power_preference", power_preference)
.field( .field(
"native_adapter_selector", "native_adapter_selector",
&self.native_adapter_selector.is_some(), &native_adapter_selector.is_some(),
) )
.finish() .finish_non_exhaustive()
} }
} }

View File

@@ -1,3 +1,5 @@
use std::fmt::Write as _;
#[derive(Clone)] #[derive(Clone)]
struct Frame { struct Frame {
/// `_main` is usually as the deepest depth. /// `_main` is usually as the deepest depth.
@@ -23,7 +25,7 @@ pub fn capture() -> String {
if let Some(file_and_line) = &mut file_and_line if let Some(file_and_line) = &mut file_and_line
&& let Some(line_nr) = symbol.lineno() && let Some(line_nr) = symbol.lineno()
{ {
file_and_line.push_str(&format!(":{line_nr}")); write!(file_and_line, ":{line_nr}").ok();
} }
let file_and_line = file_and_line.unwrap_or_default(); let file_and_line = file_and_line.unwrap_or_default();
@@ -130,12 +132,14 @@ pub fn capture() -> String {
if frame.depth + 1 < last_depth || last_depth + 1 < frame.depth { if frame.depth + 1 < last_depth || last_depth + 1 < frame.depth {
// Show that some frames were elided // Show that some frames were elided
formatted.push_str(&format!("{:widest_depth$}\n", "")); writeln!(formatted, "{:widest_depth$} …", "").ok();
} }
formatted.push_str(&format!( writeln!(
"{depth:widest_depth$}: {file_and_line:widest_file_line$} {name}\n" formatted,
)); "{depth:widest_depth$}: {file_and_line:widest_file_line$} {name}"
)
.ok();
last_depth = frame.depth; last_depth = frame.depth;
} }

View File

@@ -673,7 +673,7 @@ impl Window<'_> {
title_bar.ui( title_bar.ui(
&mut area_content_ui, &mut area_content_ui,
&content_response, content_response.as_ref(),
open.as_deref_mut(), open.as_deref_mut(),
&mut collapsing, &mut collapsing,
collapsible, collapsible,
@@ -1256,7 +1256,7 @@ impl TitleBar {
fn ui( fn ui(
self, self,
ui: &mut Ui, ui: &mut Ui,
content_response: &Option<Response>, content_response: Option<&Response>,
open: Option<&mut bool>, open: Option<&mut bool>,
collapsing: &mut CollapsingState, collapsing: &mut CollapsingState,
collapsible: bool, collapsible: bool,
@@ -1300,7 +1300,7 @@ impl TitleBar {
ui.visuals().text_color(), ui.visuals().text_color(),
); );
if let Some(content_response) = &content_response { if let Some(content_response) = content_response {
// Paint separator between title and content: // Paint separator between title and content:
let content_rect = content_response.rect; let content_rect = content_response.rect;
if false { if false {

View File

@@ -2428,6 +2428,7 @@ impl Context {
#[cfg(debug_assertions)] #[cfg(debug_assertions)]
fn debug_painting(&self) { fn debug_painting(&self) {
#![expect(clippy::iter_over_hash_type)] // ok to be sloppy in debug painting #![expect(clippy::iter_over_hash_type)] // ok to be sloppy in debug painting
use std::fmt::Write as _;
let paint_widget = |widget: &WidgetRect, text: &str, color: Color32| { let paint_widget = |widget: &WidgetRect, text: &str, color: Color32| {
let rect = widget.interact_rect; let rect = widget.interact_rect;
@@ -2500,13 +2501,17 @@ impl Context {
for id in contains_pointer { for id in contains_pointer {
let mut widget_text = format!("{id:?}"); let mut widget_text = format!("{id:?}");
if let Some(rect) = widget_rects.get(id) { if let Some(rect) = widget_rects.get(id) {
widget_text += write!(
&format!(" {:?} {:?} {:?}", rect.layer_id, rect.rect, rect.sense); widget_text,
" {:?} {:?} {:?}",
rect.layer_id, rect.rect, rect.sense
)
.ok();
} }
if let Some(info) = widget_rects.info(id) { if let Some(info) = widget_rects.info(id) {
widget_text += &format!(" {info:?}"); write!(widget_text, " {info:?}").ok();
} }
debug_text += &format!("{widget_text}\n"); writeln!(debug_text, "{widget_text}").ok();
} }
self.debug_text(debug_text); self.debug_text(debug_text);
} }
@@ -2571,7 +2576,7 @@ impl Context {
); );
self.viewport(|vp| { self.viewport(|vp| {
for reason in &vp.output.request_discard_reasons { for reason in &vp.output.request_discard_reasons {
warning += &format!("\n {reason}"); write!(warning, "\n {reason}").ok();
} }
}); });

View File

@@ -376,12 +376,14 @@ impl ViewportInfo {
ui.label(opt_as_str(&visible)); ui.label(opt_as_str(&visible));
ui.end_row(); ui.end_row();
#[expect(clippy::ref_option)]
fn opt_rect_as_string(v: &Option<Rect>) -> String { fn opt_rect_as_string(v: &Option<Rect>) -> String {
v.as_ref().map_or(String::new(), |r| { v.as_ref().map_or(String::new(), |r| {
format!("Pos: {:?}, size: {:?}", r.min, r.size()) format!("Pos: {:?}, size: {:?}", r.min, r.size())
}) })
} }
#[expect(clippy::ref_option)]
fn opt_as_str<T: std::fmt::Debug>(v: &Option<T>) -> String { fn opt_as_str<T: std::fmt::Debug>(v: &Option<T>) -> String {
v.as_ref().map_or(String::new(), |v| format!("{v:?}")) v.as_ref().map_or(String::new(), |v| format!("{v:?}"))
} }

View File

@@ -49,10 +49,15 @@ fn pos_in_galley(galley: &Galley, ccursor: CCursor) -> Pos2 {
impl std::fmt::Debug for WidgetTextCursor { impl std::fmt::Debug for WidgetTextCursor {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let Self {
widget_id,
ccursor,
pos: _,
} = self;
f.debug_struct("WidgetTextCursor") f.debug_struct("WidgetTextCursor")
.field("widget_id", &self.widget_id.short_debug_format()) .field("widget_id", &widget_id.short_debug_format())
.field("ccursor", &self.ccursor.index) .field("ccursor", &ccursor.index)
.finish() .finish_non_exhaustive()
} }
} }

View File

@@ -551,7 +551,7 @@ impl Widget for DragValue<'_> {
if let Some(value_text) = value_text { if let Some(value_text) = value_text {
// We were editing the value as text last frame, but lost focus. // We were editing the value as text last frame, but lost focus.
// Make sure we applied the last text value: // Make sure we applied the last text value:
let parsed_value = parse(&custom_parser, &value_text); let parsed_value = parse(custom_parser.as_ref(), &value_text);
if let Some(mut parsed_value) = parsed_value { if let Some(mut parsed_value) = parsed_value {
// User edits always clamps: // User edits always clamps:
parsed_value = clamp_value_to_range(parsed_value, range.clone()); parsed_value = clamp_value_to_range(parsed_value, range.clone());
@@ -591,7 +591,7 @@ impl Widget for DragValue<'_> {
response.lost_focus() && !ui.input(|i| i.key_pressed(Key::Escape)) response.lost_focus() && !ui.input(|i| i.key_pressed(Key::Escape))
}; };
if update { if update {
let parsed_value = parse(&custom_parser, &value_text); let parsed_value = parse(custom_parser.as_ref(), &value_text);
if let Some(mut parsed_value) = parsed_value { if let Some(mut parsed_value) = parsed_value {
// User edits always clamps: // User edits always clamps:
parsed_value = clamp_value_to_range(parsed_value, range.clone()); parsed_value = clamp_value_to_range(parsed_value, range.clone());
@@ -733,8 +733,8 @@ impl Widget for DragValue<'_> {
} }
} }
fn parse(custom_parser: &Option<NumParser<'_>>, value_text: &str) -> Option<f64> { fn parse(custom_parser: Option<&NumParser<'_>>, value_text: &str) -> Option<f64> {
match &custom_parser { match custom_parser {
Some(parser) => parser(value_text), Some(parser) => parser(value_text),
None => default_parser(value_text), None => default_parser(value_text),
} }

View File

@@ -38,7 +38,8 @@ fn main() {
}); });
for loud_crate in ["naga", "wgpu_core", "wgpu_hal"] { for loud_crate in ["naga", "wgpu_core", "wgpu_hal"] {
if !rust_log.contains(&format!("{loud_crate}=")) { if !rust_log.contains(&format!("{loud_crate}=")) {
rust_log += &format!(",{loud_crate}=warn"); use std::fmt::Write as _;
write!(rust_log, ",{loud_crate}=warn").ok();
} }
} }

View File

@@ -519,7 +519,8 @@ impl WrapApp {
additional_info.push(format!("{} bytes", bytes.len())); additional_info.push(format!("{} bytes", bytes.len()));
} }
if !additional_info.is_empty() { if !additional_info.is_empty() {
info += &format!(" ({})", additional_info.join(", ")); use std::fmt::Write as _;
write!(info, " ({})", additional_info.join(", ")).ok();
} }
ui.label(info); ui.label(info);

View File

@@ -996,7 +996,7 @@ impl<'a> TableBody<'a> {
overline: false, overline: false,
response: &mut response, response: &mut response,
}); });
self.capture_hover_state(&response, self.row_index); self.capture_hover_state(response.as_ref(), self.row_index);
let bottom_y = self.layout.cursor.y; let bottom_y = self.layout.cursor.y;
if Some(self.row_index) == self.scroll_to_row { if Some(self.row_index) == self.scroll_to_row {
@@ -1078,7 +1078,7 @@ impl<'a> TableBody<'a> {
overline: false, overline: false,
response: &mut response, response: &mut response,
}); });
self.capture_hover_state(&response, row_index); self.capture_hover_state(response.as_ref(), row_index);
} }
if total_rows - max_row > 0 { if total_rows - max_row > 0 {
@@ -1160,7 +1160,7 @@ impl<'a> TableBody<'a> {
overline: false, overline: false,
response: &mut response, response: &mut response,
}); });
self.capture_hover_state(&response, row_index); self.capture_hover_state(response.as_ref(), row_index);
break; break;
} }
} }
@@ -1183,7 +1183,7 @@ impl<'a> TableBody<'a> {
selected: false, selected: false,
response: &mut response, response: &mut response,
}); });
self.capture_hover_state(&response, row_index); self.capture_hover_state(response.as_ref(), row_index);
cursor_y += (row_height + spacing.y) as f64; cursor_y += (row_height + spacing.y) as f64;
if Some(row_index) == self.scroll_to_row { if Some(row_index) == self.scroll_to_row {
@@ -1234,8 +1234,8 @@ impl<'a> TableBody<'a> {
// Capture the hover information for the just created row. This is used in the next render // Capture the hover information for the just created row. This is used in the next render
// to ensure that the entire row is highlighted. // to ensure that the entire row is highlighted.
fn capture_hover_state(&self, response: &Option<Response>, row_index: usize) { fn capture_hover_state(&self, response: Option<&Response>, row_index: usize) {
let is_row_hovered = response.as_ref().is_some_and(|r| r.hovered()); let is_row_hovered = response.is_some_and(|r| r.hovered());
if is_row_hovered { if is_row_hovered {
self.layout self.layout
.ui .ui

View File

@@ -563,7 +563,7 @@ pub fn image_snapshot_options(
options: &SnapshotOptions, options: &SnapshotOptions,
) { ) {
match try_image_snapshot_options(current, name, options) { match try_image_snapshot_options(current, name, options) {
Ok(_) => {} Ok(()) => {}
Err(err) => { Err(err) => {
panic!("{err}"); panic!("{err}");
} }
@@ -582,7 +582,7 @@ pub fn image_snapshot_options(
#[track_caller] #[track_caller]
pub fn image_snapshot(current: &image::RgbaImage, name: impl Into<String>) { pub fn image_snapshot(current: &image::RgbaImage, name: impl Into<String>) {
match try_image_snapshot(current, name) { match try_image_snapshot(current, name) {
Ok(_) => {} Ok(()) => {}
Err(err) => { Err(err) => {
panic!("{err}"); panic!("{err}");
} }
@@ -884,14 +884,14 @@ impl Drop for SnapshotResults {
#[expect(clippy::manual_assert)] #[expect(clippy::manual_assert)]
if count >= 2 { if count >= 2 {
panic!( panic!(
r#" "
Multiple SnapshotResults were dropped without being handled. Multiple SnapshotResults were dropped without being handled.
In order to allow consistent snapshot updates, all snapshot results within a test should be merged in a single SnapshotResults instance. In order to allow consistent snapshot updates, all snapshot results within a test should be merged in a single SnapshotResults instance.
Usually this is handled internally in a harness. If you have multiple harnesses, you can merge the results using `Harness::take_snapshot_results` and `SnapshotResults::extend`. Usually this is handled internally in a harness. If you have multiple harnesses, you can merge the results using `Harness::take_snapshot_results` and `SnapshotResults::extend`.
The SnapshotResult was constructed at {} The SnapshotResult was constructed at {}
"#, ",
self.location self.location
); );
} }

View File

@@ -106,7 +106,7 @@ impl RotatingTriangle {
let program = gl.create_program().expect("Cannot create program"); let program = gl.create_program().expect("Cannot create program");
let (vertex_shader_source, fragment_shader_source) = ( let (vertex_shader_source, fragment_shader_source) = (
r#" "
const vec2 verts[3] = vec2[3]( const vec2 verts[3] = vec2[3](
vec2(0.0, 1.0), vec2(0.0, 1.0),
vec2(-1.0, -1.0), vec2(-1.0, -1.0),
@@ -124,15 +124,15 @@ impl RotatingTriangle {
gl_Position = vec4(verts[gl_VertexID], 0.0, 1.0); gl_Position = vec4(verts[gl_VertexID], 0.0, 1.0);
gl_Position.x *= cos(u_angle); gl_Position.x *= cos(u_angle);
} }
"#, ",
r#" "
precision mediump float; precision mediump float;
in vec4 v_color; in vec4 v_color;
out vec4 out_color; out vec4 out_color;
void main() { void main() {
out_color = v_color; out_color = v_color;
} }
"#, ",
); );
let shader_sources = [ let shader_sources = [

View File

@@ -64,7 +64,8 @@ impl eframe::App for MyApp {
additional_info.push(format!("{} bytes", bytes.len())); additional_info.push(format!("{} bytes", bytes.len()));
} }
if !additional_info.is_empty() { if !additional_info.is_empty() {
info += &format!(" ({})", additional_info.join(", ")); use std::fmt::Write as _;
write!(info, " ({})", additional_info.join(", ")).ok();
} }
ui.label(info); ui.label(info);

View File

@@ -56,7 +56,8 @@ fn viewport_info(ctx: &egui::Context) -> String {
]; ];
for (name, value) in flags { for (name, value) in flags {
if let Some(value) = value { if let Some(value) = value {
s += &format!(" {name}={value}"); use std::fmt::Write as _;
write!(s, " {name}={value}").ok();
} }
} }
s s