Избитая тема, которая уже подымалась и изучалась не один раз. Достаточно сделать:
https://www.google.com/search?q=rust+binary+size и сразу попадаем на статью
Rustlog: Why is a Rust executable large?. Настоятельно рекомендую к прочтению, хоть она и слегка устарела (Rust больше не использует jemalloc по умолчанию), но вопрос там разобран крайне детально.
Если коротко, то в Ваш бинарь попадают:
1. Если собирали не в release mode, то debug-символы.
2. Аллокатор, либо код-клей для системного аллокатора.
3. Код для panic unwinding (в том числе и libbacktrace).
4. Части libstd Rust'а, даже если Вы их не используете.
Если стоит задача минимизировать бинарь Rust (под всякий embedded, к примеру), то обычно делают
#![no_std]
, юзают
мини-аллокаторы, делают
panic = abort
и идут на другие лишения.