Recent

Author Topic: [SOLVED] Issue with precedence of a duplicate identifier in 2 different Units  (Read 3525 times)

Hartmut

  • Hero Member
  • *****
  • Posts: 1028
I have a duplicate identifier in 2 different Units, but the Compiler and the Code Tools use a different precedence. Example:
Code: Pascal  [Select][+][-]
  1. unit U1;
  2.  
  3. interface
  4.  
  5. uses ...
  6.  
  7. const Elements = 5;
  8.  
  9. implementation
  10.  
  11. uses U2; {has 'const Elements = 6'}
  12.  
  13. writeln(Elements); // output is '5'
  14.  
Code: Pascal  [Select][+][-]
  1. unit U2;
  2.  
  3. interface
  4.  
  5. uses ...
  6.  
  7. const Elements = 6;

I always thought, that the last definition wins. So writeln() should output '6', because Unit 'U2' is used at last. But:
 - the Compiler (Lazarus 3.4.0 with FPC 3.2.2) obviously uses 'const Elements = 5'
 - the Code Tools (same Lazarus+FPC version) show over the writeln-command "const Elements = 6 in U2".
Same behavior with Lazarus 3.9.9 and FPC 3.3.1 (about 1 year old).

The only documentation which I found in a reliable time is https://wiki.freepascal.org/Unit#Unit_precedence and https://www.freepascal.org/docs-html/ref/refsu102.html but both use an example, where the local definition is made after the uses-clause, while my local definition is made before the uses-clause.

Because the Compiler and the Code Tools use a different precedence, one of them must be wrong. How can I find out, whether the Compiler behavior is correct?
« Last Edit: September 30, 2025, 10:26:56 am by Hartmut »

Thaddy

  • Hero Member
  • *****
  • Posts: 18490
  • Here stood a man who saw the Elbe and jumped it.
Re: Issue with precedence of a duplicate identifier in 2 different Units
« Reply #1 on: September 26, 2025, 02:07:39 pm »
Code tools is wrong. period.
How else would the compiler work?
Due to censorship, I changed this to "Nelly the Elephant". Keeps the message clear.

440bx

  • Hero Member
  • *****
  • Posts: 5886
Re: Issue with precedence of a duplicate identifier in 2 different Units
« Reply #2 on: September 26, 2025, 02:08:20 pm »
I realize you abbreviated U1 and U2 for convenience but, to replicate the problem exactly as you see it, it would be useful to have compilable code.

IOW, provide a complete U1, U2 and program showing the problem.  That will allow others to see the problem occur.


FPC v3.2.2 and Lazarus v4.0rc3 on Windows 7 SP1 64bit.

Thaddy

  • Hero Member
  • *****
  • Posts: 18490
  • Here stood a man who saw the Elbe and jumped it.
Re: Issue with precedence of a duplicate identifier in 2 different Units
« Reply #3 on: September 26, 2025, 02:10:20 pm »
The solution is easy, btw: specify the unit name from what you expect, e.g: system.assign(). That will work in code tools.
The only authorative source for precedence is the compiler, not Code tools.
Due to censorship, I changed this to "Nelly the Elephant". Keeps the message clear.

Hartmut

  • Hero Member
  • *****
  • Posts: 1028
Re: Issue with precedence of a duplicate identifier in 2 different Units
« Reply #4 on: September 26, 2025, 02:41:08 pm »
I realize you abbreviated U1 and U2 for convenience but, to replicate the problem exactly as you see it, it would be useful to have compilable code.

IOW, provide a complete U1, U2 and program showing the problem.  That will allow others to see the problem occur.

I attached a compilable project.

440bx

  • Hero Member
  • *****
  • Posts: 5886
Re: Issue with precedence of a duplicate identifier in 2 different Units
« Reply #5 on: September 26, 2025, 03:45:53 pm »
IMO, you found a bug.

Unit U2 is the innermost scope and, as a result the identifiers in it should be the first ones to be found, therefore the value of Elements should be 6.

Codetools is doing it correctly, it finds the innermost definition which is declared with a value of 6.

