Why cant't the compile stop when it detects a circular unit reference
It can. A circular reference throws a warning. Warnings can be treated as errors: compile with -Sew and the compiler stops.
Note that I already explained that the type of circular references you refer to is always solvable with a little effort. Provide us with a little example project that fails to compile and I will solve it. If I create one that I *think* is what you mean I might otherwise be on the wrong track,,,
and handle things like forward declarations?
It is lacking information at that point. The warning is to give feedback to the programmer that he/she may have to perform further actions. As far as the compiler is concerned, the behavior is undefined.
The compiler says,
"Oh, you notified me (e.g. by a forward declaration) that YOU will resolve this later by providing me with the complete information I need. Be careful, I will continue, but it is YOUR fault if something goes wrong later on....". The compiler can't second guess you and certainly not add missing code by inserting forward declarations itself.
Would be a DWIM compiler: highly desirable, but Utopia. Circular reference is literary chicken and egg.
Note that even a multi-pass compiler can not solve this issue logically without programmer intervention with language constructs like forward declarations when there are conflicts. Although I am quite sure I have to respond to some nitwits that want proof of that or "know better".
Just write an example project. It does not have to do anything, but show us WHERE you still have issues. I can solve it quickly, but put in some effort.