Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does Rust store types at runtime?

Tags:

types

memory

rust

A u32 takes 4 bytes of memory, a String takes 3 pointer-sized integers (for location, size, and reserved space) on the stack, plus some amount on the heap.

This to me implies that Rust doesn't know, when the code is executed, what type is stored at a particular location, because that knowledge would require more memory.

But at the same time, does it not need to know what type is stored at 0xfa3d2f10, in order to be able to interpret the bytes at that location? For example, to know that the next bytes form the spec of a String on the heap?

like image 467
joel Avatar asked Jan 01 '23 15:01

joel


1 Answers

How does Rust store types at runtime?

It doesn't, generally.

Rust doesn't know, when the code is executed, what type is stored at a particular location

Correct.

does it not need to know what type is stored

No, the bytes in memory should be correct, and the rest of the code assumes as much. The offsets of fields in a struct are baked-in to the generated machine code.

When does Rust store something like type information?

When performing dynamic dispatch, a fat pointer is used. This is composed of a pointer to the data and a pointer to a vtable, a collection of functions that make up the interface in question. The vtable could be considered a representation of the type, but it doesn't have a lot of the information that you might think goes into "a type" (unless the trait requires it). Dynamic dispatch isn't super common in Rust as most people prefer static dispatch when it's possible, but both techniques have their benefits.

There's also concepts like TypeId, which can represent one specific type, but only of a subset of types. It also doesn't provide much capability besides "are these the same type or not".

Isn't this all terribly brittle?

Yes, it can be, which is one of the things that makes Rust so interesting.

In a language like C or C++, there's not much that safeguards the programmer from making dumb mistakes that go out and mess up those bytes floating around in memory. Making those mistakes is what leads to bugs due to memory safety. Instead of interpreting your password as a password, it's interpreted as your username and printed out to an attacker (oops!)

Rust provides safeguards against that in the form of a strong type system and tools like the borrow checker, but still all done at compile time. Unsafe Rust enables these dangerous tools with the tradeoff that the programmer is now expected to uphold all the guarantees themselves, much like if they were writing C or C++ again.

See also:

  • When does type binding happen in Rust?
  • How does Rust implement reflection?
  • How do I print the type of a variable in Rust?
  • How to introspect all available methods and members of a Rust type?
like image 90
Shepmaster Avatar answered Jan 19 '23 01:01

Shepmaster