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

Add assert messages and print bad argument values in asserts (#5216)

Enabled the `missing_assert_message` lint

* [x] I have followed the instructions in the PR template

---------

Co-authored-by: Lucas Meurer <lucasmeurer96@gmail.com>
This commit is contained in:
Nicolas
2025-03-25 09:20:29 +01:00
committed by GitHub
parent 903bd81313
commit 58b2ac88c0
35 changed files with 331 additions and 108 deletions

View File

@@ -159,7 +159,6 @@ impl MenuState {
}
/// Horizontal menu bar where you can add [`MenuButton`]s.
/// The menu bar goes well in a [`crate::TopBottomPanel::top`],
/// but can also be placed in a [`crate::Window`].
/// In the latter case you may want to wrap it in [`Frame`].

View File

@@ -82,7 +82,11 @@ impl Default for WrappedTextureManager {
epaint::FontImage::new([0, 0]).into(),
Default::default(),
);
assert_eq!(font_id, TextureId::default());
assert_eq!(
font_id,
TextureId::default(),
"font id should be equal to TextureId::default(), but was {font_id:?}",
);
Self(Arc::new(RwLock::new(tex_mngr)))
}
@@ -804,7 +808,11 @@ impl Context {
let max_passes = self.write(|ctx| ctx.memory.options.max_passes.get());
let mut output = FullOutput::default();
debug_assert_eq!(output.platform_output.num_completed_passes, 0);
debug_assert_eq!(
output.platform_output.num_completed_passes, 0,
"output must be fresh, but had {} passes",
output.platform_output.num_completed_passes
);
loop {
profiling::scope!(
@@ -828,7 +836,11 @@ impl Context {
self.begin_pass(new_input.take());
run_ui(self);
output.append(self.end_pass());
debug_assert!(0 < output.platform_output.num_completed_passes);
debug_assert!(
0 < output.platform_output.num_completed_passes,
"Completed passes was lower than 0, was {}",
output.platform_output.num_completed_passes
);
if !output.platform_output.requested_discard() {
break; // no need for another pass
@@ -3272,7 +3284,11 @@ impl Context {
#[cfg(feature = "accesskit")]
self.pass_state_mut(|fs| {
if let Some(state) = fs.accesskit_state.as_mut() {
assert_eq!(state.parent_stack.pop(), Some(_id));
assert_eq!(
state.parent_stack.pop(),
Some(_id),
"Mismatched push/pop in with_accessibility_parent"
);
}
});

View File

@@ -175,11 +175,17 @@ pub fn hit_test(
restore_widget_rect(wr);
}
if let Some(wr) = &mut hits.drag {
debug_assert!(wr.sense.senses_drag());
debug_assert!(
wr.sense.senses_drag(),
"We should only return drag hits if they sense drag"
);
restore_widget_rect(wr);
}
if let Some(wr) = &mut hits.click {
debug_assert!(wr.sense.senses_click());
debug_assert!(
wr.sense.senses_click(),
"We should only return click hits if they sense click"
);
restore_widget_rect(wr);
}
}

View File

@@ -71,9 +71,17 @@ impl Region {
}
pub fn sanity_check(&self) {
debug_assert!(!self.min_rect.any_nan());
debug_assert!(!self.max_rect.any_nan());
debug_assert!(!self.cursor.any_nan());
debug_assert!(
!self.min_rect.any_nan(),
"min rect has Nan: {:?}",
self.min_rect
);
debug_assert!(
!self.max_rect.any_nan(),
"max rect has Nan: {:?}",
self.max_rect
);
debug_assert!(!self.cursor.any_nan(), "cursor has Nan: {:?}", self.cursor);
}
}
@@ -394,8 +402,8 @@ impl Layout {
/// ## Doing layout
impl Layout {
pub fn align_size_within_rect(&self, size: Vec2, outer: Rect) -> Rect {
debug_assert!(size.x >= 0.0 && size.y >= 0.0);
debug_assert!(!outer.is_negative());
debug_assert!(size.x >= 0.0 && size.y >= 0.0, "Negative size: {size:?}");
debug_assert!(!outer.is_negative(), "Negative outer: {outer:?}");
self.align2().align_size_within_rect(size, outer).round_ui()
}
@@ -421,7 +429,7 @@ impl Layout {
}
pub(crate) fn region_from_max_rect(&self, max_rect: Rect) -> Region {
debug_assert!(!max_rect.any_nan());
debug_assert!(!max_rect.any_nan(), "max_rect is not NaN: {max_rect:?}");
let mut region = Region {
min_rect: Rect::NOTHING, // temporary
max_rect,
@@ -454,8 +462,8 @@ impl Layout {
/// Given the cursor in the region, how much space is available
/// for the next widget?
fn available_from_cursor_max_rect(&self, cursor: Rect, max_rect: Rect) -> Rect {
debug_assert!(!cursor.any_nan());
debug_assert!(!max_rect.any_nan());
debug_assert!(!cursor.any_nan(), "cursor is NaN: {cursor:?}");
debug_assert!(!max_rect.any_nan(), "max_rect is NaN: {max_rect:?}");
// NOTE: in normal top-down layout the cursor has moved below the current max_rect,
// but the available shouldn't be negative.
@@ -509,7 +517,7 @@ impl Layout {
avail.max.y = y;
}
debug_assert!(!avail.any_nan());
debug_assert!(!avail.any_nan(), "avail is NaN: {avail:?}");
avail
}
@@ -520,7 +528,10 @@ impl Layout {
/// Use `justify_and_align` to get the inner `widget_rect`.
pub(crate) fn next_frame(&self, region: &Region, child_size: Vec2, spacing: Vec2) -> Rect {
region.sanity_check();
debug_assert!(child_size.x >= 0.0 && child_size.y >= 0.0);
debug_assert!(
child_size.x >= 0.0 && child_size.y >= 0.0,
"Negative size: {child_size:?}"
);
if self.main_wrap {
let available_size = self.available_rect_before_wrap(region).size();
@@ -600,7 +611,10 @@ impl Layout {
fn next_frame_ignore_wrap(&self, region: &Region, child_size: Vec2) -> Rect {
region.sanity_check();
debug_assert!(child_size.x >= 0.0 && child_size.y >= 0.0);
debug_assert!(
child_size.x >= 0.0 && child_size.y >= 0.0,
"Negative size: {child_size:?}"
);
let available_rect = self.available_rect_before_wrap(region);
@@ -633,16 +647,19 @@ impl Layout {
frame_rect = frame_rect.translate(Vec2::Y * (region.cursor.top() - frame_rect.top()));
}
debug_assert!(!frame_rect.any_nan());
debug_assert!(!frame_rect.is_negative());
debug_assert!(!frame_rect.any_nan(), "frame_rect is NaN: {frame_rect:?}");
debug_assert!(!frame_rect.is_negative(), "frame_rect is negative");
frame_rect.round_ui()
}
/// Apply justify (fill width/height) and/or alignment after calling `next_space`.
pub(crate) fn justify_and_align(&self, frame: Rect, mut child_size: Vec2) -> Rect {
debug_assert!(child_size.x >= 0.0 && child_size.y >= 0.0);
debug_assert!(!frame.is_negative());
debug_assert!(
child_size.x >= 0.0 && child_size.y >= 0.0,
"Negative size: {child_size:?}"
);
debug_assert!(!frame.is_negative(), "frame is negative");
if self.horizontal_justify() {
child_size.x = child_size.x.at_least(frame.width()); // fill full width
@@ -660,8 +677,8 @@ impl Layout {
) -> Rect {
let frame = self.next_frame_ignore_wrap(region, size);
let rect = self.align_size_within_rect(size, frame);
debug_assert!(!rect.any_nan());
debug_assert!(!rect.is_negative());
debug_assert!(!rect.any_nan(), "rect is NaN: {rect:?}");
debug_assert!(!rect.is_negative(), "rect is negative: {rect:?}");
rect
}
@@ -704,7 +721,7 @@ impl Layout {
widget_rect: Rect,
item_spacing: Vec2,
) {
debug_assert!(!cursor.any_nan());
debug_assert!(!cursor.any_nan(), "cursor is NaN: {cursor:?}");
if self.main_wrap {
if cursor.intersects(frame_rect.shrink(1.0)) {
// make row/column larger if necessary

View File

@@ -133,8 +133,8 @@ impl Placer {
/// Apply justify or alignment after calling `next_space`.
pub(crate) fn justify_and_align(&self, rect: Rect, child_size: Vec2) -> Rect {
debug_assert!(!rect.any_nan());
debug_assert!(!child_size.any_nan());
debug_assert!(!rect.any_nan(), "rect: {rect:?}");
debug_assert!(!child_size.any_nan(), "child_size is NaN: {child_size:?}");
if let Some(grid) = &self.grid {
grid.justify_and_align(rect, child_size)
@@ -164,8 +164,11 @@ impl Placer {
widget_rect: Rect,
item_spacing: Vec2,
) {
debug_assert!(!frame_rect.any_nan());
debug_assert!(!widget_rect.any_nan());
debug_assert!(!frame_rect.any_nan(), "frame_rect: {frame_rect:?}");
debug_assert!(
!widget_rect.any_nan(),
"widget_rect is NaN: {widget_rect:?}"
);
self.region.sanity_check();
if let Some(grid) = &mut self.grid {

View File

@@ -985,7 +985,10 @@ impl Response {
///
/// You may not call [`Self::interact`] on the resulting `Response`.
pub fn union(&self, other: Self) -> Self {
assert!(self.ctx == other.ctx);
assert!(
self.ctx == other.ctx,
"Responses must be from the same `Context`"
);
debug_assert!(
self.layer_id == other.layer_id,
"It makes no sense to combine Responses from two different layers"

View File

@@ -271,7 +271,12 @@ pub fn byte_index_from_char_index(s: &str, char_index: usize) -> usize {
}
pub fn slice_char_range(s: &str, char_range: std::ops::Range<usize>) -> &str {
assert!(char_range.start <= char_range.end);
assert!(
char_range.start <= char_range.end,
"Invalid range, start must be less than end, but start = {}, end = {}",
char_range.start,
char_range.end
);
let start_byte = byte_index_from_char_index(s, char_range.start);
let end_byte = byte_index_from_char_index(s, char_range.end);
&s[start_byte..end_byte]

View File

@@ -59,7 +59,11 @@ pub fn paint_text_selection(
// Start by appending the selection rectangle to end of the mesh, as two triangles (= 6 indices):
let num_indices_before = mesh.indices.len();
mesh.add_colored_rect(rect, color);
assert_eq!(num_indices_before + 6, mesh.indices.len());
assert_eq!(
num_indices_before + 6,
mesh.indices.len(),
"We expect exactly 6 new indices"
);
// Copy out the new triangles:
let selection_triangles = [

View File

@@ -286,7 +286,7 @@ impl Ui {
}
}
debug_assert!(!max_rect.any_nan());
debug_assert!(!max_rect.any_nan(), "max_rect is NaN: {max_rect:?}");
let stable_id = self.id.with(id_salt);
let unique_id = stable_id.with(self.next_auto_id_salt);
let next_auto_id_salt = unique_id.value().wrapping_add(1);
@@ -914,14 +914,20 @@ impl Ui {
/// Set the minimum width of the ui.
/// This can't shrink the ui, only make it larger.
pub fn set_min_width(&mut self, width: f32) {
debug_assert!(0.0 <= width);
debug_assert!(
0.0 <= width,
"Negative width makes no sense, but got: {width}"
);
self.placer.set_min_width(width);
}
/// Set the minimum height of the ui.
/// This can't shrink the ui, only make it larger.
pub fn set_min_height(&mut self, height: f32) {
debug_assert!(0.0 <= height);
debug_assert!(
0.0 <= height,
"Negative height makes no sense, but got: {height}"
);
self.placer.set_min_height(height);
}
@@ -1399,7 +1405,7 @@ impl Ui {
fn allocate_space_impl(&mut self, desired_size: Vec2) -> Rect {
let item_spacing = self.spacing().item_spacing;
let frame_rect = self.placer.next_space(desired_size, item_spacing);
debug_assert!(!frame_rect.any_nan());
debug_assert!(!frame_rect.any_nan(), "frame_rect is nan in allocate_space");
let widget_rect = self.placer.justify_and_align(frame_rect, desired_size);
self.placer
@@ -1422,7 +1428,7 @@ impl Ui {
/// Allocate a rect without interacting with it.
pub fn advance_cursor_after_rect(&mut self, rect: Rect) -> Id {
debug_assert!(!rect.any_nan());
debug_assert!(!rect.any_nan(), "rect is nan in advance_cursor_after_rect");
let rect = rect.round_ui();
let item_spacing = self.spacing().item_spacing;
@@ -1494,7 +1500,10 @@ impl Ui {
layout: Layout,
add_contents: Box<dyn FnOnce(&mut Self) -> R + 'c>,
) -> InnerResponse<R> {
debug_assert!(desired_size.x >= 0.0 && desired_size.y >= 0.0);
debug_assert!(
desired_size.x >= 0.0 && desired_size.y >= 0.0,
"Negative desired size: {desired_size:?}"
);
let item_spacing = self.spacing().item_spacing;
let frame_rect = self.placer.next_space(desired_size, item_spacing);
let child_rect = self.placer.justify_and_align(frame_rect, desired_size);

View File

@@ -199,7 +199,10 @@ impl Label {
let cursor = ui.cursor();
let first_row_indentation = available_width - ui.available_size_before_wrap().x;
debug_assert!(first_row_indentation.is_finite());
debug_assert!(
first_row_indentation.is_finite(),
"first row indentation is not finite: {first_row_indentation}"
);
layout_job.wrap.max_width = available_width;
layout_job.first_row_min_height = cursor.height();

View File

@@ -1065,7 +1065,10 @@ fn value_from_normalized(normalized: f64, range: RangeInclusive<f64>, spec: &Sli
let log = lerp(min_log..=max_log, normalized);
10.0_f64.powf(log)
} else {
assert!(min < 0.0 && 0.0 < max);
assert!(
min < 0.0 && 0.0 < max,
"min should be negative and max positive, but got min={min} and max={max}"
);
let zero_cutoff = logarithmic_zero_cutoff(min, max);
if normalized < zero_cutoff {
// negative
@@ -1114,7 +1117,10 @@ fn normalized_from_value(value: f64, range: RangeInclusive<f64>, spec: &SliderSp
let value_log = value.log10();
remap_clamp(value_log, min_log..=max_log, 0.0..=1.0)
} else {
assert!(min < 0.0 && 0.0 < max);
assert!(
min < 0.0 && 0.0 < max,
"min should be negative and max positive, but got min={min} and max={max}"
);
let zero_cutoff = logarithmic_zero_cutoff(min, max);
if value < 0.0 {
// negative
@@ -1142,8 +1148,11 @@ fn normalized_from_value(value: f64, range: RangeInclusive<f64>, spec: &SliderSp
}
fn range_log10(min: f64, max: f64, spec: &SliderSpec) -> (f64, f64) {
assert!(spec.logarithmic);
assert!(min <= max);
assert!(spec.logarithmic, "spec must be logarithmic");
assert!(
min <= max,
"min must be less than or equal to max, but was min={min} and max={max}"
);
if min == 0.0 && max == INFINITY {
(spec.smallest_positive.log10(), INF_RANGE_MAGNITUDE)
@@ -1167,7 +1176,10 @@ fn range_log10(min: f64, max: f64, spec: &SliderSpec) -> (f64, f64) {
/// where to put the zero cutoff for logarithmic sliders
/// that crosses zero ?
fn logarithmic_zero_cutoff(min: f64, max: f64) -> f64 {
assert!(min < 0.0 && 0.0 < max);
assert!(
min < 0.0 && 0.0 < max,
"min must be negative and max positive, but got min={min} and max={max}"
);
let min_magnitude = if min == -INFINITY {
INF_RANGE_MAGNITUDE

View File

@@ -194,7 +194,10 @@ impl TextBuffer for String {
}
fn delete_char_range(&mut self, char_range: Range<usize>) {
assert!(char_range.start <= char_range.end);
assert!(
char_range.start <= char_range.end,
"start must be <= end, but got {char_range:?}"
);
// Get both byte indices
let byte_start = byte_index_from_char_index(self.as_str(), char_range.start);