In XE2 and later, for reasons of backward compatibility I guess, you can get away with not using fully qualified unit scope names for the RTL/VCL etc if you add the required prefixes to project options (Delphi Compiler section, Unit scope names field). Certain default prefixes are added by Delphi when you create a new project. For a new VCL application in Delphi 12.2 I get:
Winapi;System.Win;Data.Win;Datasnap.Win;Web.Win;Soap.Win;Xml.Win;Bde;System;Xml;Data;Datasnap;Web;Soap;Vcl;Vcl.Imaging;Vcl.Touch;Vcl.Samples;Vcl.Shell
That's probably why the "mixed" code works, but it's asking for trouble IMHO.
I worry about possible conflicts using default unit scope names, so I usually delete all the default prefixes from project options, which enforces the use of fully qualified scope names.
In library code that needs to compile with compilers either side of XE2, where it can't be guaranteed that the user will have any default unit scopes defined, I use something like:
{$UNDEF RequiresUnitScopeNames}
{$IFDEF CONDITIONALEXPRESSIONS}
{$IF CompilerVersion >= 24.0} // Delphi XE3 and later
{$LEGACYIFEND ON} // NOTE: this must come before all $IFEND directives
{$IFEND}
{$IF CompilerVersion >= 23.0} // Delphi XE2 and later
{$DEFINE RequiresUnitScopeNames}
{$IFEND}
{$ENDIF}
then in uses statements, for e.g.:
uses
{$IFNDEF RequiresUnitScopeNames}
Windows,
Classes;
{$ELSE}
Winapi.Windows,
System.Classes;
{$ENDIF}
It's a pain, and it's easy to forget to add both versions of a unit name, but it works for me.
BTW the $LEGACYIFEND stuff is a work around for problems I encountered with the way $IFEND and $ENDIF work in XE3 and later! Your mileage may vary.