Actually the problem is deeper than this. You can't have type safety w/o memory safety, and it has nothing to do with casting.
Here's an example. You allocate a chunk of memory as type Foo. You use it as Foo. You hand out references to Foo. Everyone is happy. Then someone says, "We don't need this instance of Foo anymore" and deletes it. Someone later comes and allocates Bar and the memory allocator correctly goes and grabs some of Foo's old memory and uses it for Bar.
All good, right? Well, except there's this other thread that is using a reference to that old instance of Foo. Suddenly you have a type safety issue at hand.
Now you can say, "Don't write programs with bugs". And indeed that is just about the only alternative.
My claim is that well designed C++ programs do not have calls to delete at all, not just ones that cause bugs: you come up with your memory abstraction, you build that part of the system (it is likely that this code will have a single call to delete in it), and then your actual program relies on that as a "runtime": if the code in that area calls "delete", you do not allow that code, and treat it as a build failure.
I have been responsible for projects with on the order of hundreds of thousands of line of C++ (such as for a video game we were developing), and the only calls to "delete" were in the stack-locked reference counting implementation I designed, and a few optimized containers. It isn't even hard to think like this in a language like C++, and isn't highly different than a language like Haskell (you build abstractions from unsafePerformIO: you don't routinely code with it).
No; the pointer-to-Foo will always point to the original Foo (unless it's reassigned). The point of the example is to show that type safety depends on not having access explicit heap management.
You're more likely to get silent data corruption without memory safety, than with it.
It has nothing to do with Java specifically, FWIW. Ruby, Python, shell script, C#, Haskell, they are all memory safe. It's a big church.
I don't know if you're being deliberately obtuse. At the semantic level of a memory safe language, there never is any memory reuse, because memory isn't a resource like that. It is impossible to observe memory being reused from within the language. In fact, you could use that as a kind of definition of memory safety. It cuts off a whole kind of memory corruption bug, makes it impossible (aside from bugs in the language and / or runtime, of course).
I'm just going to have to throw up my hands here. The masses on HN are apparently proudly ignorant, and unwilling to learn even the slightest thing before wading in.
It's not completely different from type safety. You're right, they're not the same thing, but GCs prevent a common form of type safety violation. With that said there are other techniques that exist that are orthogonal to GC.
At the same time there are problems, like lack of bounds checking, which can result in type safety issues.
My point isn't that you need a GC per se, but you do need memory safety. GCs happen to be one of the most prevalent ways to achieve it. Someone else in this thread noted that they build a complete runtime that guaratees memory safety and requires their devs to code against that runtime. That's fine too (although I think a lot less common than that poster might lead one to believe). It's almost like the memory safe subset of other popular existing runtimes.
Ok, enlighten me: Assuming you don't have an infinite amount of RAM how do you avoid running out of memory without doing at least one of garbage collection or explicit memory deallocation?
Here's an example. You allocate a chunk of memory as type Foo. You use it as Foo. You hand out references to Foo. Everyone is happy. Then someone says, "We don't need this instance of Foo anymore" and deletes it. Someone later comes and allocates Bar and the memory allocator correctly goes and grabs some of Foo's old memory and uses it for Bar.
All good, right? Well, except there's this other thread that is using a reference to that old instance of Foo. Suddenly you have a type safety issue at hand.
Now you can say, "Don't write programs with bugs". And indeed that is just about the only alternative.