What's stated above is strict and correct theory.  I've seen other cases where FPC gets "creative" with scope resolution, this may be one of those cases but, strictly speaking, the value written out should be 6, not 5.


ETA:

Correction: there is no bug.  Just a sufficiently subtle situation that can easily be confused with a bug.


« Last Edit: September 26, 2025, 09:34:31 pm by 440bx »
FPC v3.2.2 and Lazarus v4.0rc3 on Windows 7 SP1 64bit.

Hartmut

  • Hero Member
  • *****
  • Posts: 1028
Re: Issue with precedence of a duplicate identifier in 2 different Units
« Reply #6 on: September 26, 2025, 04:29:02 pm »
IMO, you found a bug.
I agree, that applying the documentation strictly, the Compiler does wrong. But if this would be a Compiler bug, I would be surprised, that it was not found earlier (FPC 3.0.4 behaves the same). If it is not a Compiler bug, the documentation necessarily must be improved.

I hope that one of the developers, e.g. @PascalDragon finds this Topic and can give a reliable answer.

Thaddy

  • Hero Member
  • *****
  • Posts: 18490
  • Here stood a man who saw the Elbe and jumped it.
Re: Issue with precedence of a duplicate identifier in 2 different Units
« Reply #7 on: September 26, 2025, 05:36:48 pm »
There is some reference to a "bug"  ( I reported it ;) )where people sort the uses clause- which is wrong!- with code tools. There is no warning for that in Lazarus prior to 3.6 but it is fixed later, certainly in Lazarus 4.0 and trying to sort it now gives an explicit warning. Also check if the units have an initialization section. That can run havoc if the order is wrong.
If the compiler would be wrong, it would have been found a long time ago.
Just prefix the offending construct with the unit name will solve it in all cases.
« Last Edit: September 26, 2025, 05:42:04 pm by Thaddy »
Due to censorship, I changed this to "Nelly the Elephant". Keeps the message clear.

440bx

  • Hero Member
  • *****
  • Posts: 5886
Re: Issue with precedence of a duplicate identifier in 2 different Units
« Reply #8 on: September 26, 2025, 05:51:33 pm »
Just prefix the offending construct with the unit name will solve it in all cases.
One of the many points of scoping rules is to not need superfluous prefixes.

The innermost scope states that the value of the Elements constant is 6, therefore that's the value the compiler should see and use. 

There are bugs that take years to find sometimes because the feature that triggers it isn't used much, sometimes because people didn't pay attention and just went along with whatever the compiler did and, quite often, because the programmer believes that if the compiler did it that way then it must be right (does that last one sound familiar to you ?)

hmmm... and that's not the worst part... which I won't even mention.
FPC v3.2.2 and Lazarus v4.0rc3 on Windows 7 SP1 64bit.

paweld

  • Hero Member
  • *****
  • Posts: 1516
Re: Issue with precedence of a duplicate identifier in 2 different Units
« Reply #9 on: September 26, 2025, 06:08:07 pm »
In my opinion, the compiler's behavior is correct, i.e., the value 5 should be returned, because the structures (consts / functions / procedures etc.) in the current unit should take precedence.
The order of the units would matter if you used
Code: Pascal  [Select][+][-]
  1. WriteLn(Elements);
in the duplicat unit.
As @Thaddy wrote, the error is in CodeTools.
Best regards / Pozdrawiam
paweld

Martin_fr

  • Administrator
  • Hero Member
  • *
  • Posts: 11903
  • Debugger - SynEdit - and more
    • wiki
Re: Issue with precedence of a duplicate identifier in 2 different Units
« Reply #10 on: September 26, 2025, 06:13:57 pm »
https://www.freepascal.org/docs-html/ref/refsu102.html

Quote
All identifiers in the interface part of a unit are valid from the point of declaration, until the end of the unit.

This may, or may not mean to cover what you try (really to vague to be able to say if it does).

They are valid to the end of the unit. And as your can test, if you try to declare the same ident again (within that unit), then you get an error (not speaking about locals, or nested in classes, that is a different scope).

