In any case, in the following code, the compiler clearly goes: "scope first". And not "last first".
It prints out: 3
I think this is a different case. 'const BAR = 3' is inside a class, which could be seen similar to the mechanism of a local const inside a procedure, which has precedence over a global const with the same name.
A local var is always going to be the "last by order" too. Try to write some code, where there is a global declaration between the local declaration and the local code body.
Yet, yes, I agree, I think a local declaration takes precedence due to scoping, not due to ordering. => And yet, I have not searched if I can find that documented.
Duplicate identifiers in the *exact* same scope are usually not allowed (I can't think of a case where they would be / apart from modeswitches for fields vs local - but those are diff scopes anyway).
Then (and again, not checked for docs)
all resolution should be by scope, and by scope only, and never ever by "order of appearance". (Only: certain scopes can depend on some "order"...)
Units are scopes too.
Used units are a different scope than the current unit. And each used unit has a scope of its own (and those scopes are ordered by the reverse order in which those units are listed in uses).
The entire issue arises because
https://www.freepascal.org/docs-html/ref/refsu102.html says
that an identifier of a unit can be redefined
(Leaving aside that the entire help pages uses "unit" without much clarification for the "used unit" and the "current unit"....)
The problem is that it says "
redefined". =>
IMHO that is plain wrong.Uses UnitA;
{ Redeclaration of MyType}
Type MyType = Integer;
- The Identifier "UnitA.MyType" is never "redeclared". It stays as it is.
- A new identifier "{prog.}MyType" is declared. And it hides the existing identifier.
But anyway, even then it should be pointed out that the scoping rules apply independent of the order of the "uses" vs the current-unit "type MyType =".
Well, scopes do/should not depend on their content. The scope of a "unit" or "program" is always the same, and affects anything that is inside it.
Of course embedded/nested scopes (e.g. class) may take precedence. And a "class" adds its parent as a scope, that takes precedence over the "unit", even if it comes from another unit.
But a "uses" clause, does not give precedence to the scope of the used units. If it did, then that precedence would be "global", i.e. visible in the entire "unit" in which the uses occurs, even before the uses.
So "uses" clauses have a curiosity regarding scoping.We can not simply say, each used unit is added as a new scope (with the last having the highest prior). At least not to the entire using unit.
"uses" in interface are adding scopes visible to the entire using unit.
But "uses" in implementation add scopes only visible to the implementation section. So, does that mean the implementation section is treated as a separate scope? (however sharing uniqueness for identifier names with the interface section / like locals vs fields?)
Or is that just an effect that within a scope, there is no (or limited) forward visibility? But then "uses" would add scopes limited by forward visibility (that differs from order of declaration, because once visible scoping follows scoping rules, not ordering / see class inheritance / also direct interface content still comes before implementation uses and that would be scoping rule over ordering)
Anyway, all that said, it does not replace the missing (or missing clarity?) documentation.