It is a fundamental language limitation, unless you want to claim that the core library (or rather what's left when using no_std) is not part of the language.

The problem comes from a combination of three things:

1. Rust's standard library (including core) likes to panic a lot, e.g. for code that is genuinely unreachable (and this is fine)

2. Rust/LLVM cannot always optimize unreachable code away (and this is also fine)

3. The presence of at least one panic causes Rust to also include the error string format machinery, which is HUGE (and this is completely unavoidable)

Because of #2, there is no way to prevent this for larger code. I can define my own panic handler, but I can't prevent panic!() calls from inside core from constructing the format message using core::fmt before they call my panic handler.

And so any non-trivial code sometimes just randomly becomes 3x larger, and I can no longer fit it on my MCU, despite never actually printing or caring about any panic messages.

I think we just disagree about what "fundamental" means. If you don't use panics, you don't get the machinery. This means it's not fundamental.

What you're talking about is the ease of which you can not include the panic machinery. I agree that it is not always easy to keep out, and that I would like if it were to be made easier.

But people are doing real, commercial projects on MCUs your size and smaller.

> If you don't use panics, you don't get the machinery.

I'm not using panics, and yet I'm getting the machinery. That is where my frustration is coming from.