Two possible generics bugs

classic Classic list List threaded Threaded
15 messages Options
Reply | Threaded
Open this post in threaded view
|

Two possible generics bugs

Free Pascal - General mailing list
Testing on 3.3.1. Are these both bugs? I wanted to ask first before filing a report.

{$mode objfpc}

program test;
uses
  FGL;

// No Error specializing TFPGList in parameter list...
generic function CopyList<T>(source: specialize TFPGList<T>): specialize TFPGList<T>;
begin
end;

// ... but getting an error specializing TFPGObjectList in parameter list
// Class type expected, but got "T"
generic function CopyList<T>(source: specialize TFPGObjectList<T>): specialize TFPGObjectList<T>;
begin
end;

begin
end.

===========================

{$mode objfpc}

program test;
uses
  FGL;

// Type identifier expected
// Internal error 2019112401
generic function CopyList<T>(source: specialize FGL.TFPGObjectList<T>): specialize FGL.TFPGObjectList<T>;
begin
end;

begin
end.


Regards,
        Ryan Joseph

_______________________________________________
fpc-pascal maillist  -  [hidden email]
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Two possible generics bugs

Free Pascal - General mailing list
Ryan Joseph via fpc-pascal <[hidden email]> schrieb am Do., 28. Nov. 2019, 20:36:
Testing on 3.3.1. Are these both bugs? I wanted to ask first before filing a report.

{$mode objfpc}

program test;
uses
  FGL;

// No Error specializing TFPGList in parameter list...
generic function CopyList<T>(source: specialize TFPGList<T>): specialize TFPGList<T>;
begin
end;

// ... but getting an error specializing TFPGObjectList in parameter list
// Class type expected, but got "T"
generic function CopyList<T>(source: specialize TFPGObjectList<T>): specialize TFPGObjectList<T>;
begin
end;

begin
end.

TFPGObjectList has a constraint to class types, so you need to constrain your T as well using ": class". 

Please note however that you'll likely encounter another bug then once you move your function to a unit: https://bugs.freepascal.org/view.php?id=35943


===========================

{$mode objfpc}

program test;
uses
  FGL;

// Type identifier expected
// Internal error 2019112401
generic function CopyList<T>(source: specialize FGL.TFPGObjectList<T>): specialize FGL.TFPGObjectList<T>;
begin
end;

begin
end.

The "specialize" is part of the generic identifier, so it must be "FGL.specialize TFPGObjectList<T>". 

