The compiler will not do any verification when you use typecasts. Try:
Of course it does, not between Pointer and classes, but for other types:
var
p: Integer = 42;
sl:TStringList;
c: Integer;
begin
sl:=TStringList(p);
c:=sl.Count;
WriteLn('c: ',c);
As I said, programs are constantly evolving. Most bugs are not introduced because someone made a mistake while programming a function, most bugs are introduced when rolling out updates that change the behavior of the code such that the assumptions in some parts of the code do not hold anymore (was the result of some research papers, but I couldn't find then on the fly right now).
Sure you can create such a function now and this is perfectly fine, but if in 2 years from now, you or maybe a completely different developer changes this function signature without changing the function body.
This doesn't even need to be in a single step, for example in one update someone might think that for documentation purposes it is probably better to use a custom type name rather than pointer:
type
TMyObjectReference = Pointer;
function SortByIndex(Item1, Item2: TMyObjectReference): integer;
//Asume that Tmyobject has a property Val which is integer.
var o1 : TMyObject absolute Item1;
o2 : TMyObject absolute Item2;
begin
Result := o1.Val - o2.Val;
end;
Then some time down the line one thinks, hey, I want to use a caching mechanism and builds the following. At this point in most of the code where TMyObjectReference is used, typecasts are used and the developer completely forgott (or is new to the project and doesn't know) about this one function that uses absolute, so they do this:
type
TMyObjectReference = type LongInt;
var
MyObjectCache: specialize TDictionary<TMyObjectReference, TMyObject>;
operator := (ARef: TMyObjectReference): TMyObject;
begin
Result := MyObjectCache[ARef];
end;
This works completely fine in the test cases, which happen to not cover SortByIndex, because some developer was lazy and didn't create a unit test, and is pushed to the master branch and deployed to the customers, for whom then the application starts crashing left and right.
Long story short, if you use absolute, you basically are freezing the type structure as the way it is. If someone new doesn't know about this restriction, or forgets about it, it can easiely result in bugs without any warnings by the compiler.
This can also be a problem without overloading the casting operator. Because if someone wants to change the type of parameter, the easiest way, rather then searching every occurance, is to simply change it and let the compiler figure out where you need to apply changes (this is usually the way I go about when switching up types). With absolute it doesn't generate a compiler error but silently fails and results in invalid data accesses