A lot of metadata is included with each library crate, be it statically linked ( .rlib ) or dynamically linked ( .so / .dylib / .dll ):

module structure

exported macro_rules macros

macros type and trait definitions

constants with their initializer expressions

signatures for all functions

the entire body of each function that is marked as #[inline] or is generic (default trait methods are considered generic over Self )

All of this is enough to reproduce some of the original source (how much depends on the usage of generics), albeit with no comments or other whitespace.

The function bodies are serialized in the compiler's internal AST structure - you can see a pretty form of it with rustc -Z ast-json lib.rs .

While the metadata is binary, not JSON, using librustc to extract all exported function definitions from a compiled crate, and pretty-printing the ASTs is fairly easy.

In the future, there might not be any AST past type-checking, so the metadata would encode an IR of sorts – one possibility is CFG, i.e. "control flow graph", which is already used internally in a couple places.

However, that would still expose more information than Java bytecode, it would be an optimization, you could still approximate the original code (and easily get something which compiles).

As such, there are only two options I can recommend: