# Solid reflection in rust

**URL:** https://internals.rust-lang.org/t/solid-reflection-in-rust/12550
**Category:** language design
**Created:** [June 14, 2020, 11:29am UTC](https://internals.rust-lang.org/t/solid-reflection-in-rust/12550 "2020-06-14T11:29:53Z")
**Posts on this page:** 20
**Page:** 1

<div class="post-metadata">

### Author: ![publicocean0](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/publicocean0/32/6932_2.png) [@publicocean0](https://internals.rust-lang.org/u/publicocean0)
#### Post date: [June 14, 2020, 11:29am UTC](https://internals.rust-lang.org/t/solid-reflection-in-rust/12550/1 "2020-06-14T11:29:53Z")

</div>

I think rust is a very interesting. In many aspects it is better than other langs . I think a company could be almost ready to pass to create projects in rust lang but there is still a strong limit caused by reflection absense. The most important frameworks , library in enterprise world software are using reflection . It is mandatary in the modern software to use reflection. I think the first priority for adding new feature in language should be in this sense . I opened this topic for triggering rust developers and designers to give much more effort in this direction.

---

<div class="post-metadata">

### Author: ![Ixrec](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/ixrec/32/6754_2.png) [@Ixrec](https://internals.rust-lang.org/u/Ixrec)
#### Post date: [June 14, 2020, 12:08pm UTC](https://internals.rust-lang.org/t/solid-reflection-in-rust/12550/2 "2020-06-14T12:08:18Z")

</div>

This is pretty thoroughly covered in existing discussions, most recently [Pre-RFC: Runtime reflection](https://internals.rust-lang.org/t/pre-rfc-runtime-reflection/11039)

IIRC the conclusions in that thread boiled down to "compile-time reflection is already _mostly_ feasible with macro libraries, and there's no motivation for runtime reflection; the reasons Java/C#/etc have runtime reflection simply don't apply to Rust."

Perhaps most interesting was this post from an "enterprise" user of Rust who basically whipped up their own compile-time reflection stuff in-house and yet agrees for many reasons that it shouldn't be a core language feature:

> [@Pre-RFC: Runtime reflection](https://internals.rust-lang.org/t/pre-rfc-runtime-reflection/11039/48):
>
> In our system, we've built something very similar to what is proposed in this RFC. What we have is: we have our own trait-object-based "reflection" API. we've re-built serialization to use that API instead of using serde directly. Exactly the case mentioned in the RFC. we use that API for other purposes, too (for example, validation against dynamic type schemas). So, this RFC would be down our alley, right? Well, not quite, I don't think so. Here is why. Based on my experience building this …

In particular, the suggestions for improvement that post does make:

> Things that, I think, would help us are smaller building blocks that we can use to create our "reflection" API, such as:
> 
> - compile-time macroses for things like 1) field offsets 2) trait object vtables (yeah... there's a lot behind this "tiny" ask 🙂 )
> - maybe, some ABI stability for trait objects & such (so we can have types to be dynamically loadable)

are things actively being discussed by the community under other subject headers like "layout guarantees", since they're far more low-level than and would unlock a lot more use cases than just reflection code.

---

<div class="post-metadata">

### Author: ![publicocean0](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/publicocean0/32/6932_2.png) [@publicocean0](https://internals.rust-lang.org/u/publicocean0)
#### Post date: [June 14, 2020, 12:34pm UTC](https://internals.rust-lang.org/t/solid-reflection-in-rust/12550/3 "2020-06-14T12:34:11Z")

</div>

Reflection not embedded in language sounds good . Reflection implemented in a crate is a good idea . Reflection at compile time?uhmm i dont think is sufficient in the modern software . There are many cases where you need to add behaviour, features not at compile time but when the application is running. To handle many customizable features in application on demand-time is the tipical need in enterprise platforms . I dont think also at compile time you can add reflection if you apply it on already compiled crate. I m worried, rust with this choise will block its diffusion . So it will remain smart alternative for c++ , nothing else.

---

<div class="post-metadata">

### Author: ![Ixrec](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/ixrec/32/6754_2.png) [@Ixrec](https://internals.rust-lang.org/u/Ixrec)
#### Post date: [June 14, 2020, 12:40pm UTC](https://internals.rust-lang.org/t/solid-reflection-in-rust/12550/4 "2020-06-14T12:40:03Z")

</div>

> [@publicocean0](#):
>
> There are many cases where you need to add behaviour, features not at compile time but when the application is running. To handle many customizable features in application on demand-time is the tipical need in enterprise platforms .

This appears to be talking about plugins, which are a totally separate thing from runtime reflection. I believe Java/C#/etc typically use runtime reflection for plugins, but this is just another example of "those languages' reasons don't apply to Rust".

See [Plugins in Rust · Michael-F-Bryan](http://adventures.michaelfbryan.com/posts/plugins-in-rust/) for details.

If plugins are not what you're trying to ask for, then please provide way more detail so we can understand you.

> [@publicocean0](#):
>
> I dont think also at compile time you can add reflection is you apply it on already compiled crate.

After compilation, there's no guarantee the type you want to reflect on even _exists_ any more, so it's not clear what "runtime reflection" would even mean (without some opt-in component at compile-time, which then might as well just provide compile-time reflection instead).

So this is most likely a deeply confused statement and we're again going to need way more detail about what you're looking for to offer any meaningful response.

---

<div class="post-metadata">

### Author: ![H2CO3](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/h2co3/32/2849_2.png) [@H2CO3](https://internals.rust-lang.org/u/H2CO3)
#### Post date: [June 14, 2020, 12:40pm UTC](https://internals.rust-lang.org/t/solid-reflection-in-rust/12550/5 "2020-06-14T12:40:20Z")

</div>

Please do some research. Many real-world use cases are covered by compile-time reflection in a better, more principled way than what's possible in other languages. Serde, Diesel, `derive`-able traits in general. Your abstract "it won't be good enough" argument is readily contradicted by their existence.

Furthermore, if you prefer working in C++ and not using Rust for this reason or another, that is perfectly fine.

---

<div class="post-metadata">

### Author: ![publicocean0](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/publicocean0/32/6932_2.png) [@publicocean0](https://internals.rust-lang.org/u/publicocean0)
#### Post date: [June 14, 2020, 12:48pm UTC](https://internals.rust-lang.org/t/solid-reflection-in-rust/12550/6 "2020-06-14T12:48:49Z")

</div>

Non only plugins , instrumentation for example is very used in modern languages , it permits to add bevaviour to the compiled code at runtime , native code generation based on specific struct defined by a runtime application(not tell me to write rust code in a file and then to compile it because it is not a serious solution ),....How do you solve it?

---

<div class="post-metadata">

### Author: ![Ixrec](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/ixrec/32/6754_2.png) [@Ixrec](https://internals.rust-lang.org/u/Ixrec)
#### Post date: [June 14, 2020, 12:54pm UTC](https://internals.rust-lang.org/t/solid-reflection-in-rust/12550/7 "2020-06-14T12:54:58Z")

</div>

Again, you need to be far more specific and detailed for us to tell what you're trying to say.

I _could_ make some additional guesses about what "add behavior ... at runtime" means and point out that there are loads of sanitizers and profilers and other tools which basically do that at the assembly level and thus work just as well on Rust as on C/C++. But again, I simply have no idea if that's what you're talking about or not. Help us help you.

---

<div class="post-metadata">

### Author: ![publicocean0](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/publicocean0/32/6932_2.png) [@publicocean0](https://internals.rust-lang.org/u/publicocean0)
#### Post date: [June 14, 2020, 1:01pm UTC](https://internals.rust-lang.org/t/solid-reflection-in-rust/12550/8 "2020-06-14T13:01:52Z")

</div>

instrumentation and code generation are not concept invented by me . They are known and used for many decades . I think you have to study a bit about it. To be critical in general ok but you need also to evaluate and weight the fact if thousands of engineers used a solution ... maybe there are cases where it is necessary

---

<div class="post-metadata">

### Author: ![RustyYato](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/rustyyato/32/13627_2.png) [@RustyYato](https://internals.rust-lang.org/u/RustyYato)
#### Post date: [June 14, 2020, 4:46pm UTC](https://internals.rust-lang.org/t/solid-reflection-in-rust/12550/9 "2020-06-14T16:46:59Z")

</div>

I think the combo of macros and dylibs should be enough to suit any need that other languages would use reflection for... so it's not clear what you feel is lacking. You just say that "instrumentation and code generation are important" but you don't explain why Rust doesn't solve these issues.

---

<div class="post-metadata">

### Author: ![publicocean0](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/publicocean0/32/6932_2.png) [@publicocean0](https://internals.rust-lang.org/u/publicocean0)
#### Post date: [June 14, 2020, 4:54pm UTC](https://internals.rust-lang.org/t/solid-reflection-in-rust/12550/10 "2020-06-14T16:54:17Z")

</div>

if you think rust can solve , explain you how to do this. Instrumentation and code generation is known. I cant expain computer science concepts here. There are books and manuals

---

<div class="post-metadata">

### Author: ![chriskrycho](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/chriskrycho/32/12576_2.png) [@chriskrycho](https://internals.rust-lang.org/u/chriskrycho)
#### Post date: [June 14, 2020, 5:48pm UTC](https://internals.rust-lang.org/t/solid-reflection-in-rust/12550/11 "2020-06-14T17:48:54Z")

</div>

The thing other people are trying to express is: it’s possible to instrument code and generate code _at compile time_ in Rust, via its macro system. In particular, _many_ of the things that use reflection in C♯ and other languages not only _can_ be done but _are_ done in Rust—via procedural macros! Are you familiar with all the kinds of things that Rust’s macros can do? If so, can you give a specific example of a thing you would _like_ to be able to do but find that you cannot? Because “code generation” and “instrumentation” are already things you can do in Rust—just in a different way than you would in other languages. People here understand the broad strokes; it’s the details that matter. 🙂

---

<div class="post-metadata">

### Author: ![publicocean0](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/publicocean0/32/6932_2.png) [@publicocean0](https://internals.rust-lang.org/u/publicocean0)
#### Post date: [June 14, 2020, 6:42pm UTC](https://internals.rust-lang.org/t/solid-reflection-in-rust/12550/12 "2020-06-14T18:42:34Z")

</div>

yes you can deassembly a struct in memory , inject a method on the fly in the struct or modify a method already present. In this way you can change the normal bevaviour of a struct . The code generation is used to generate dinamically struct defined at runtime time. Suppose you want create a struct with specific attributes based on a user form for handling with high performance dynamic structure. This concepts are used also for AOP programming. The fact is at compile time you can use a library defined by others developers , you havent the source code or you have but for you it is a black box . When you work in a big project you cant imagine to modify external libraries you dont know But it is not important for you . You can just add a additional feature to logic without touch the code . You work using formal logic for modify the behaviour. Instrumentation is used also for patch modules (also multiple module in the same time). For example you have a complex application using many external libraries using a common mutex. You can change the mutex behavour without touching the logic of libraries. Many framework use code generation for create optimized code based on your configuration read at runtime. Yes the generic idea to use the power of rust macro for reflection is very intelligent. But it is not the solution for all.

---

<div class="post-metadata">

### Author: ![RustyYato](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/rustyyato/32/13627_2.png) [@RustyYato](https://internals.rust-lang.org/u/RustyYato)
#### Post date: [June 14, 2020, 7:00pm UTC](https://internals.rust-lang.org/t/solid-reflection-in-rust/12550/13 "2020-06-14T19:00:49Z")

</div>

I think you underestimate the power of macros. In particular, procedural macros are basically just normal Rust code that you can do anything with (read files, talk the the network), if you want to dynamically load in things modules, that's what dylibs are for. Everything else can be done in build scripts (which I see as light weight codegen), which is also just ordinary Rust code.

> [@publicocean0](#):
>
> For example you have a complex application using many external libraries using a common mutex. You can change the mutex behavour without touching the logic of libraries.

This is a bad example, because you don't need reflection for this at all. This is just pulling in a library. (see [`parking_lot`](https://docs.rs/parking_lot/0.10.2/parking_lot/) for an example of decoupling the mutex implementation from the usage). But you can't change the implementations of mutexes used in upstream libraries, as that could undermine the safety of those libraries who depend on their implementations for safety.

* * *

Note: Rust may not do things in the exact same way, but that's fine. There are other ways to solve the same problems.

> [@publicocean0](#):
>
> yes you can deassembly a struct in memory , inject a method on the fly in the struct or modify a method already present. In this way you can change the normal bevaviour of a struct .

You can do something similar with dylibs, (see the plugin article that was linked earlier).

> [@publicocean0](#):
>
> The code generation is used to generate dinamically struct defined at runtime time.

This can't be done, all structs must be defined at compile time. Instead you could use something like `HashMap<String, Box<dyn Any>>`, for a dynamically defined struct. (or a wrapper around this). This is similar to how other langauges internally represent structs. (maybe swap `Box` for another smart pointer depending on how you use it).

> [@publicocean0](#):
>
> Many framework use code generation for create optimized code based on your configuration read at runtime.

This is done with `proc-macros`/build scripts

> [@publicocean0](#):
>
> The fact is at compile time you can use a library defined by others developers , you havent the source code or you have but for you it is a black box . When you work in a big project you cant imagine to modify external libraries you dont know But it is not important for you . You can just add a additional feature to logic without touch the code .

I don't know what your getting at here.

---

<div class="post-metadata">

### Author: ![publicocean0](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/publicocean0/32/6932_2.png) [@publicocean0](https://internals.rust-lang.org/u/publicocean0)
#### Post date: [June 14, 2020, 8:06pm UTC](https://internals.rust-lang.org/t/solid-reflection-in-rust/12550/14 "2020-06-14T20:06:41Z")

</div>

> [@RustyYato](#):
>
> This is a bad example, because you don't need reflection for this at all. This is just pulling in a library. (see [`parking_lot`](https://docs.rs/parking_lot/0.10.2/parking_lot/) for an example of decoupling the mutex implementation from the usage). But you can't change the implementations of mutexes used in upstream libraries, as that could undermine the safety of those libraries who depend on their implementations for safety.

You are not yet understanding ☹

> You can do something similar with dylibs, (see the plugin article that was linked earlier). I dont think is the same , in your case read on the fly it seems you are loading dinamically a library , ie, it is a code already defined , in my case the code is written at runtime , not compile time.

---

<div class="post-metadata">

### Author: ![publicocean0](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/publicocean0/32/6932_2.png) [@publicocean0](https://internals.rust-lang.org/u/publicocean0)
#### Post date: [June 14, 2020, 8:18pm UTC](https://internals.rust-lang.org/t/solid-reflection-in-rust/12550/15 "2020-06-14T20:18:03Z")

</div>

i found finally a library doing it . A developer understanding exists ,ahahaah [https://docs.rs/reflect/0.0.7/reflect/](https://docs.rs/reflect/0.0.7/reflect/) but it is not solid yet

---

<div class="post-metadata">

### Author: ![matt1985](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/matt1985/32/4772_2.png) [@matt1985](https://internals.rust-lang.org/u/matt1985)
#### Post date: [June 14, 2020, 9:50pm UTC](https://internals.rust-lang.org/t/solid-reflection-in-rust/12550/16 "2020-06-14T21:50:34Z")

</div>

I'm confused,the library doesn't do anything at runtime:

> Once again the reflection API is _just_ a means for defining a procedural macro. Despite what it may look like below, everything written here executes at compile time. The `reflect` library spits out generated code in an output `TokenStream` that is compiled into the macro user's crate. This token stream contains no vestiges of runtime reflection.

---

<div class="post-metadata">

### Author: ![ohAitch](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/ohaitch/32/5779_2.png) [@ohAitch](https://internals.rust-lang.org/u/ohAitch)
#### Post date: [June 14, 2020, 10:05pm UTC](https://internals.rust-lang.org/t/solid-reflection-in-rust/12550/17 "2020-06-14T22:05:33Z")

</div>

> [@publicocean0](#):
>
> The fact is at compile time you can use a library defined by others developers , you havent the source code or you have but for you it is a black box .

This seems to be a lot of the disconnect here: Rust is really not designed for working with binary/obfuscated-source dependencies, and for good reason. Java allows you to do a lot by runtime decompiling library bytecode, even if the vendor intended not to provide them in readable form; I believe a lot of the Rust ABI stability pushback is to prevent being stuck developing in "black box" scenarios as a supported use-case.

---

<div class="post-metadata">

### Author: ![Ixrec](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/ixrec/32/6754_2.png) [@Ixrec](https://internals.rust-lang.org/u/Ixrec)
#### Post date: [June 14, 2020, 10:12pm UTC](https://internals.rust-lang.org/t/solid-reflection-in-rust/12550/18 "2020-06-14T22:12:47Z")

</div>

Even more fundamentally, Rust deeply and pervasively relies on zero-cost abstractions to achieve most of the high-level properties that made us care about the language in the first place ("fast, reliable, productive: pick three."). But you simply cannot do that while preserving all of the type information that Java/C#/etc bytecode does, which is critical to doing things like runtime reflection against precompiled libraries you can’t change the source of.

(this is what I was getting at earlier when I mentioned that types aren’t even guaranteed to exist at runtime; many types can’t be zero-cost abstractions if we forbade the optimizer from optimizing away their existence)

---

<div class="post-metadata">

### Author: ![publicocean0](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/publicocean0/32/6932_2.png) [@publicocean0](https://internals.rust-lang.org/u/publicocean0)
#### Post date: [June 14, 2020, 11:42pm UTC](https://internals.rust-lang.org/t/solid-reflection-in-rust/12550/20 "2020-06-14T23:42:30Z")

</div>

It add extra info in struct data permitting to read metadata associated to struct at runtime. The final result is that you can make reflection at runtime the data struct. But code generation is more complex to do in rust, you have to pass trough the llvm, anyway it is possible . The instrumentation is the most complex task to do in rust. There are 2 ways or implementing a runtime bytecode engine or a online engine similar to macro engine but a lot more powerful than the current does

---

<div class="post-metadata">

### Author: ![schungx](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/schungx/32/5926_2.png) [@schungx](https://internals.rust-lang.org/u/schungx)
#### Post date: [June 15, 2020, 3:02am UTC](https://internals.rust-lang.org/t/solid-reflection-in-rust/12550/21 "2020-06-15T03:02:28Z")

</div>

For a person who wrote a _LOT_ of C#, I understand perfectly what you're asking. However, Rust is different enough from C#/Java that what you're looking for may not make sense, and that has caused a lot of the confusion.

In my experience, reflection is commonly used to do the following:

## Dynamic instantiation

Instantiate a new object (`type` in Rust) in a late-bind manner. For example, given a text string containing the type's full path name, find the type in any loaded library/assembly, and create an instance of it, optionally choosing a constructor method and passing parameters. Notice that there is no compile-time knowledge of _what_ that class may be or whether it resides in the current program or is something that a user wrote as an add-on (usually it is the latter).

This is extremely useful for highly-configurable software (aka "enterprise" software) because you can basically extend the functionalities of the core system by 1) writing a plugin module/assembly/library, 2) load it, 3) create an object based on some text name, 4) as long as that object implements some system _interface_..., 5) hook it up to the system via said interface. The system does not even _need_ know about these extensions; it only works with _objects_ implementing a standard interface.

I believe this is reasonably covered by Rust using `dynlib` and having user types implement a standard trait. Rust cannot instantiate a type directly given its name, but it _can_ do it via a factory function that each plugin library must export. That function can, given a name, create a trait object of the required type. In fact this is how Windows's `COM` does it to allow itself to interop with C#.

## Dynamic discovery of behaviors via metadata

When faced with a type, determine what _behaviors_ it supports by examining the set of _attributes_, _methods_, _properties_ and/or _interfaces_ it supports. This set can be obtained via reflection API's. Invoke supported behaviors by calling such methods/properties/interfaces, passing parameters.

Combined with dynamic instantiation, this becomes a complete system of late-bound extensions. Again, this is extremely flexible for highly-configurable "enterprise" software.

Rust doesn't have the same concept. In fact, as mentioned, the functions in question may not even exist in the compiled binary -- they may have been inlined away. You can still achieve exactly the same thing by providing a metadata function that all external library/assembly/module must export. In fact, this is how Windows RT does it via the `wmd` files to expose its API to C# reflection, but you must be prepared to write a lot of wrappers and shims to convert a metadata call to an actual function call. Usually these are machine-generated.

## Dynamic extension of behaviors

Some languages allow extension of compiled behaviors. Most don't, though. For instance, AOP is really hard to do in C# because it is a compiled language and there is no monkey-patching; people do AOP via rewriting the MSIL instructions.

Still, some behaviors can be lazy-added. For example, "extension methods" in C# allow users to add methods to a "black-boxed" library type without knowing the internal implementation. These extension implementations have no access to the _internals_ of the type, and they are there only to _mimic_ a method. One can easily define a normal function to do exactly the same thing, but you can't build a "fluent" API via function calls, can you?

However, you'll find that Rust actually supports extension methods in a major way -- in fact, _all_ of Rust's type methods are actually "extension methods" in the C# manner. It is so powerful that Rust actually has to manually _prohibit_ users from doing it (i.e. the rule that you cannot extend a type with a trait both not defined in the same crate); and it also has to disallow users from `impl`-ing a type that is not defined in the same crate.

This restriction in functionality is to prevent exactly the same issues plaguing C#'s extension methods -- when the library updates with new methods, it breaks user code due to method conflicts. Rust has a simple way to get around this: the newtype pattern.

## Dependency injection

All that easy reflection power combines to give us DI containers and IOC systems, very popular among highly-configurable enterprise software.

[Next page](https://internals.rust-lang.org/t/solid-reflection-in-rust/12550.md?page=2)
