You are covering a lot of ground here.
I'll try to address each part.
First, I'll note that if you require the compiler to have a hook for when control leaves a function to delete a vector, you might as well make it general. There are a lot of things that can be "freed" when control leaves a function, not just memory. You can close files, sockets, shared memory etc. C++;s RAII idiom is based on this and Go uses a more explicit method of doing this with its defer construct. I am more of a fan of RAII than defer simply because defer can get forgotten whereas RAII is baked into the code when you declare your variable.
Data lifetime and the function call hierarchy are not necessarily the same. Data tends to fall into three main buckets: ephemeral within one function, data only passed down to sub-functions that do operations on it, or data that is built in a function and intended to be returned upward. For the latter, think of a function that builds a tree node. As far as I can tell, your vectors only cover the first two of these cases. How do you turn it off so that functions can construct data and return it to the caller?
Vectors and Blocks
If I understand correctly, vectors are resizable and blocks are not. Other than that, they are intended to be used more or less the same way? If so, why the difference? The memory in question is allocated out of the heap in both cases. If you allow resizing to reallocate, you can merge the two back into one construct. The fewer things the better.
The for..range loop is not possible without either significant other infrastructure and conventions (C++) or limited application (just arrays). From what you are doing here, it seems like it might be easier just to drop C's pointers-are-arrays (except when they are not) approach. Either disallow pointer arithmetic or minimize it and make arrays carry their sizes with them. This may be another area for simplification: If you use an array, that means you want bounds checking. If you use a pointer, you do not.
You bring some interesting ideas to the table, but I think it might make sense to strip them down into the more basic parts possible and see how those can be combined to build what you want.
- Automatic freeing: generalize this to some sort of on-function-exit hook. That is very powerful and you can do a lot with it. C.f. C++'s RAII and Go's defer.
- Vectors/blocks: simplify to arrays having bounds. The for..range construct only works with arrays. Arrays could be resizeable and assignable independent of this. I would make a much more clear separation between pointers and arrays.
- slices. These are generally good and can be implemented as arrays with shared data parts (though you need to watch the lifetimes!)
Side Effects
Removing globals does not make functions pure. Think about passing an address around (a pointer). I pass the value of the pointer around, but each function that gets it can dereference the pointer to look at the value in memory. So, I just made it a little bit harder to have globals, but I did not really remove them.
I think that memory safety is definitely something interesting. There are so many security exploits that rely on buffer overflows, bad pointer arithmetic etc.