Skip to content

#74: Debug impl forwards through Debug, not Display#75

Merged
yegor256 merged 1 commit into
yegor256:masterfrom
guaardvark:fix/74-debug-forwards-debug
Jun 8, 2026
Merged

#74: Debug impl forwards through Debug, not Display#75
yegor256 merged 1 commit into
yegor256:masterfrom
guaardvark:fix/74-debug-forwards-debug

Conversation

@guaardvark

Copy link
Copy Markdown
Contributor

Closes #74.

Problem

The Debug impl for Stack<V, N> (src/debug.rs) was bounded on V: Display + Copy and formatted each element with format!("{v}") — that calls Display::fmt, not Debug::fmt. Two consequences:

  • A Stack<T, N> whose element implements Debug but not Display (any plain #[derive(Debug)] struct, Option<_>, etc.) could not be printed with {:?} at all, even though T: Debug holds.
  • When T implemented both traits, {:?} silently produced the Display representation instead of the Debug one.

This contradicts the convention every std container follows, where Debug on the container forwards through Debug on the element.

Fix

Bound the Debug impl on V: Debug + Copy and format with format!("{v:?}").

The Display impl previously delegated to Debug (<&Self as Debug>::fmt). Since the two impls now carry different bounds (Display vs Debug) and produce different output, that delegation no longer type-checks, so Display gets its own identical loop over Display::fmt — its behaviour is unchanged.

Tests

  • debugs_stack now asserts the quoted Debug form of &str: [\"one\", \"two\"].
  • New debugs_stack_of_debug_only_type builds a Stack<Option<i32>, N>Option<i32> is Debug + Copy but not Display, so this test would not even have compiled under the old bound.

Verified locally: cargo test (debug + release), cargo fmt --check, and cargo clippy -- --no-deps all clean, with no new warnings in debug.rs.

@yegor256

yegor256 commented Jun 7, 2026

Copy link
Copy Markdown
Owner

@guaardvark don't commit target/ dir please

@guaardvark guaardvark force-pushed the fix/74-debug-forwards-debug branch from 00e3f49 to 17dca3c Compare June 7, 2026 15:14
@guaardvark

Copy link
Copy Markdown
Contributor Author

Good catch, sorry about that — removed the target/ dir and force-pushed; the PR now contains only src/debug.rs.

@guaardvark guaardvark force-pushed the fix/74-debug-forwards-debug branch 2 times, most recently from 56ffb91 to 232405c Compare June 7, 2026 15:35
The `Debug` impl for `Stack<V, N>` was bounded on `V: Display + Copy` and
formatted each element with `format!("{v}")`, i.e. via `Display::fmt`. As a
result a `Stack<T, N>` whose element only implements `Debug` (any plain
`#[derive(Debug)]` type, `Option<_>`, etc.) could not be printed with `{:?}`
at all, and when `T` implemented both traits the `{:?}` output silently
showed the `Display` form instead of the `Debug` form.

This contradicts every std container, where `Debug` on the container
forwards through `Debug` on the element. Bound the `Debug` impl on
`V: Debug + Copy` and format with `format!("{v:?}")`.

The `Display` impl previously delegated to `Debug`; since the two impls now
have different bounds and different output, `Display` gets its own identical
loop over `Display::fmt`, keeping its behaviour unchanged.

Tests: `debugs_stack` now asserts the quoted `Debug` form of `&str`; a new
`debugs_stack_of_debug_only_type` uses `Stack<Option<i32>, N>` (Debug but
not Display) which would not have compiled under the old bound.
@yegor256 yegor256 merged commit 21fdb1d into yegor256:master Jun 8, 2026
3 checks passed
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.

Debug impl in src/debug.rs requires V: Display and uses the Display formatter, hiding types that only implement Debug

2 participants