I want to remove explicit addressing from my type system.
In low level languages like C or Rust, you always have a choice whether to store some data by value or by reference. There are some advantages to each:
|Space can be reserved at compile time, no memory allocations needed
|Fast to pass regardless of size
|Better cache consistency
|Allows recursive, potentially infinitely sized, data structures
|Always needs to be at least as large as the largest potential size
|Allows dynamic size
|...many more subtle differences
There is an issue with this: Determining which is more efficient depends on a dozen factors and is hard for a programmer to determine. Even if one option is better for the moment it could change, but it's hard to make changes to the type of things.
There is also a matter of philosophy. I view the type system as describing the relationships between data and the set of valid states. How an object is stored should not be part of that; it's just noise.
Many object oriented languages solve this by only ever storing pointers. This works, but is not always the most efficient. It leads to many very small memory allocations, which is slow and hurts cache consistency. I don't need inheritance-based polymorphism. One exception is C# which allows declaring at the type, instead of at the declaration level whether the type should be stored by value or by reference, which is still not ideal.
So here is my question: If I have a type declaration without any explicit indicators for how memory should be managed, how do I determine if it is more efficient to store a specific attribute by value or by reference? Ideally it would work for any kind of place data is stored or transferred, like a local variable, function argument, field of a different type etc.
If no exact answers exist, at least some heuristics would be nice.