No, it is not a valid cast, in this case.
Obj is declared as IInterface, so it is pointing at the IInterface portion of the TMyClass object. But the object also has other portions in it, for TMyBaseClass, TInterfacedObject, IMyInterface, etc (not drawn exactly as the compiler lays it out, but you should get the idea):
-------------------
| TMyClass |
| ---------------- | <- Obj points here
| | IInterface | |
| ---------------- |
| ---------------- |
| | IMyInterface | |
| ---------------- |
| ... |
-------------------
You are type-casting Obj AS-IS from IInterface to IMyInterface, which tells the compiler to MIS-interpret Obj as pointing to the IMyInterface portion of the object EVEN-THOUGH it is actually pointing at the IInterface portion of the object. Whereas the 'as' operator and Support() function, which use QueryInterface() internally, will return a pointer that properly points to the IMyInterface portion of the object, eg:
-------------------
| TMyClass |
| ---------------- | <- IMyInterface(Obj) points here
| | IInterface | |
| ---------------- |
| ---------------- | <- (Obj as IMyInterface) points here!
| | IMyInterface | |
| ---------------- |
| ... |
-------------------
So, when you call IMyInterface(Obj).DoesNothing(), you are calling DoesNothing() on an invalid IMyInterface, so it does not access the correct area of the TMyClass object.
In order for the compiler to access the members of a TMyClass object through an IInterface pointer, an IMyInterface pointer, a TMyBaseClass pointer, etc, the pointer has to be ADJUSTED according to the offset of the pointer's dereferenced type in relation to the implementation class. The compiler knows the offset of the IInterface portion of TMyClass, so given an IInterface pointer it knows how to adjust that pointer to reach TMyClass. Same with IMyInterface, etc. Thus, it adjusts a pointer according to the pointer's DECLARED type.
So, if you start out with an invalid pointer to begin with, those adjustments are not performed correctly, and you end up with bad behaviors, such as crashes, corrupted data, etc.
That works only if SomeVariable is pointing at the memory address where a valid IWhatever exists.
Because you altered the layout of the object in memory, but didn't update your pointer usage accordingly.