That said however an internal error should not happen (especially the one I just added some days ago ^^'). Please report this one. 

Regards, 
Sven 

_______________________________________________
fpc-pascal maillist  -  [hidden email]
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Two possible generics bugs

Free Pascal - General mailing list


> On Nov 28, 2019, at 6:38 PM, Sven Barth via fpc-pascal <[hidden email]> wrote:
>
> TFPGObjectList has a constraint to class types, so you need to constrain your T as well using ": class".
>
> Please note however that you'll likely encounter another bug then once you move your function to a unit: https://bugs.freepascal.org/view.php?id=35943

A better error would be nice but I guess I can't do this anyways until the other bug is fixed.


> The "specialize" is part of the generic identifier, so it must be "FGL.specialize TFPGObjectList<T>".
>
> That said however an internal error should not happen (especially the one I just added some days ago ^^'). Please report this one.
>

That doesn't look right to my eyes but ok. I filed a report (https://bugs.freepascal.org/view.php?id=36377).


It looks like my plan was foiled so I made a non-generic attempt. Can you explain why I get the EListError at runtime? I checked the itemSize property and it's the same for both lists.

{$mode objfpc}

program test;
uses
  FGL;

type
  TNode = class (TInterfacedObject)
  end;
  TNodeObjectList = specialize TFPGInterfacedObjectList<TNode>;

function CopyList (source: TFPSList): TFPSList;
begin
  result := TFPSList(source.ClassType.Create);
  result.Assign(source);
end;

var
  a, b: TNodeObjectList;
begin
  a := TNodeObjectList.Create;
  // EListError: Incompatible item size in source list
  b := CopyList(a) as TNodeObjectList;
end.

Regards,
        Ryan Joseph

_______________________________________________
fpc-pascal maillist  -  [hidden email]
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Two possible generics bugs

Free Pascal - General mailing list
Ryan Joseph via fpc-pascal <[hidden email]> schrieb am Fr., 29. Nov. 2019, 01:11:


> On Nov 28, 2019, at 6:38 PM, Sven Barth via fpc-pascal <[hidden email]> wrote:
>
> TFPGObjectList has a constraint to class types, so you need to constrain your T as well using ": class".
>
> Please note however that you'll likely encounter another bug then once you move your function to a unit: https://bugs.freepascal.org/view.php?id=35943

A better error would be nice but I guess I can't do this anyways until the other bug is fixed.

Why? It does say that a class type is expected. And the column of the error should point to the correct location. 
That's the same error you'd get when specializing outside of a generic with a non-class type. 



> The "specialize" is part of the generic identifier, so it must be "FGL.specialize TFPGObjectList<T>".
>
> That said however an internal error should not happen (especially the one I just added some days ago ^^'). Please report this one.
>

That doesn't look right to my eyes but ok. I filed a report (https://bugs.freepascal.org/view.php?id=36377).

The idea is that "specialize" belongs to the identifier just like "generic" does. This comes especially apparent for nested specializations:

SomeUnit.specialize SomeType<... >.specialize SomeFunc<... >



It looks like my plan was foiled so I made a non-generic attempt. Can you explain why I get the EListError at runtime? I checked the itemSize property and it's the same for both lists.

{$mode objfpc}

program test;
uses
  FGL;

type
  TNode = class (TInterfacedObject)
  end;
  TNodeObjectList = specialize TFPGInterfacedObjectList<TNode>;

function CopyList (source: TFPSList): TFPSList;
begin
  result := TFPSList(source.ClassType.Create);
  result.Assign(source);
end;

var
  a, b: TNodeObjectList;
begin
  a := TNodeObjectList.Create;
  // EListError: Incompatible item size in source list
  b := CopyList(a) as TNodeObjectList;
end.

Can't tell right now from looking at it. Will need to test that later on. 

Regards, 
Sven 

_______________________________________________
fpc-pascal maillist  -  [hidden email]
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Two possible generics bugs

Free Pascal - General mailing list


> On Nov 29, 2019, at 2:00 AM, Sven Barth via fpc-pascal <[hidden email]> wrote:
>
> Why? It does say that a class type is expected. And the column of the error should point to the correct location.
> That's the same error you'd get when specializing outside of a generic with a non-class type.

I think you're right, my fault for not looking at the column close enough.

>
>
> > The "specialize" is part of the generic identifier, so it must be "FGL.specialize TFPGObjectList<T>".
> >
> > That said however an internal error should not happen (especially the one I just added some days ago ^^'). Please report this one.
> >
>
> That doesn't look right to my eyes but ok. I filed a report (https://bugs.freepascal.org/view.php?id=36377).
>
> The idea is that "specialize" belongs to the identifier just like "generic" does. This comes especially apparent for nested specializations:
>
> SomeUnit.specialize SomeType<... >.specialize SomeFunc<... >

What's your plan to make an implicit specialize modeswitch? I remember you said you wanted to and it sounds like low-hanging fruit I could maybe help with. The specialize keyword is a bit much in my opinion and it sounds like it could be omitted like Delphi mode does.

>
> begin
>   a := TNodeObjectList.Create;
>   // EListError: Incompatible item size in source list
>   b := CopyList(a) as TNodeObjectList;
> end.
>
> Can't tell right now from looking at it. Will need to test that later on.
>

Anyone else have any idea? Doesn't make any sense to me.

Regards,
        Ryan Joseph

_______________________________________________
fpc-pascal maillist  -  [hidden email]
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Two possible generics bugs

Free Pascal - General mailing list
In reply to this post by Free Pascal - General mailing list
Am 28.11.2019 um 16:14 schrieb Ryan Joseph via fpc-pascal:

> {$mode objfpc}
>
> program test;
> uses
>    FGL;
>
> // Type identifier expected
> // Internal error 2019112401
> generic function CopyList<T>(source: specialize FGL.TFPGObjectList<T>): specialize FGL.TFPGObjectList<T>;
> begin
> end;
>
> begin
> end.
>
What option did you use to compile it? What platform did you use? Cause
I can't reproduce the internal error...

=== code begin ===

PS C:\fpc\git> .\compiler\ppcx64.exe -n -Furtl\units\x86_64-win64 -viwn
-FEtestoutput .\tests\tbf\tb0272.pp
Target OS: Win64 for x64
Compiling .\tests\tbf\tb0272.pp
tb0272.pp(9,52) Error: Type identifier expected
tb0272.pp(9,87) Error: Type identifier expected
tb0272.pp(15) Fatal: There were 2 errors compiling module, stopping
Fatal: Compilation aborted

=== code end ===

Regards,
Sven
_______________________________________________
fpc-pascal maillist  -  [hidden email]
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Two possible generics bugs

Florian Klämpfl
Am 30.11.19 um 18:51 schrieb Sven Barth via fpc-pascal:

> Am 28.11.2019 um 16:14 schrieb Ryan Joseph via fpc-pascal:
>> {$mode objfpc}
>>
>> program test;
>> uses
>>    FGL;
>>
>> // Type identifier expected
>> // Internal error 2019112401
>> generic function CopyList<T>(source: specialize
>> FGL.TFPGObjectList<T>): specialize FGL.TFPGObjectList<T>;
>> begin
>> end;
>>
>> begin
>> end.
>>
> What option did you use to compile it? What platform did you use? Cause
> I can't reproduce the internal error...

r43612 | florian | 2019-11-29 23:13:17 +0100 (Fr, 29. Nov 2019) | 1 Zeile

   * better error recovery, resolves #36377

;)
_______________________________________________
fpc-pascal maillist  -  [hidden email]
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Two possible generics bugs

Free Pascal - General mailing list
In reply to this post by Free Pascal - General mailing list
Am 29.11.2019 um 01:01 schrieb Ryan Joseph via fpc-pascal:
>
> function CopyList (source: TFPSList): TFPSList;
> begin
>    result := TFPSList(source.ClassType.Create);
>    result.Assign(source);
> end;
This can't work. ClassType is of type TClass and TClass.Create calls
TObject.Create, *not* the constructor of your list type, cause the
constructor chain is not virtual.

What you can do is this:

=== code begin ===

generic function CopyList<T: TFPSList> (source: T): T;
begin
   result := T.Create;
   result.Assign(source);
end;

var
   a, b: TNodeObjectList;
begin
   a := TNodeObjectList.Create;
   b := specialize CopyList<TNodeObjectList>(a);
end.

=== code end ===

Regards,
Sven
_______________________________________________
fpc-pascal maillist  -  [hidden email]
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Two possible generics bugs

Free Pascal - General mailing list
In reply to this post by Florian Klämpfl
Am 30.11.2019 um 18:56 schrieb Florian Klämpfl:

> Am 30.11.19 um 18:51 schrieb Sven Barth via fpc-pascal:
>> Am 28.11.2019 um 16:14 schrieb Ryan Joseph via fpc-pascal:
>>> {$mode objfpc}
>>>
>>> program test;
>>> uses
>>>    FGL;
>>>
>>> // Type identifier expected
>>> // Internal error 2019112401
>>> generic function CopyList<T>(source: specialize
>>> FGL.TFPGObjectList<T>): specialize FGL.TFPGObjectList<T>;
>>> begin
>>> end;
>>>
>>> begin
>>> end.
>>>
>> What option did you use to compile it? What platform did you use?
>> Cause I can't reproduce the internal error...
>
> r43612 | florian | 2019-11-29 23:13:17 +0100 (Fr, 29. Nov 2019) | 1 Zeile
>
>   * better error recovery, resolves #36377
>
> ;)
That indeed explains it 😅

Regards,
Sven
_______________________________________________
fpc-pascal maillist  -  [hidden email]
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Two possible generics bugs

Free Pascal - General mailing list
In reply to this post by Free Pascal - General mailing list
Am 29.11.2019 um 22:56 schrieb Ryan Joseph via fpc-pascal:

>
>> On Nov 29, 2019, at 2:00 AM, Sven Barth via fpc-pascal <[hidden email]> wrote:
>>
>> Why? It does say that a class type is expected. And the column of the error should point to the correct location.
>> That's the same error you'd get when specializing outside of a generic with a non-class type.
> I think you're right, my fault for not looking at the column close enough.
>
>>
>>> The "specialize" is part of the generic identifier, so it must be "FGL.specialize TFPGObjectList<T>".
>>>
>>> That said however an internal error should not happen (especially the one I just added some days ago ^^'). Please report this one.
>>>
>> That doesn't look right to my eyes but ok. I filed a report (https://bugs.freepascal.org/view.php?id=36377).
>>
>> The idea is that "specialize" belongs to the identifier just like "generic" does. This comes especially apparent for nested specializations:
>>
>> SomeUnit.specialize SomeType<... >.specialize SomeFunc<... >
> What's your plan to make an implicit specialize modeswitch? I remember you said you wanted to and it sounds like low-hanging fruit I could maybe help with. The specialize keyword is a bit much in my opinion and it sounds like it could be omitted like Delphi mode does.
Well, if you want you can find any place where the _SPECIALIZE and
_GENERIC tokens are used and checked against mode Delphi to check
against a new modeswitch instead ("GENERICKEYWORDS") which must be
enabled by default in all modes except the Delphi ones.

Please note however that disabling the generic keywords also restricts
some expressions that the compiler can handle as the Delphi syntax is
not completly without ambiguity and not completly handled in the parser yet.

Regards,
Sven
_______________________________________________
fpc-pascal maillist  -  [hidden email]
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Two possible generics bugs

Free Pascal - General mailing list


> On Nov 30, 2019, at 1:04 PM, Sven Barth via fpc-pascal <[hidden email]> wrote:
>
> Well, if you want you can find any place where the _SPECIALIZE and _GENERIC tokens are used and checked against mode Delphi to check against a new modeswitch instead ("GENERICKEYWORDS") which must be enabled by default in all modes except the Delphi ones.

So to get Delphi mode style generics in ObjFPC mode you need to disable the modeswitch? That's kind of backwards from what mode switches usually  do but it makes sense. How do you even disable a mode switch?

Regards,
        Ryan Joseph

_______________________________________________
fpc-pascal maillist  -  [hidden email]
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Two possible generics bugs

Free Pascal - General mailing list
In reply to this post by Free Pascal - General mailing list


> On Nov 30, 2019, at 12:58 PM, Sven Barth via fpc-pascal <[hidden email]> wrote:
>
> This can't work. ClassType is of type TClass and TClass.Create calls TObject.Create, *not* the constructor of your list type, cause the constructor chain is not virtual.

Ok, so if the constructor was virtual this would work as expected? I guess that make sense. We really need implicit function specialization already but I don't want to bog down your review process anymore than I have. Removing the generic keyword will at least make this a little nicer to work with in the mean time and that's low hanging fruit.

Regards,
        Ryan Joseph

_______________________________________________
fpc-pascal maillist  -  [hidden email]
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Two possible generics bugs

Free Pascal - General mailing list
In reply to this post by Free Pascal - General mailing list


> On Nov 30, 2019, at 12:58 PM, Sven Barth via fpc-pascal <[hidden email]> wrote:
>
> This can't work. ClassType is of type TClass and TClass.Create calls TObject.Create, *not* the constructor of your list type, cause the constructor chain is not virtual.
>
> What you can do is this:
>
> === code begin ===
>
> generic function CopyList<T: TFPSList> (source: T): T;
> begin
>   result := T.Create;
>   result.Assign(source);
> end;
>
> var
>   a, b: TNodeObjectList;
> begin
>   a := TNodeObjectList.Create;
>   b := specialize CopyList<TNodeObjectList>(a);
> end.
>
> === code end ===

Found yet another internal compiler error trying your code:

https://bugs.freepascal.org/view.php?id=36388

The previous day was another internal compiler error with inline functions in case you missed it. ;)

https://bugs.freepascal.org/view.php?id=36381

Regards,
        Ryan Joseph

_______________________________________________
fpc-pascal maillist  -  [hidden email]
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Two possible generics bugs

Free Pascal - General mailing list
In reply to this post by Free Pascal - General mailing list
Ryan Joseph via fpc-pascal <[hidden email]> schrieb am So., 1. Dez. 2019, 23:11:


> On Nov 30, 2019, at 1:04 PM, Sven Barth via fpc-pascal <[hidden email]> wrote:
>
> Well, if you want you can find any place where the _SPECIALIZE and _GENERIC tokens are used and checked against mode Delphi to check against a new modeswitch instead ("GENERICKEYWORDS") which must be enabled by default in all modes except the Delphi ones.

So to get Delphi mode style generics in ObjFPC mode you need to disable the modeswitch? That's kind of backwards from what mode switches usually  do but it makes sense. How do you even disable a mode switch?

Well, you disable a feature that a mode provides. Some strange there... 

And it's simply done as with other switches:

{$modeswitch xyz-} 

(I don't know right now whether "off" is supported as well) 

Regards, 
Sven 

_______________________________________________
fpc-pascal maillist  -  [hidden email]
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal
Reply | Threaded
Open this post in threaded view
|

Re: Two possible generics bugs

Free Pascal - General mailing list
In reply to this post by Free Pascal - General mailing list
Ryan Joseph via fpc-pascal <[hidden email]> schrieb am Mo., 2. Dez. 2019, 14:01:


> On Nov 30, 2019, at 12:58 PM, Sven Barth via fpc-pascal <[hidden email]> wrote:
>
> This can't work. ClassType is of type TClass and TClass.Create calls TObject.Create, *not* the constructor of your list type, cause the constructor chain is not virtual.

Ok, so if the constructor was virtual this would work as expected? I guess that make sense. 

In this specific case: not really. Because TFPSList has a different constructor signature than TFPGList<>. And even then you'd need to cast ClassType to a "class of TFPSList" type as TObject.Create is never virtual. 

Regards, 
Sven 

_______________________________________________
fpc-pascal maillist  -  [hidden email]
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal