Live data from Hacker News

Native Reflection in Rust

jack.wrenn.fyi

61–68 of 68 posts

Re: Native Reflection in Rust

#61
post #33
post #5

Earlier quoted context omitted.

Reflection is usually not available in AoT compiled languages. The prevalent Rust coding styles rely heavily on monomorphic data types and functions, meaning there's nothing left to reflect at runtime. But if you want to deal with trait objects and need to access the underlying type, you need to use Any::downcast or rely on annotations on every type you want to reflect on. Or now, leverage DWARF info on Linux with de…

That's runtime reflection. Compile time reflection AFAIK is available in D and Zig, and is planned for C++.

"Compile time reflection" is an inconsistent and nonstandard concept; originally it seemed to just mean typeclasses for people who hadn't heard of typeclasses.

Re: Native Reflection in Rust

#62
post #33

Earlier quoted context omitted.

That's runtime reflection. Compile time reflection AFAIK is available in D and Zig, and is planned for C++.

Yup. I consider runtime reflection an antifeature, which has negative performance effects, is unsafe (see e.g. log4j) and leads to fragile code. I would however welcome static reflection with open arms. In Rust in particular, I’d prefer it if derive was implemented using static reflection, rather than proc macros.

Derive or equivalent ought to be something you can implement on top of frunk (so you're ultimately still depending on a proc macro, but the whole ecosystem only needs to depend on that one macro, and tools etc. can build in support for it) - that's how it's usually done in Scala.

Re: Native Reflection in Rust

#63
post #30

"When you call .reflect on a dyn Reflect value, deflect figures out its concrete type in four steps:" * invokes local_type_id to get the memory address of your value’s static implementation of local_type_id * maps that memory address to an offset in your application’s binary * searches your application’s debug info for the entry describing the function at that offset * parses that debugging information entry (DIE) to…

Are you saying there aren’t any legitimate uses for runtime reflection? Because I think Java and .Net, even Go have proved that wrong over the years.

This seems like a valuable library. It’s impressive that it can be so powerful in a compiled language. C and C++ are much older but don’t have anything quite like this.

Re: Native Reflection in Rust

#64
post #30

"When you call .reflect on a dyn Reflect value, deflect figures out its concrete type in four steps:" * invokes local_type_id to get the memory address of your value’s static implementation of local_type_id * maps that memory address to an offset in your application’s binary * searches your application’s debug info for the entry describing the function at that offset * parses that debugging information entry (DIE) to…

Are you saying there aren’t any legitimate uses for runtime reflection? Because I think Java and .Net, even Go have proved that wrong over the years. This seems like a valuable library. It’s impressive that it can be so powerful in a compiled language. C and C++ are much older but don’t have anything quite like this.

A lot of what you'd use reflection for in GC languages is done with macros/code generation at compile time in Rust. For example, rather than using reflection to map objects to something like JSON to serialize, Rust has a library called serde (https://serde.rs/) that lets you annotate structs and enums and generate conversions at compile time that you can use. I wouldn't go so far as saying that there's no possible legitimate use of reflection, but I do wonder how much could be happening in Java and C# and Go that's so dynamic that you wouldn't be able to reason about it in advance. I think most of what reflection is used for in those languages _could_ be done at compile time, but it would both require a way to express it (via macros, codegen, or something like that) and be worth the extra compile time in order to save runtime. Rust's ethos is to try to optimize as much as possible for runtime efficiency even at the expensive of compile time, and while there can be (and often are!) ways to opt out of this for a given feature, it's almost never the default.

Re: Native Reflection in Rust

#65
post #64

Earlier quoted context omitted.

Are you saying there aren’t any legitimate uses for runtime reflection? Because I think Java and .Net, even Go have proved that wrong over the years. This seems like a valuable library. It’s impressive that it can be so powerful in a compiled language. C and C++ are much older but don’t have anything quite like this.

A lot of what you'd use reflection for in GC languages is done with macros/code generation at compile time in Rust. For example, rather than using reflection to map objects to something like JSON to serialize, Rust has a library called serde ( https://serde.rs/ ) that lets you annotate structs and enums and generate conversions at compile time that you can use. I wouldn't go so far as saying that there's no possible…

I’ve used Rust extensively the last couple years. I understand that. A lot of what people do with reflection in Go could be done more efficiently with code generation - but more easily with reflection. I’m sure the same is true in Rust, to a lesser extent. There are times when runtime reflection would be really nice to have.

Re: Native Reflection in Rust

#66
post #61
post #33

Earlier quoted context omitted.

That's runtime reflection. Compile time reflection AFAIK is available in D and Zig, and is planned for C++.

"Compile time reflection" is an inconsistent and nonstandard concept; originally it seemed to just mean typeclasses for people who hadn't heard of typeclasses.

for weirdos who only have ad-hoc constraints instead of knowing what typeclasses are, it means that you can first say "I only have ad-hoc constraints" then say "wait wait I need to make decisions based on the specifics of the type" which may be useful for e.g. generating serializers and deserializers at compile time instead of using code generators like protobuf

Re: Native Reflection in Rust

#67
post #36

I've used very similar method, at work, to provide C++ "reflection" between my own system and a system from another team. Basically, the other system is a dynamic library which sends and receives C structures from my application. Those structures are then mapped into a buffer that is supposed to have the same size and there are pointers with metadata pointing into the buffer that are supposed to be exactly like the s…

Was the other team completely unwilling to provide a header?

Yes, they are willing, that wasn't the problem. The problem was that the consuming app on my side is historically metadata driven, and historically tries to avoid having to recompile when the interface changes. We do that by keeping the code generic and by reading the interface from a database. This leads to faster iterations. The problem rises when we have to interface with any other system which is not generic and has its interface defined in H files.

Yeah, I know, it's our problem, not theirs. It's something I cannot fix on my own without a huge effort. I've tried pushing for it for more than a decade, and at some point my wish was sort of abducted by my boss' boss as an excuse to create a DSL [0]. This did solve some huge problems but also created many others. It didn't solve that char* / h file problem since it doesn't really have an FFI.

[0] Domain specific language, custom-made for our own internal users. I've come to hate DSLs since I have to support that one, which never wanted.

Re: Native Reflection in Rust

#68
post #57
post #41

My version of Greenspun's Tenth [1] is that any sufficiently complex static language contains an adhoc, informally specified, bug ridden and slow version of a dynamic "any" type. Thx OP for providing an example. [1] https://en.wikipedia.org/wiki/Greenspun's_tenth_rule

Rust has a dynamic any type, `std::any::Any`.

The entire purpose of OPs thing is to give you a semblance of workable reflection so you can actually operate on said type. It requires byzantine hacks to read debug info and doesn't work on macOS.

I don't think you understand how people in dynamic languages use any types at all.

Post reply on HN