View Issue Details

IDProjectCategoryView StatusLast Update
0038363FPCCompilerpublic2021-01-17 17:26
ReporterBart Broersma Assigned To 
PrioritynormalSeverityminorReproducibilityalways
Status newResolutionopen 
Platformi386OSWindows 
Product Version3.3.1 
Summary0038363: Private fields of a generic class are accessible by specilized class.
DescriptionYou can access private fields of a generic class in the class that you specialized.

Steps To Reproduce
    unit foo;
     
    {$mode objfpc}{$H+}
     
    interface
     
    uses
      Classes, SysUtils;
     
    type
     
      { TFoo }
     
      TFoo = class
      private
        PrivateVar: String;
      end;
     
     
      type
        generic TBar<T>=class
        private
          PrivateVar:T;
      end;
     
      TBarInt = specialize TBar<Integer>;
     
    implementation
     
    end.



    program vis;
     
    {$mode objfpc}
    {$h+}
     
    uses foo;
     
    type
      TBarChar = class (specialize TBar<Char>);
      TFooChild = class(TFoo);
     
    var
      AFoo: TFoo;
      AFooChild: TFooChild;
      ABarChar: TBarChar;
      ABarInt: TBarInt;
     
     
    begin
      ABarChar.PrivateVar := 'A'; //compiles (to my surprise: why?)
      ABarInt.PrivateVar := 1; //vis.lpr(21,11) Error: identifier idents no member "PrivateVar" (if the above is allowed, why not this?)
      AFooChild.PrivateVar := ''; //vis.lpr(22,13) Error: identifier idents no member "PrivateVar" (as expected)
      AFoo.PrivateVar := ''; //vis.lpr(23,8) Error: identifier idents no member "PrivateVar" (as expected)
    end.
Additional InformationSee: https://forum.lazarus.freepascal.org/index.php/topic,52883.0.html
I was asked to report it here.
Tagsgenerics
Fixed in Revision
FPCOldBugId
FPCTarget
Attached Files

Activities

Bart Broersma

2021-01-16 17:41

reporter   ~0128370

Attached test case.
Please delete the contents of "Steps to reproduce", I only saw the extra line-endings once I posted.
vis.zip (960 bytes)

jamie philbrook

2021-01-16 18:00

reporter   ~0128372

So why is this any different than creating a class without using generics in the same unit, you get visibility like you would otherwise ?

I am not a generic lover myself due to how it uses resources (duplicates currently) But it is basically a template generation system and thus what ever unit you happen to specialize it in will be the same as if you manually created the class within the same unit, regardless where the declaration of the GENERIC is.

 I believe I have a pretty good understanding on the general GENERIC system which is most likely why I tried to avoid it.

Sven Barth

2021-01-17 17:25

manager   ~0128390

@jamie: Because the compiler is free to reuse a specialization from another unit if it's in scope to avoid duplication of binary code. This would lead to access to private fields failing to compile in some times depending on the units in the uses list. Delphi does not allow this either. The point is that the generic is part of the unit its declared in and thus the visibility rules of that unit need to be applied.

Issue History

Date Modified Username Field Change
2021-01-16 17:39 Bart Broersma New Issue
2021-01-16 17:41 Bart Broersma Note Added: 0128370
2021-01-16 17:41 Bart Broersma File Added: vis.zip
2021-01-16 18:00 jamie philbrook Note Added: 0128372
2021-01-17 17:25 Sven Barth Note Added: 0128390
2021-01-17 17:26 Sven Barth Tag Attached: generics