EDIT: Which would mean, that if anything: If declaration in another unit would try redeclaration, then that should give an error too.

Further:
Quote
The rules of unit scope imply that an identifier of a unit can be redefined. To have access to an identifier of another unit that was redeclared in the current unit,
The page only speaks about "redefining" an identifier that was declared in another unit. (The wording could be better, as you need to read the 2nd sentence to gain that clarity).

It does not speak of that you can (in any way) redeclare any identifier within the unit in which it was declared. Of course it also doesn't state that you can't (but if it was a feature then it should).



So I would say that the observed compiler behaviour is likely as wanted by design.

If indeed so, then the documentation should probably say, that declaring an identifier, will also redeclare (override) definitions from uses still to come.
« Last Edit: September 26, 2025, 06:23:08 pm by Martin_fr »

440bx

  • Hero Member
  • *****
  • Posts: 5886
Re: Issue with precedence of a duplicate identifier in 2 different Units
« Reply #11 on: September 26, 2025, 06:30:25 pm »
The last declaration should _always_ take precedence, no exceptions.

That means that the value of Elements should be 6 because that's the "newest" value and, as such, it masks any other declarations.

Of course, that's how it _should_ work, which apparently codetools knows.

FPC v3.2.2 and Lazarus v4.0rc3 on Windows 7 SP1 64bit.

Thaddy

  • Hero Member
  • *****
  • Posts: 18490
  • Here stood a man who saw the Elbe and jumped it.
Re: Issue with precedence of a duplicate identifier in 2 different Units
« Reply #12 on: September 26, 2025, 06:31:56 pm »
One of the many points of scoping rules is to not need superfluous prefixes.
Indeed, but the "fix" is unobtrusive in most cases. The code tools parser is - I believe - based on the very old TmwParser and in recent days I ran into trouble with it - based on Castalia version, but already heavily modified - and had to specify some unit prefixes while adapting it to newer Delphi versions than VER200.
Quicker fix than analysing the uses clause for 4 fixes.
Why do you insist the compiler is wrong? It isn't. Code tools is wrong.
« Last Edit: September 26, 2025, 06:36:14 pm by Thaddy »
Due to censorship, I changed this to "Nelly the Elephant". Keeps the message clear.

Hartmut

  • Hero Member
  • *****
  • Posts: 1028
Re: Issue with precedence of a duplicate identifier in 2 different Units
« Reply #13 on: September 26, 2025, 06:52:46 pm »
There is some reference to a "bug"  ( I reported it ;) )where people sort the uses clause- which is wrong!- with code tools. There is no warning for that in Lazarus prior to 3.6 but it is fixed later, certainly in Lazarus 4.0 and trying to sort it now gives an explicit warning. Also check if the units have an initialization section. That can run havoc if the order is wrong.
I don't understand what this has to do with this Topic. And writing that you reported a bug does not help us without posting it's link. ;)

Quote
Just prefix the offending construct with the unit name will solve it in all cases.
This Topic is about to clarify, whether this is a Compiler bug and not about searching workarounds - in which case it would be much easier to move line 'uses U2;' from the implementation- up to the interface-section.



Quote
All identifiers in the interface part of a unit are valid from the point of declaration, until the end of the unit.
This may, or may not mean to cover what you try (really to vague to be able to say if it does).
I agree, that it is possible to interpret this that way. But a documentation should be clear and unambiguous.

Quote
So I would say that the observed compiler behaviour is likely as wanted by design.

If indeed so, then the documentation should probably say, that declaring an identifier, will also redeclare (override) definitions from uses still to come.

I think we need someone from the developers, e.g. @PascalDragon to get a reliable answer - we can only speculate and won't get a reliable result which makes no sense.

Thausand

  • Sr. Member
  • ****
  • Posts: 441
Re: Issue with precedence of a duplicate identifier in 2 different Units
« Reply #14 on: September 26, 2025, 07:15:10 pm »
The last declaration should _always_ take precedence, no exceptions.
Only have precedence when scope same. When scope not same then scope have priority rule.

 

TinyPortal © 2005-2018