Skip to content

Any Display error works, including Box<dyn Error> — and it already did - #8

Merged
zmaril merged 1 commit into
mainfrom
feat/boxed-error
Aug 18, 2026
Merged

Any Display error works, including Box<dyn Error> — and it already did#8
zmaril merged 1 commit into
mainfrom
feat/boxed-error

Conversation

@zmaril

@zmaril zmaril commented Aug 18, 2026

Copy link
Copy Markdown
Contributor

Stacked on #7. Item 5, with a correction: the premise was wrong, and the
wrongness was mine.

I reported that a function which can fail two ways had to flatten to
Result<_, String> and litter itself with .map_err(|e| e.to_string()) — six
such calls in jawohl's surface. But jedem never inspected the error type.
Every backend renders failure as that language's own mechanism carrying the
error's Display text, so Box<dyn Error> and anyhow::Error have always
worked. jawohl's map_err calls were self-inflicted.

So this adds no feature. It proves the behaviour, documents it where someone
would look, and demonstrates it:

pub fn halve_parsed(text: &str) -> Result<i64, Box<dyn Error>> {
    let n: i64 = text.parse()?;              // one failure type
    if n % 2 != 0 { return Err(format!("{n} is odd").into()); }   // another
    Ok(n / 2)
}
hello.halve_parsed("10")      # 5
hello.halve_parsed("9")       # ValueError: 9 is odd
hello.halve_parsed("banana")  # ValueError: invalid digit found in string

jawohl's surface can now drop its six map_err calls — a change in the
jawohl repo, which I'll make there.

The fourth occurrence of one bug class

While adding the demo, cargo fmt broke the drift guard again — this time
collapsing a double blank line between two interfaces. The previous three were a
trailing space on an empty doc line, a trailing blank line at EOF, and the same
again per backend.

Patching the emitter a fourth time would have been the wrong response. The
invariants are now central: a normalise() step every backend's output
passes through, enforcing no trailing whitespace, no run of blank lines, exactly
one terminal newline. Tests assert each across Target::ALL, plus one that
generation is normalisation-stable — what jedem writes is what rustfmt would
leave alone.

39 tests, clippy clean, both round-trips passing.

Next and last of the series: #[derive(Enum)].

🤖 Generated with Claude Code

https://claude.ai/code/session_01HsDxLrGdx6nPaXkVEWkNvS

Base automatically changed from feat/export-bare-fn to main August 18, 2026 20:46
Item 5, with a correction: the premise was wrong, and the wrongness was mine.

The complaint was that a function which can fail two ways had to flatten to
Result<_, String> and litter itself with .map_err(|e| e.to_string()) -- six such
calls in jawohl's surface. But jedem never inspected the error type. Every
backend renders failure as that language's own mechanism carrying the error's
Display text, so Box<dyn Error> and anyhow::Error have always worked. jawohl's
map_err calls were self-inflicted.

So this commit does not add a feature. It proves the behaviour with tests, says
so in the docs where someone would look, and demonstrates it in the demo: a
function returning Result<i64, Box<dyn Error>> that fails two different ways --
a parse error and a domain error -- crosses to Python and Node with each
message intact. jawohl's surface can now drop its six map_err calls; that is a
change in the jawohl repo.

While adding the demo, cargo fmt broke the drift guard again -- the fourth
occurrence of the same class. This time it collapsed a double blank line
between two interfaces. The previous three were a trailing space on an empty
doc line, a trailing blank line at end of file, and the same again per backend.

Patching the emitter a fourth time would have been the wrong response, so the
invariants are now central: a normalise() step every backend's output passes
through, enforcing no trailing whitespace, no run of blank lines, and exactly
one terminal newline. Tests assert each invariant across Target::ALL, plus one
that generation is normalisation-stable -- what jedem writes is what rustfmt
would leave alone.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HsDxLrGdx6nPaXkVEWkNvS
@zmaril
zmaril merged commit f35ed1b into main Aug 18, 2026
4 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.

1 participant