> Rusts approach, I think, is in the entirely wrong direction. You should only have one kind of reference, but if you use it correctly the compiler should figure out how to free it.
This has been an area of intense research for four or five decades now, and it's probably not going to get better than what we have now, in the general case. In the presence of general recursive data structures, the compiler can't know when each object is going to die. I'm pretty sure you can easily reduce this to the halting problem.
To date, you've had three sorts of solutions: 1) explicit malloc/free; 2) tracing GC or reference counting + various tricks to take advantage of special cases; and 3) putting additional information in the type system to help the compiler infer when objects might become free while preserving memory safety (this is the direction taken by Rust, Cyclone, MLKit, and to an extent C++ too).
I think if your code does use references in a way that does not let you guarantee memory safety without an extremely convoluted type system, you should perhaps just be using GC.
For most code I personally know, that does not play well with GC (firmware, hard real-time, etc.), you really don't want to do much allocation after initialization anyway, and the little you do can be handled by malloc/free style manual memory management, or perhaps by escape analysis. And then I think Nimrods approach might work well, because you could declare that everything done by a proc should be verified by escape analysis, rather than manually tagging each pointer used in that procedure.
But I recognize that Rusts approach should be extremely useful in a few applications. But then again I wonder if Nimrods type-system eventually will be able to implement its most useful pointer types in a library.
> So what you have is various approaches to take advantage of special cases (different forms of GC), or approaches that give the compiler more information (as in C or C++, and Rust or Cyclone or MLKit).
Pretty much. I'd also add ParaSail to the list of languages that give the compiler more information (or more precisely, restricts what is possible, and for reasons other than just memory management).
This has been an area of intense research for four or five decades now, and it's probably not going to get better than what we have now, in the general case. In the presence of general recursive data structures, the compiler can't know when each object is going to die. I'm pretty sure you can easily reduce this to the halting problem.
To date, you've had three sorts of solutions: 1) explicit malloc/free; 2) tracing GC or reference counting + various tricks to take advantage of special cases; and 3) putting additional information in the type system to help the compiler infer when objects might become free while preserving memory safety (this is the direction taken by Rust, Cyclone, MLKit, and to an extent C++ too).