Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-devel / 2017-08

Allow record helper inheritance in Delphi mode

59 messages · 7 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Ondrej Pokorny

Hello!

I find it unnecessary to disable record helper inheritance in Delphi mode. Due to this  artificial limitation I have to change unit mode from Delphi to ObjFPC.

Reasons:
1.) It's a limitation of a feature that FPC already has. 2.) I write FPC-only code in Delphi mode. I don't care about Delphi compatibilty.
3.) There are already switches/features allowed in Delphi mode that are not compatible with Delphi either. (E.g.  {$COPERATORS ON}, {$MACRO ON}, maybe more).

Please either allow record helper inheritance in Delphi mode by default or at least make a switch to allow it. I can try to come up with a patch if you suggest what you prefer.

I find it ridiculous to change the mode of a whole unit just to enable a feature that FPC already has and Delphi strangely lacks.

Ondrej

Reply by email

Michael Van Canneyt
to Ondrej Pokorny: Hello! I find it unnecessary to disable record helper inheritance in Delphi mode. Due to…
Ondrej Pokorny wrote 20 lines
Hello! I find it unnecessary to disable record helper inheritance in Delphi mode. Due to this  artificial limitation I have to change unit mode from Delphi to ObjFPC. Reasons: 1.) It's a limitation of a feature that FPC already has. 2.) I write FPC-only code in Delphi mode. I don't care about Delphi compatibilty. 3.) There are already switches/features allowed in Delphi mode that are not compatible with Delphi either. (E.g.  {$COPERATORS ON}, {$MACRO ON}, maybe more). Please either allow record helper inheritance in Delphi mode by default or at least make a switch to allow it. I can try to come up with a patch if you suggest what you prefer. I find it ridiculous to change the mode of a whole unit just to enable a feature that FPC already has and Delphi strangely lacks.

That's the idea of Delphi compatibility mode.

The default should remain as is, but a modeswitch can be implemented.

Michael.

Reply by email

Sven Barth
to Ondrej Pokorny: Hello! I find it unnecessary to disable record helper inheritance in Delphi mode. Due to…
"Ondrej Pokorny" wrote
Hello! I find it unnecessary to disable record helper inheritance in Delphi

mode. Due to this artificial limitation I have to change unit mode from Delphi to ObjFPC.

Reasons: 1.) It's a limitation of a feature that FPC already has. 2.) I write FPC-only code in Delphi mode. I don't care about Delphi

compatibilty.

3.) There are already switches/features allowed in Delphi mode that are

not compatible with Delphi either. (E.g. {$COPERATORS ON}, {$MACRO ON}, maybe more).

Please either allow record helper inheritance in Delphi mode by default

or at least make a switch to allow it. I can try to come up with a patch if you suggest what you prefer.

I find it ridiculous to change the mode of a whole unit just to enable a

feature that FPC already has and Delphi strangely lacks.

This will not be enabled by default. If anything a modeswitch will be added so that users are aware that what they'll write will not be compatible with Delphi.
However since I'm busy with other FPC stuff: patches welcome. Suggested name is "NonDelphiExtensions".

Regards,
Sven

Reply by email

Michael Van Canneyt
to Sven Barth
Sven Barth wrote 29 lines
Am 28.08.2017 23:11 schrieb "Ondrej Pokorny" : > > Hello! > > I find it unnecessary to disable record helper inheritance in Delphi mode. Due to this artificial limitation I have to change unit mode from Delphi to ObjFPC. > > Reasons: > 1.) It's a limitation of a feature that FPC already has. > 2.) I write FPC-only code in Delphi mode. I don't care about Delphi compatibilty. > 3.) There are already switches/features allowed in Delphi mode that are not compatible with Delphi either. (E.g. {$COPERATORS ON}, {$MACRO ON}, maybe more). > > Please either allow record helper inheritance in Delphi mode by default or at least make a switch to allow it. I can try to come up with a patch if you suggest what you prefer. > > I find it ridiculous to change the mode of a whole unit just to enable a feature that FPC already has and Delphi strangely lacks. > This will not be enabled by default. If anything a modeswitch will be added so that users are aware that what they'll write will not be compatible with Delphi. However since I'm busy with other FPC stuff: patches welcome. Suggested name is "NonDelphiExtensions".

Why not simply allow $RECORDHELPERS or so ?

Michael.

Reply by email

Ondrej Pokorny
to Michael Van Canneyt: Why not simply allow $RECORDHELPERS or so ? Michael.
Michael Van Canneyt wrote 5 lines
On Tue, 29 Aug 2017, Sven Barth via fpc-devel wrote: > Suggested name is "NonDelphiExtensions". Why not simply allow $RECORDHELPERS or so ?

Hmm yes. Reading
https://www.freepascal.org/docs-html/3.0.2/prog/progsu105.html you can define other non-delphi extensions for the Delphi mode (like NESTEDCOMMENTS).

Maybe it would be more clear to name the modeswitch TYPEHELPERINHERITANCE and don't bind it to delphi mode?

Ondrej

Reply by email

Maciej Izak
to Ondrej Pokorny

2017-08-29 10:37 GMT+02:00 Ondrej Pokorny :

Show quoted text 6 lines
Hmm yes. Reading https://www.freepascal.org/doc s-html/3.0.2/prog/progsu105.html you can define other non-delphi extensions for the Delphi mode (like NESTEDCOMMENTS). Maybe it would be more clear to name the modeswitch TYPEHELPERINHERITANCE and don't bind it to delphi mode?

IMO the switch should be related strictly to unified type helpers usage. I prefer to have also "type helper for" also in Dlephi mode instead of "record helper for" for simple types. Different syntax for the same thing is very annoying especially when someone need to work in many modes. -,-

Best regards, Maciej Izak

Reply by email

Ondrej Pokorny
to Maciej Izak
Maciej Izak wrote
I prefer to have also "type helper for" also in Dlephi mode instead of "record helper for" for simple types. Different syntax for the same thing is very annoying especially when someone need to work in many modes. -,-

I don't care about the syntax that much. For me it's the lacking features what is important.

Ondrej

Reply by email

Sven Barth
to Michael Van Canneyt: Why not simply allow $RECORDHELPERS or so ? Michael.
"Michael Van Canneyt" wrote 31 lines
On Tue, 29 Aug 2017, Sven Barth via fpc-devel wrote: > Am 28.08.2017 23:11 schrieb "Ondrej Pokorny" : >> >> >> Hello! >> >> I find it unnecessary to disable record helper inheritance in Delphi > > mode. Due to this artificial limitation I have to change unit mode from > Delphi to ObjFPC. >> >> >> Reasons: >> 1.) It's a limitation of a feature that FPC already has. >> 2.) I write FPC-only code in Delphi mode. I don't care about Delphi > > compatibilty. >> >> 3.) There are already switches/features allowed in Delphi mode that are > > not compatible with Delphi either. (E.g. {$COPERATORS ON}, {$MACRO ON}, > maybe more). >> >> >> Please either allow record helper inheritance in Delphi mode by default > > or at least make a switch to allow it. I can try to come up with a patch

if

Show quoted text 10 lines
> you suggest what you prefer. >> >> >> I find it ridiculous to change the mode of a whole unit just to enable a > > feature that FPC already has and Delphi strangely lacks. >> >> > > This will not be enabled by default. If anything a modeswitch will be

added

> so that users are aware that what they'll write will not be compatible

with

Show quoted text 6 lines
> Delphi. > However since I'm busy with other FPC stuff: patches welcome. Suggested > name is "NonDelphiExtensions". Why not simply allow $RECORDHELPERS or so ?

What strangeness is this? We have the modeswitch concept for a reason, namely that we don't need to introduce a new directive for everything.

Regards,
Sven

Reply by email

Sven Barth
to Ondrej Pokorny: Hmm yes. Reading https://www.freepascal.org/docs-html/3.0.2/prog/progsu105.html you can…
"Ondrej Pokorny" wrote 12 lines
On 29.08.2017 8:47, Michael Van Canneyt wrote: > > On Tue, 29 Aug 2017, Sven Barth via fpc-devel wrote: > >> Suggested name is "NonDelphiExtensions". > > > Why not simply allow $RECORDHELPERS or so ? Hmm yes. Reading

https://www.freepascal.org/docs-html/3.0.2/prog/progsu105.html you can define other non-delphi extensions for the Delphi mode (like NESTEDCOMMENTS).

Maybe it would be more clear to name the modeswitch TYPEHELPERINHERITANCE

and don't bind it to delphi mode?

The idea is okay as well, but I'd name it RecordHelperInheritance, cause if we'd allow "type helper" in mode Delphi (as Maciej asks) then those would support inheritance by default as they aren't Delphi compatible as a whole anyway.

Regards,
Sven

Reply by email

Ondrej Pokorny
to Sven Barth
Sven Barth wrote
The idea is okay as well, but I'd name it RecordHelperInheritance, cause if we'd allow "type helper" in mode Delphi (as Maciej asks) then those would support inheritance by default as they aren't Delphi compatible as a whole anyway.

Actually, IMO {$modeswitch typehelpers} should be supported in delphi mode as well - just like {$modeswitch advancedrecords} is. Some code to test:

program Project1;
{$mode delphi}
{$modeswitch typehelpers+} // it doesn't allow "TStringHelper = type
helper for AnsiString"
{$modeswitch advancedrecords-} // it doesn't disable record helper for TRec
type
   TRec = record
     A, B: Integer;
   end;

  TRecHelper = record helper for TRec
  public
  end;

  TStringHelper = type helper for AnsiString
  public
  end;

begin
end.

Furthermore the record helper Delphi syntax is supported in ObjFPC mode
- even with inheritance [!]:

program Project1;
{$mode objfpc}
{$modeswitch typehelpers+}
{$modeswitch advancedrecords}
type
   TRec = record
     A, B: Integer;
   end;

  TRecHelper = record helper for TRec
  public
  end;

   TStringHelper = record helper for AnsiString
   public
     function R: string;
   end;
   TStringHelper2 = record helper(TStringHelper) for AnsiString
   public
     function R2: string;
   end;
function TStringHelper2.R2: string;
begin
   Result := 'R2';
end;
function TStringHelper.R: string;
begin
   Result := 'R';
end;
var
   S: AnsiString;
begin
   Writeln(S.R2);
end.

So, yes. There are inconsistencies that should be fixed: 1.) Support {$modeswitch typehelpers +/-} in delphi mode. 2.) Add a new modeswitch "RecordHelperInheritance" to enable/disable record helper inheritance in all modes.

Ondrej

Reply by email

Sven Barth
to Ondrej Pokorny: Actually, IMO {$modeswitch typehelpers} should be supported in delphi mode as well - just…
"Ondrej Pokorny" wrote
On 29.08.2017 11:48, Sven Barth via fpc-devel wrote: > > The idea is okay as well, but I'd name it RecordHelperInheritance, cause

if we'd allow "type helper" in mode Delphi (as Maciej asks) then those would support inheritance by default as they aren't Delphi compatible as a whole anyway.

Actually, IMO {$modeswitch typehelpers} should be supported in delphi

mode as well - just like {$modeswitch advancedrecords} is. Some code to test:

It is supported and in fact also enabled by default, just not in the manner you expect: it controls whether primitive types can be used with record helpers in Delphi modes.

Furthermore the record helper Delphi syntax is supported in ObjFPC mode -

even with inheritance [!]:

Of course it is, because the record (and class) helpers were implemented first and I saw no reason to differentiate between class and record helpers regarding inheritance. I merely differentiated between mode Delphi and the others, because Delphi does not allow it.

Regards,
Sven

Reply by email

Ondrej Pokorny
to Sven Barth

There is a difference between FPC 3.0.0 and current trunk (without my patch) regarding {$modeswitch typehelpers} and "TXYZHelper = type helper for TXYZ".

In 3.0.0 it is obvious - it can be used only for primitive types. In trunk you can use type helper for everything (with {$modeswitch typehelpers}) - primitive types, record, classes and interfaces (btw. thanks for the interfaces - you should announce it loud :) ).

Example code:

program DelphiHelpers;
{$mode objfpc}
{$modeswitch advancedrecords+}
{$modeswitch typehelpers+}
type
   TRec = record
   public
     function A: string;
   end;
   TRecHelper = type helper for TRec
   public
     function AB: string;
   end;

  TObjectHelper = type helper for TObject
  public
  end;

{ TRecHelper }

function TRecHelper.AB: string;
begin
   Result := inherited A + 'b';
end;

{ TRec }

function TRec.A: string;
begin
   Result := 'a';
end;
var
   T: TRec;
begin
   if T.AB  'ab' then
     Halt(1);
   Writeln('ok');
end.

-> It compiles fine in trunk but does not compile in 3.0.0.

So yes, your description of {$modeswitch typehelpers} makes sense for 3.0.0 but not for trunk any more. So what is your intention - 3.0.0 behavior or trunk behavior?

Ondrej

Reply by email

Anthony Walter
to Ondrej Pokorny

Out of curiosity, is there any strategy that is or can be employed to ensure new language features and mode switches automatically work with codetools and by extension the Lazarus IDE?

Or is duplication of effort the only way to get codetools properly parsing new language features?

Reply by email

Ondrej Pokorny
to Anthony Walter
Anthony Walter wrote 6 lines
Out of curiosity, is there any strategy that is or can be employed to ensure new language features and mode switches automatically work with codetools and by extension the Lazarus IDE? Or is duplication of effort the only way to get codetools properly parsing new language features?

"duplication of effort" is the correct answer :)

Ondrej

Reply by email

Sven Barth
to Ondrej Pokorny: There is a difference between FPC 3.0.0 and current trunk (without my patch) regarding…
"Ondrej Pokorny" wrote
So yes, your description of {$modeswitch typehelpers} makes sense for

3.0.0 but not for trunk any more. So what is your intention - 3.0.0 behavior or trunk behavior?

Maybe it would indeed make more sense to adjust the meaning of the typehelpers modeswitch in mode Delphi... Namely that it enabled the "type helper" syntax including the inheritance. But the record helpers are left as is... (btw: a type helper for a primitive type can inherit from a record helper of the same type, internally they're all the same)

This way we won't need a new modeswitch...

Regards,
Sven

Reply by email

Ondrej Pokorny
to Sven Barth
Sven Barth wrote 15 lines
Am 29.08.2017 17:39 schrieb "Ondrej Pokorny" < >: > So yes, your description of {$modeswitch typehelpers} makes sense for 3.0.0 but not for trunk any more. So what is your intention - 3.0.0 behavior or trunk behavior? Maybe it would indeed make more sense to adjust the meaning of the typehelpers modeswitch in mode Delphi... Namely that it enabled the "type helper" syntax including the inheritance. But the record helpers are left as is... (btw: a type helper for a primitive type can inherit from a record helper of the same type, internally they're all the same) This way we won't need a new modeswitch...

Looks OK to me. Actually I only will join RecordHelperInheritance and TypeHelpers switch from delphi-helpers-2.patch in
https://mantis.freepascal.org/view.php?id=32355. It should be easy to do.

+ It means that record helper inheritance will be enabled with typehelpers as well because if I am not mistaken currently the compiler cannot distinguish between a type helper and record helper acting on a record. (IMO it is even a plus.)

Ondrej

Reply by email

Maciej Izak
to Sven Barth: 3.0.0 but not for trunk any more. So what is your intention - 3.0.0 behavior or trunk…

2017-08-29 18:54 GMT+02:00 Sven Barth via fpc-devel <

Show quoted text 10 lines
: Maybe it would indeed make more sense to adjust the meaning of the typehelpers modeswitch in mode Delphi... Namely that it enabled the "type helper" syntax including the inheritance. But the record helpers are left as is... (btw: a type helper for a primitive type can inherit from a record helper of the same type, internally they're all the same) This way we won't need a new modeswitch...

+1 for single modeswitch. In my case both would be used all the time.

IMO inheritance for record helpers in Delphi mode has no really meaning and may stay as undefined behavior (finally we have many non Delphi behaviors available in Delphi mode), even more - it is nice addition :).

Best regards, Maciej Izak

Reply by email

Ondrej Pokorny
to Maciej Izak
Maciej Izak wrote
IMO inheritance for record helpers in Delphi mode has no really meaning and may stay as undefined behavior

No - please not yet another undefined behavior :)

It's perfectly defined: disabled without typehelpers, enabled with typehelpers.

Ondrej

Reply by email

Maciej Izak
to Ondrej Pokorny

2017-08-29 20:24 GMT+02:00 Ondrej Pokorny :

Show quoted text 5 lines
No - please not yet another undefined behavior :) It's perfectly defined: disabled without typehelpers, enabled with typehelpers.

but in the case of strictly defined rules we must to do as Sven said:

"Namely that it enabled the "type helper" syntax including the inheritance. But the record helpers are left as is..."

it is contrary to your previous message:

+ It means that record helper inheritance will be enabled with typehelpers

as well because if I am not mistaken currently the compiler cannot distinguish between a type helper and record helper acting on a record. (IMO it is even a plus.)

in "Svens scenario" inheritance for "record helper" should be blocked in Delphi mode and compiler is obligated to knows differences between "type helper" and "record helper".

By "undefined behavior" I mean allowing inheritance for "record helper" in Delphi mode *for now* because is not harmful (especially with switch typehelpers). "for now" means years or even forever.

If you wish to have strictly defined rules for "record helpers" inheritance in Delphi mode it simple means no inheritance for such case as is in Delphi :)

Best regards, Maciej Izak

Reply by email

Maciej Izak
to Ondrej Pokorny: "duplication of effort" is the correct answer :) Ondrej

2017-08-29 17:51 GMT+02:00 Ondrej Pokorny :

Show quoted text 12 lines
On 29.08.2017 17:47, Anthony Walter wrote: Out of curiosity, is there any strategy that is or can be employed to ensure new language features and mode switches automatically work with codetools and by extension the Lazarus IDE? Or is duplication of effort the only way to get codetools properly parsing new language features? "duplication of effort" is the correct answer :)

for codetools synchronized with compiler we should have:

* new frontend for compiler (dual licensing GPL/LGPL with static linking exception would be cool for 3rd tools)
* or smart plugins system for compiler
* or some other hardcore solution :)

Best regards, Maciej Izak

Reply by email

Michael Van Canneyt
to Maciej Izak
Maciej Izak wrote 21 lines
2017-08-29 17:51 GMT+02:00 Ondrej Pokorny : > On 29.08.2017 17:47, Anthony Walter wrote: > > Out of curiosity, is there any strategy that is or can be employed to > ensure new language features and mode switches automatically work with > codetools and by extension the Lazarus IDE? > > Or is duplication of effort the only way to get codetools properly parsing > new language features? > > > "duplication of effort" is the correct answer :) > for codetools synchronized with compiler we should have: * new frontend for compiler (dual licensing GPL/LGPL with static linking exception would be cool for 3rd tools) * or smart plugins system for compiler * or some other hardcore solution :)

I advise against it.

The codetools need a lot more than just a working compiler. The compiler was never designed to be used in an IDE.

And actually, duplication of effort has a good side: in a way, the IDE independently 'checks' the working of the compiler.

Michael.

Reply by email

Ondrej Pokorny
to Maciej Izak: 2017-08-29 20:24 GMT+02:00 Ondrej Pokorny : but in the case of strictly defined rules we…
Maciej Izak wrote 13 lines
2017-08-29 20:24 GMT+02:00 Ondrej Pokorny < >: No - please not yet another undefined behavior :) It's perfectly defined: disabled without typehelpers, enabled with typehelpers. but in the case of strictly defined rules we must to do as Sven said:  "Namely that it enabled the "type helper" syntax including the inheritance. But the record helpers are left as is..."

Why? I can make strictly defined rules that typehelpers also allow record helper inheritance. There are no limitations for definitions ;)

Show quoted text 10 lines
it is contrary to your previous message: + It means that record helper inheritance will be enabled with typehelpers as well because if I am not mistaken currently the compiler cannot distinguish between a type helper and record helper acting on a record. (IMO it is even a plus.) in "Svens scenario" inheritance for "record helper" should be blocked in Delphi mode and compiler is obligated to knows differences between "type helper" and "record helper".

I, on the contrary, read:

Sven Barth wrote
(btw: a type helper for a primitive type can inherit from a record

helper of the same type, internally they're all the same)

Btw. record helpers support inheritance in all modes but Delphi. It doesn't make sense to disallow it for record helpers but allow it for type helpers... Too overcomplicated without any plus value :/

Ondrej

Reply by email

Ondrej Pokorny
to Michael Van Canneyt: I advise against it. The codetools need a lot more than just a working compiler. The…
Michael Van Canneyt wrote
And actually, duplication of effort has a good side: in a way, the IDE independently 'checks' the working of the compiler.

Unfortunately the reality is the other way round: the compiler checks the working of CodeTools :)

Positive is that CodeTools understand 99.9% of code (apart from generics). So yes, the big task is to make CodeTools understand generics. Everything else is either already implemented or easy to add.

Btw. I miss compiler support of anonymous methods much more than CodeTools support of generics.

Ondrej

Reply by email

Maciej Izak
to Ondrej Pokorny: Why? I can make strictly defined rules that typehelpers also allow record helper…

2017-08-29 22:09 GMT+02:00 Ondrej Pokorny :

Show quoted text 6 lines
I, on the contrary, read: On 29.08.2017 18:54, Sven Barth via fpc-devel wrote: > (btw: a type helper for a primitive type can inherit from a record helper of the same type, internally they're all the same)

but in this example you have different kind of inheritance (type helper from record helper). "internally" is the key word ;)

Btw. record helpers support inheritance in all modes but Delphi. It doesn't make sense to disallow it for record helpers but allow it for type helpers... Too overcomplicated without any plus value :/

what if Delphi will decide to introduce some new exotic syntax/extension/feature for "record helper"? With "type helper" and modeswitch typehelpers usage of inheritance still will be possible in Delphi mode and is safer :).

You have also right, so inheritance in Delphi mode for record helpers should be "undefined" but you don't like this, so I have no idea how you want to convince Sven to "record helpers" inheritance in Delphi mode :P. Good luck ;)

Best regards, Maciej Izak

Reply by email

Ondrej Pokorny
to Maciej Izak
Maciej Izak wrote 8 lines
Btw. record helpers support inheritance in all modes but Delphi. It doesn't make sense to disallow it for record helpers but allow it for type helpers... Too overcomplicated without any plus value :/ what if Delphi will decide to introduce some new exotic syntax/extension/feature for "record helper"?

Yeah, they might enable record helper inheritance for example :P (Record helper inheritance was documented to work for about 7 years since Delphi 2007 until XE6
http://docwiki.embarcadero.com/RADStudio/XE6/en/Class_and_Record_Helpers_(Delphi) ).

Ondrej

Reply by email

Sven Barth
to Ondrej Pokorny
"Ondrej Pokorny" wrote 6 lines
On 29.08.2017 22:30, Maciej Izak wrote: > > >> >> Btw. record helpers support inheritance in all modes but Delphi. It

doesn't make sense to disallow it for record helpers but allow it for type helpers... Too overcomplicated without any plus value :/

> > > what if Delphi will decide to introduce some new exotic

syntax/extension/feature for "record helper"?

Yeah, they might enable record helper inheritance for example :P (Record

helper inheritance was documented to work for about 7 years since Delphi 2007 until XE6
http://docwiki.embarcadero.com/RADStudio/XE6/en/Class_and_Record_Helpers_(Delphi) ).

Huh? I had developed the feature while testing with Delphi XE and there record helpers did not support inheritance, only class helpers did. So as long as you don't provide prove I'd say that this is a documentation bug.

Regards,
Sven

Reply by email

Marco van de Voort
to Sven Barth

In our previous episode, Sven Barth via fpc-devel said:

Show quoted text 5 lines
> Yeah, they might enable record helper inheritance for example :P (Record helper inheritance was documented to work for about 7 years since Delphi 2007 until XE6 http://docwiki.embarcadero.com/RADStudio/XE6/en/Class_and_Record_Helpers_(Delphi) ).

(pretty underwhelming as a description of helper inheritance, doesn't describe at all what it is good for or how it works)

Huh? I had developed the feature while testing with Delphi XE and there record helpers did not support inheritance, only class helpers did. So as long as you don't provide prove I'd say that this is a documentation bug.

My XE4 doesn't either.

Reply by email

Ondrej Pokorny
to Sven Barth: doesn't make sense to disallow it for record helpers but allow it for type helpers... Too…
Sven Barth wrote 14 lines
> Yeah, they might enable record helper inheritance for example :P (Record helper inheritance was documented to work for about 7 years since Delphi 2007 until XE6 http://docwiki.embarcadero.com/RADStudio/XE6/en/Class_and_Record_Helpers_(Delphi) <http://docwiki.embarcadero.com/RADStudio/XE6/en/Class_and_Record_Helpers_%28Delphi%29> ). > Huh? I had developed the feature while testing with Delphi XE and there record helpers did not support inheritance, only class helpers did. So as long as you don't provide prove I'd say that this is a documentation bug.

That's exactly what I say: record helpers don't support inheritance but the documentation (until XE6) says nothing about this restriction, on the contrary. Only in XE7 they added the "It [the ancestor list] can be specified only for class helper." line. See:

http://docwiki.embarcadero.com/RADStudio/XE6/en/Class_and_Record_Helpers_(Delphi) http://docwiki.embarcadero.com/RADStudio/XE7/en/Class_and_Record_Helpers_(Delphi)

It is a matter of point of view if it was a documentation bug or a compiler bug. Embarcadero shared your opinion with "documentation bug". (My personal opinion is that they just forgot about inheritance when they implemented record helpers and then instead of fixing the compiler they fixed the docs - yeah because it's easier.)

+++++

I remember a compiler bug in class destructor order call in Delphi: https://stackoverflow.com/questions/19332847/delphi-class-variable-going-out-of-scope-before-class-destructor-is-called

There were several issue reports about it in Embarcadero Quality Central (which is now down, so I can't provide the links), all resolved as "won't fix". Embarcadero always claimed this was by design.

But when they introduced ARC they suddendly couldn't justify the design flaw because consequently class objects were not available in class destructors in ARC mode but they were available in non-ARC mode. So they decided to fix the order just like lots of people requested from the very beginning. IMO it was VERY embarrassing for Embarcadero.

By the way, FPC is affected by the very same bug:
https://mantis.freepascal.org/view.php?id=29334 .

Ondrej

Reply by email

Sven Barth
to Ondrej Pokorny: That's exactly what I say: record helpers don't support inheritance but the documentation…
"Ondrej Pokorny" wrote 5 lines
On 31.08.2017 14:55, Sven Barth via fpc-devel wrote: > > > > Yeah, they might enable record helper inheritance for example :P

(Record helper inheritance was documented to work for about 7 years since Delphi 2007 until XE6
http://docwiki.embarcadero.com/RADStudio/XE6/en/Class_and_Record_Helpers_(Delphi) <
http://docwiki.embarcadero.com/RADStudio/XE6/en/Class_and_Record_Helpers_%28Delphi%29> ).

> > > > > Huh? I had developed the feature while testing with Delphi XE and there

record helpers did not support inheritance, only class helpers did. So as long as you don't provide prove I'd say that this is a documentation bug.

> That's exactly what I say: record helpers don't support inheritance but

the documentation (until XE6) says nothing about this restriction, on the contrary. Only in XE7 they added the "It [the ancestor list] can be specified only for class helper." line. See:

http://docwiki.embarcadero.com/RADStudio/XE6/en/Class_and_Record_Helpers_(Delphi)

http://docwiki.embarcadero.com/RADStudio/XE7/en/Class_and_Record_Helpers_(Delphi)

It is a matter of point of view if it was a documentation bug or a

compiler bug. Embarcadero shared your opinion with "documentation bug". (My personal opinion is that they just forgot about inheritance when they implemented record helpers and then instead of fixing the compiler they fixed the docs - yeah because it's easier.)

No, I don't think they thought this way. Class and record helpers weren't largely advertised back when they were introduced. They even had the note that one shouldn't use them for own implementations. And for record helpers they modelled them after records. If I remember correctly the "protected" section isn't allowed in record helpers either, because it isn't allowed in records.

+++++ I remember a compiler bug in class destructor order call in Delphi:

https://stackoverflow.com/questions/19332847/delphi-class-variable-going-out-of-scope-before-class-destructor-is-called

There were several issue reports about it in Embarcadero Quality Central

(which is now down, so I can't provide the links), all resolved as "won't fix". Embarcadero always claimed this was by design.

But when they introduced ARC they suddendly couldn't justify the design

flaw because consequently class objects were not available in class destructors in ARC mode but they were available in non-ARC mode. So they decided to fix the order just like lots of people requested from the very beginning. IMO it was VERY embarrassing for Embarcadero.

By the way, FPC is affected by the very same bug:

https://mantis.freepascal.org/view.php?id=29334 .

That should get solved once I reworked the unit initialization which is the last real blocker for dynamically loading packages.

Regards,
Sven

Reply by email

Ondrej Pokorny
to Sven Barth
Sven Barth wrote 7 lines
> I remember a compiler bug in class destructor order call in Delphi: https://stackoverflow.com/questions/19332847/delphi-class-variable-going-out-of-scope-before-class-destructor-is-called That should get solved once I reworked the unit initialization which is the last real blocker for dynamically loading packages.

What I particularly like is that you considered it as a bug and were open for a discussion from the very beginning - even if the behavior was Delphi compatible at that point. Not like Embarcadero closing eyes and ears until they really had to solve it. All kudos to you and the FPC team :)

Maybe Embarcadero changes their record inheritance policy as well at some point - especially because they introduced record helpers for primitive types (like TStringHelper). Not having inheritance for them forbids easy extension of them.

Ondrej

Reply by email

Sven Barth
to Ondrej Pokorny
"Ondrej Pokorny" wrote
On 31.08.2017 17:22, Sven Barth via fpc-devel wrote: > > > I remember a compiler bug in class destructor order call in Delphi:

https://stackoverflow.com/questions/19332847/delphi-class-variable-going-out-of-scope-before-class-destructor-is-called

> > > That should get solved once I reworked the unit initialization which is

the last real blocker for dynamically loading packages.

> What I particularly like is that you considered it as a bug and were open

for a discussion from the very beginning - even if the behavior was Delphi compatible at that point. Not like Embarcadero closing eyes and ears until they really had to solve it. All kudos to you and the FPC team :)

Though to be fair the team in general and me especially can be rather stubborn on other topics ;)

Maybe Embarcadero changes their record inheritance policy as well at some

point - especially because they introduced record helpers for primitive types (like TStringHelper). Not having inheritance for them forbids easy extension of them.

I seriously doubt that they really care about that. They want to add fancy thing X and awesome feature Y, but don't care about such things. Especially with there being fewer and fewer compiler developers for Delphi around...

Regards,
Sven

Reply by email

Stefan Glienke
to Ondrej Pokorny: What I particularly like is that you considered it as a bug and were open for a…

Inheritance seems like the obvious way but you just defer the "I cannot extend the builtin helpers" problem. If any third party code decides to do so you are at the same point again because now do you inherit from the third party helper or from the builtin one? What if two third parties inherit from the helper?

Therefor I argue that the "only the last one in scope is applied" restriction should be removed. If there are any clashes because two helpers introduce a any ambiguity well then it is the compilers job to warn or error about those and provide a way to explicitly call the method from one specific helper by hardcasting the instance to the helper type or otherwise.

Show quoted text 26 lines
On 31 August 2017 at 17:47 Ondrej Pokorny wrote: On 31.08.2017 17:22, Sven Barth via fpc-devel wrote: > > I remember a compiler bug in class destructor order call in Delphi: > https://stackoverflow.com/questions/19332847/delphi-class-variable-going-out-of-scope-before-class-destructor-is-called > > > That should get solved once I reworked the unit initialization which > is the last real blocker for dynamically loading packages. > What I particularly like is that you considered it as a bug and were open for a discussion from the very beginning - even if the behavior was Delphi compatible at that point. Not like Embarcadero closing eyes and ears until they really had to solve it. All kudos to you and the FPC team :) Maybe Embarcadero changes their record inheritance policy as well at some point - especially because they introduced record helpers for primitive types (like TStringHelper). Not having inheritance for them forbids easy extension of them. Ondrej _______________________________________________ fpc-devel maillist - http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel

Reply by email

Ondrej Pokorny
to Stefan Glienke
Stefan Glienke wrote 6 lines
Inheritance seems like the obvious way but you just defer the "I cannot extend the builtin helpers" problem. If any third party code decides to do so you are at the same point again because now do you inherit from the third party helper or from the builtin one? What if two third parties inherit from the helper?

Yes, you are right, I forgot about this issue.

Therefor I argue that the "only the last one in scope is applied" restriction should be removed.

This could be also solved by supporting "ancestor list" (what Delphi documentation talks about but the compiler doesn't allow it again):

  TEmbarcaderoHelper = class helper for TObject
  public
  end;

  TThirdPartyHelper = class helper for TObject
  public
  end;

  TMyHelper = class helper(TEmbarcaderoHelper, TThirdPartyHelper) for TObject
  public
  end;

Ondrej

Reply by email

Sven Barth
to Stefan Glienke: Inheritance seems like the obvious way but you just defer the "I cannot extend the…
"Stefan Glienke" wrote
Therefor I argue that the "only the last one in scope is applied"

restriction should be removed.

If there are any clashes because two helpers introduce a any ambiguity

well then it is the compilers job to warn or error about those and provide a way to explicitly call the method from one specific helper by hardcasting the instance to the helper type or otherwise.

That one is on my ToDo-list already.

Regards,
Sven

Reply by email

Stefan Glienke
to Ondrej Pokorny: Yes, you are right, I forgot about this issue. This could be also solved by supporting…

Again you will cause unnecessary headaches because now your helper has the dependency of the builtin and the third party one. How would third party one and third party two implement them? They both probably would extend the builtin one. Which one can you use in your code then? Yes, the one that comes last in the uses. What if you want to use functions from both? Out of luck again.

Inheritance regardless what form is never is the best option here. I think "ancestor list" is just a misnomer in the documentation as it cannot be a list but only one in case of class helper.

Show quoted text 38 lines
On 01 September 2017 at 09:40 Ondrej Pokorny wrote: On 01.09.2017 8:47, Stefan Glienke wrote: > Inheritance seems like the obvious way but you just defer the "I > cannot extend the builtin helpers" problem. > If any third party code decides to do so you are at the same point > again because now do you inherit from the third party helper or from > the builtin one? > What if two third parties inherit from the helper? Yes, you are right, I forgot about this issue. > Therefor I argue that the "only the last one in scope is applied" > restriction should be removed. This could be also solved by supporting "ancestor list" (what Delphi documentation talks about but the compiler doesn't allow it again): TEmbarcaderoHelper = class helper for TObject public end; TThirdPartyHelper = class helper for TObject public end; TMyHelper = class helper(TEmbarcaderoHelper, TThirdPartyHelper) for TObject public end; Ondrej _______________________________________________ fpc-devel maillist - http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel

Reply by email

Stefan Glienke
to Sven Barth: restriction should be removed. well then it is the compilers job to warn or error about…

What I am lobbying for in Delphi are interface helpers and helpers for generic types in general.

I just saw that FPC currently has the same limitation. That also on your list?

Show quoted text 16 lines
On 01 September 2017 at 11:07 Sven Barth wrote: Am 01.09.2017 08:47 schrieb "Stefan Glienke" : > Therefor I argue that the "only the last one in scope is applied" restriction should be removed. > If there are any clashes because two helpers introduce a any ambiguity well then it is the compilers job to warn or error about those and provide a way to explicitly call the method from one specific helper by hardcasting the instance to the helper type or otherwise. > That one is on my ToDo-list already. Regards, Sven

Reply by email

Ondrej Pokorny
to Stefan Glienke: Again you will cause unnecessary headaches because now your helper has the dependency of…
Stefan Glienke wrote
Again you will cause unnecessary headaches because now your helper has the dependency of the builtin and the third party one.

Not really, if you want to use both helpers (builtin and 3rd party) in the same unit you have the dependencies already added.

How would third party one and third party two implement them? They both probably would extend the builtin one. Which one can you use in your code then?

I define TMyHelper with the ancestors I want to have available. It has the plus that I also can disable helpers that I don't want to use but that are available through unit dependencies.

Yes, the one that comes last in the uses. What if you want to use functions from both? Out of luck again.

No, TMyHelper has all methods available both from both TEmbarcaderoHelper and TThirdPartyHelper, I can also have something like:

TMyHelper = class helper (THelper3rdParty1, THelper3rdParty2)

+++

But yes I fully agree with you. It's much easier when the "only the last one in scope is applied" restriction is removed. It was just an idea how to make it using the current Delphi documentation.

Ondrej

Reply by email

Maciej Izak
to Stefan Glienke: Again you will cause unnecessary headaches because now your helper has the dependency of…

2017-09-01 11:41 GMT+02:00 Stefan Glienke :

Show quoted text 11 lines
Again you will cause unnecessary headaches because now your helper has the dependency of the builtin and the third party one. How would third party one and third party two implement them? They both probably would extend the builtin one. Which one can you use in your code then? Yes, the one that comes last in the uses. What if you want to use functions from both? Out of luck again. Inheritance regardless what form is never is the best option here. I think "ancestor list" is just a misnomer in the documentation as it cannot be a list but only one in case of class helper.

The control of modules order in uses section can turn programmers life into real hell for type helpers. I think that new directive $EXPLICITHELPERS should help :

type
  TH1 = record helper for string
    procedure foo;
    procedure foo1;
  end;
  TH2 = record helper for string
    procedure foo;
    procedure foo2;
  end;
  TH3 = record helper for string
    procedure foo;
    procedure foo3;
  end;
var
  s: string;
begin
  s.foo; // call TH3.foo
{$EXPLICITHELPERS TH1 for string} // scope for helpers limited only to TH1
  s.foo; // call TH1.foo
  s.foo3; // error
{$EXPLICITHELPERS TH2, TH1 for string}
  s.foo; // call TH2.foo
  s.foo1; // call TH1.foo1
{$EXPLICITHELPERS default for string}
  s.foo; // call TH3.foo
{$EXPLICITHELPERS TH1, default for string}
  s.foo; // TH1.foo
  s.foo1;
  s.foo2;
  s.foo3;
end.
Best regards, Maciej Izak

Reply by email

Ondrej Pokorny
to Maciej Izak
Maciej Izak wrote 19 lines
2017-09-01 11:41 GMT+02:00 Stefan Glienke < >: Again you will cause unnecessary headaches because now your helper has the dependency of the builtin and the third party one. How would third party one and third party two implement them? They both probably would extend the builtin one. Which one can you use in your code then? Yes, the one that comes last in the uses. What if you want to use functions from both? Out of luck again. Inheritance regardless what form is never is the best option here. I think "ancestor list" is just a misnomer in the documentation as it cannot be a list but only one in case of class helper. The control of modules order in uses section can turn programmers life into real hell for type helpers. I think that new directive $EXPLICITHELPERS should help :

That's effectively just another way to write:

TMyHelper = class helper (TH2, TH1) // scope for helpers limited to TH2, TH1

:P

Ondrej

Reply by email

Stefan Glienke
to Maciej Izak: 2017-09-01 11:41 GMT+02:00 Stefan Glienke : The control of modules order in uses section…

I consider that as terribly hard to maintain code. As soon as you move around statements, refactor things everything gets messed up. No thanks.

Show quoted text 64 lines
On 01 September 2017 at 12:15 Maciej Izak wrote: 2017-09-01 11:41 GMT+02:00 Stefan Glienke : > Again you will cause unnecessary headaches because now your helper has the > dependency of the builtin and the third party one. > How would third party one and third party two implement them? They both > probably would extend the builtin one. Which one can you use in your code > then? > Yes, the one that comes last in the uses. What if you want to use > functions from both? Out of luck again. > > Inheritance regardless what form is never is the best option here. I think > "ancestor list" is just a misnomer in the documentation as it cannot be a > list but only one in case of class helper. The control of modules order in uses section can turn programmers life into real hell for type helpers. I think that new directive $EXPLICITHELPERS should help : type TH1 = record helper for string procedure foo; procedure foo1; end; TH2 = record helper for string procedure foo; procedure foo2; end; TH3 = record helper for string procedure foo; procedure foo3; end; var s: string; begin s.foo; // call TH3.foo {$EXPLICITHELPERS TH1 for string} // scope for helpers limited only to TH1 s.foo; // call TH1.foo s.foo3; // error {$EXPLICITHELPERS TH2, TH1 for string} s.foo; // call TH2.foo s.foo1; // call TH1.foo1 {$EXPLICITHELPERS default for string} s.foo; // call TH3.foo {$EXPLICITHELPERS TH1, default for string} s.foo; // TH1.foo s.foo1; s.foo2; s.foo3; end. -- Best regards, Maciej Izak

Reply by email

Sven Barth
to Stefan Glienke: What I am lobbying for in Delphi are interface helpers and helpers for generic types in…
"Stefan Glienke" wrote
What I am lobbying for in Delphi are interface helpers and helpers for

generic types in general.

I just saw that FPC currently has the same limitation. That also on your

list?

Interface helpers are implemented in trunk for around two weeks now.

For generics the only way to support them is that you must explicitly specialize a generic helper type. The compiler won't do any type inference for you.
This is on my ToDo list as well (the generic helpers, not the type inference).

Regards,
Sven

Reply by email

Sven Barth
to Maciej Izak: 2017-09-01 11:41 GMT+02:00 Stefan Glienke : The control of modules order in uses section…
"Maciej Izak" wrote
2017-09-01 11:41 GMT+02:00 Stefan Glienke : > > Again you will cause unnecessary headaches because now your helper has

the dependency of the builtin and the third party one.

> How would third party one and third party two implement them? They both

probably would extend the builtin one. Which one can you use in your code then?

> Yes, the one that comes last in the uses. What if you want to use

functions from both? Out of luck again.

> > Inheritance regardless what form is never is the best option here. I

think "ancestor list" is just a misnomer in the documentation as it cannot be a list but only one in case of class helper.

The control of modules order in uses section can turn programmers life

into real hell for type helpers. I think that new directive $EXPLICITHELPERS should help :

Show quoted text 39 lines
type TH1 = record helper for string procedure foo; procedure foo1; end; TH2 = record helper for string procedure foo; procedure foo2; end; TH3 = record helper for string procedure foo; procedure foo3; end; var s: string; begin s.foo; // call TH3.foo {$EXPLICITHELPERS TH1 for string} // scope for helpers limited only to TH1 s.foo; // call TH1.foo s.foo3; // error {$EXPLICITHELPERS TH2, TH1 for string} s.foo; // call TH2.foo s.foo1; // call TH1.foo1 {$EXPLICITHELPERS default for string} s.foo; // call TH3.foo {$EXPLICITHELPERS TH1, default for string} s.foo; // TH1.foo s.foo1; s.foo2; s.foo3; end.

No, directives won't be abused for something like that.

Regards,
Sven

Reply by email

Michael Van Canneyt
to Sven Barth
Sven Barth wrote 12 lines
Am 01.09.2017 12:15 schrieb "Maciej Izak" : > > 2017-09-01 11:41 GMT+02:00 Stefan Glienke : > > {$EXPLICITHELPERS TH1, default for string} > s.foo; // TH1.foo > s.foo1; > s.foo2; > s.foo3; > end. No, directives won't be abused for something like that.

I am glad I am not the only one who thins so :)

Michael.

Reply by email

Maciej Izak
to Michael Van Canneyt

2017-09-01 14:30 GMT+02:00 Michael Van Canneyt :

Show quoted text 5 lines
> No, directives won't be abused for something like that. > I am glad I am not the only one who thins so :)

I like experiments as you know. Thanks for critical words as always :P. But this time I must agree too. :) Only one experimental option left in my mind for this:

s: string with TH1, TH2;

but for now probably hardcasting is the best what we can.

Best regards, Maciej Izak

Reply by email

Stefan Glienke
to Sven Barth: generic types in general. list? Interface helpers are implemented in trunk for around two…
For generics the only way to support them is that you must explicitly specialize a generic helper type. The compiler won't do any type inference for you.

IMO this makes them rather useless. Is that a technical limitation or just something you did not want to do? I don't know much about compiler internals for forgive me my naivety.

If I have TFoo<T> and a TFooHelper<T> and somewhere declare a TFoo<Integer> and use a method from my helper can't the compiler make sure to compile the TFooHelper<Integer> version for it?

I guess it's because it does not know anymore that TFoo<Integer> is in fact a closed generic type that was constructed from the open geneneric type TFoo<T>?

Reply by email

Sven Barth
to Maciej Izak: 2017-09-01 14:30 GMT+02:00 Michael Van Canneyt : I like experiments as you know. Thanks…
"Maciej Izak" wrote 11 lines
2017-09-01 14:30 GMT+02:00 Michael Van Canneyt : >> >> >> No, directives won't be abused for something like that. > > > I am glad I am not the only one who thins so :) I like experiments as you know. Thanks for critical words as always :P.

But this time I must agree too. :) Only one experimental option left in my mind for this:

s: string with TH1, TH2; but for now probably hardcasting is the best what we can.

I'd prefer to keep that syntax for aspects or as alternative attribute syntax instead of wasting it for helpers that are defined to work based on the type.

Regards,
Sven

Reply by email

Sven Barth
"Stefan Glienke" wrote
> For generics the only way to support them is that you must explicitly

specialize a generic helper type. The compiler won't do any type inference for you.

IMO this makes them rather useless. Is that a technical limitation or

just something you did not want to do?

I don't know much about compiler internals for forgive me my naivety. If I have TFoo<T> and a TFooHelper<T> and somewhere declare a

TFoo<Integer> and use a method

from my helper can't the compiler make sure to compile the

TFooHelper<Integer> version for it?

What if I do the initial specialization in a unit that does not know about the helper? It can't just do speculative specialization once both the specialized generic and the generic helper are used in the same unit. And even if the compiler would postpone it till some method of the specialized type is called things would get polluted once multiple helpers lee type are allowed as every one of the generic helpers in scope would need to be specialized for overload resolution.

So in short: no, I don't *want* this, but it's due to technical reasons.

I guess it's because it does not know anymore that TFoo<Integer> is in

fact a closed generic type that was constructed from the open geneneric type TFoo<T>?

The compiler can know rather easily that a type is a specialization, but you need to keep in mind that helpers are also active for parent types. So if you descend from a specialization the helpers of the generic would need to be available as well.

Regards,
Sven

Reply by email

Maciej Izak
to Sven Barth: But this time I must agree too. :) Only one experimental option left in my mind for this:…

2017-09-01 18:30 GMT+02:00 Sven Barth via fpc-devel <

Show quoted text 6 lines
: I'd prefer to keep that syntax for aspects or as alternative attribute syntax instead of wasting it for helpers that are defined to work based on the type

+1 :))) so we have nice topic to talk. I have hope that you remember our last long conversation about default field? Since that time I've done work around aspects and smart pointers / nullable types too (and syntax with "with" is also related and can aspects can coexist with my proposition for helpers - anyway we will discuss this later in other topic). All syntax/conceptual problems mentioned last time by Jonas for default field are solved. But I don't want to start yet another discussion around new patch, especially that FastRTTI is in last phase ;) (I hope so).

Best regards, Maciej Izak

Reply by email

Stefan Glienke
to Sven Barth: specialize a generic helper type. The compiler won't do any type inference for you. just…

As I said for me then it's rather useless for what I see the benefit in helpers for generic types.

It's not even close to the benefit I get from extension methods in C# (yeah, I know generics work a bit different there).

Having really slim interfaces like IEnumerable<T> or IObservable<T> which both have only one method but a ton of extension methods that give all the power to those types is great not only for extensibility by adding more extension methods but also for implementing your own enumerables or observables (only need to implement one method!).

Having to put those methods on the interface in pascal which is not even possible because some of those extension methods have more than just the one generic parameter from the type they are extending is making this kind of code very unwieldy (you have to write it in a reverse way wrapping static method calls into each other rather than just chaining them together).

Sven Barth wrote 39 lines
Am 01.09.2017 14:50 schrieb "Stefan Glienke" < >: > > > For generics the only way to support them is that you must explicitly specialize a generic helper type. The compiler won't do any type inference for you. > > IMO this makes them rather useless. Is that a technical limitation or just something you did not want to do? > I don't know much about compiler internals for forgive me my naivety. > > If I have TFoo<T> and a TFooHelper<T> and somewhere declare a TFoo<Integer> and use a method > from my helper can't the compiler make sure to compile the TFooHelper<Integer> version for it? What if I do the initial specialization in a unit that does not know about the helper? It can't just do speculative specialization once both the specialized generic and the generic helper are used in the same unit. And even if the compiler would postpone it till some method of the specialized type is called things would get polluted once multiple helpers lee type are allowed as every one of the generic helpers in scope would need to be specialized for overload resolution. So in short: no, I don't *want* this, but it's due to technical reasons. > I guess it's because it does not know anymore that TFoo<Integer> is in fact a closed generic type that was constructed from the open geneneric type TFoo<T>? The compiler can know rather easily that a type is a specialization, but you need to keep in mind that helpers are also active for parent types. So if you descend from a specialization the helpers of the generic would need to be available as well. Regards, Sven

---
Diese E-Mail wurde von Avast Antivirus-Software auf Viren geprüft. https://www.avast.com/antivirus

Reply by email

Ondrej Pokorny
to Sven Barth: specialize a generic helper type. The compiler won't do any type inference for you. just…
Sven Barth wrote 19 lines
What if I do the initial specialization in a unit that does not know about the helper? It can't just do speculative specialization once both the specialized generic and the generic helper are used in the same unit. And even if the compiler would postpone it till some method of the specialized type is called things would get polluted once multiple helpers lee type are allowed as every one of the generic helpers in scope would need to be specialized for overload resolution. So in short: no, I don't *want* this, but it's due to technical reasons. > I guess it's because it does not know anymore that TFoo<Integer> is in fact a closed generic type that was constructed from the open geneneric type TFoo<T>? The compiler can know rather easily that a type is a specialization, but you need to keep in mind that helpers are also active for parent types. So if you descend from a specialization the helpers of the generic would need to be available as well.

What about explicitely specializing the generic helper?

   generic TMyClass<T> = class;
   generic TMyClassHelper<T> = class helper for TMyClass<T>;

...

   TMyClassInt = specialize TMyClass<Integer>;
   TMyClassIntHelper = specialize class helper(TMyClassHelper<Integer>)
for TMyClass<Integer>;
- or -
   TMyClassIntHelper = specialize class helper(TMyClassHelper<Integer>)
for TMyClassInt;

In this case the compiler knows about the TMyClassIntHelper for TMyClassInt(TMyClass<Integer>) and that it has to inherit from TMyClassHelper<Integer>.

Ondrej

Reply by email

Sven Barth
"Ondrej Pokorny" wrote
On 01.09.2017 18:38, Sven Barth via fpc-devel wrote: > > What if I do the initial specialization in a unit that does not know

about the helper? It can't just do speculative specialization once both the specialized generic and the generic helper are used in the same unit. And even if the compiler would postpone it till some method of the specialized type is called things would get polluted once multiple helpers lee type are allowed as every one of the generic helpers in scope would need to be specialized for overload resolution.

> > So in short: no, I don't *want* this, but it's due to technical reasons. > > > I guess it's because it does not know anymore that TFoo<Integer> is in

fact a closed generic type that was constructed from the open geneneric type TFoo<T>?

> > The compiler can know rather easily that a type is a specialization, but

you need to keep in mind that helpers are also active for parent types. So if you descend from a specialization the helpers of the generic would need to be available as well.

Show quoted text 11 lines
> What about explicitely specializing the generic helper? generic TMyClass<T> = class; generic TMyClassHelper<T> = class helper for TMyClass<T>; ... TMyClassInt = specialize TMyClass<Integer>; TMyClassIntHelper = specialize class helper(TMyClassHelper<Integer>)
for TMyClass<Integer>;
- or - TMyClassIntHelper = specialize class helper(TMyClassHelper<Integer>)
for TMyClassInt;
In this case the compiler knows about the TMyClassIntHelper for

TMyClassInt(TMyClass<Integer>) and that it has to inherit from TMyClassHelper<Integer>.

That is basically what I was talking about though it would be like this:

=== code begin ===

TMyClassIntHelper = specialize TMyClassHelper<LongInt>;
// somewhere else
specialize TMyClass<LongInt>.SomeHelperMethod;

=== code end ===

This would even be rather easy to implement.

Regards,
Sven

Reply by email

Ondrej Pokorny
to Sven Barth: mode. Due to this artificial limitation I have to change unit mode from Delphi to ObjFPC.
Sven Barth wrote
This will not be enabled by default. If anything a modeswitch will be added so that users are aware that what they'll write will not be compatible with Delphi.

Any chance to get the (last) patch in issue #32355 reviewed? Somehow I have the feeling that I always hear "patches are welcome" but consequently my patches are ignored and then they just get forgotten if I don't remind several times.

Btw. when you are so strict about disabling helper inheritance due to Delphi compatibility why do you allow C-like operators in Delphi mode by default?

program Cop;
{$mode delphi}
var
   I: Integer;
begin
   I := 0;
   I += 1;
end.

... and they even have their COPERATORS directive.

Ondrej

Reply by email

Sven Barth
to Ondrej Pokorny
Ondrej Pokorny wrote 9 lines
On 29.08.2017 7:54, Sven Barth via fpc-devel wrote: > This will not be enabled by default. If anything a modeswitch will be > added so that users are aware that what they'll write will not be > compatible with Delphi. Any chance to get the (last) patch in issue #32355 reviewed? Somehow I have the feeling that I always hear "patches are welcome" but consequently my patches are ignored and then they just get forgotten if I don't remind several times.

Ever thought that I might not work on FPC every day yet alone review patches?
Anyway, I had looked at your patch last Friday, but after some thinking I came to the conclusion that I definitely don't want the typehelpers modeswitch to enable inheritance on record helpers in mode Delphi cause that would be some unexpected sideeffect on that switch. However to implement this correctly I'll need to store the helper type in the PPU. It's nothing big, just something I need to find the time for...

Show quoted text 16 lines
Btw. when you are so strict about disabling helper inheritance due to Delphi compatibility why do you allow C-like operators in Delphi mode by default? program Cop; {$mode delphi} var I: Integer; begin I := 0; I += 1; end. ... and they even have their COPERATORS directive.

Two things:
1. If you compile with -n (and -Fupath/to/rtl) you'll see that it is not Delphi mode that enables the C-operators, but the default fpc.cfg (and no, I don't know who had the idea to enable that as default; maybe it was originally default and then moved to a directive, but kept set by default using the fpc.cfg... - for this however see the next point)
2. Backwards compatibility. In the past quite some features were added without much respect for the modes (e.g. the "<<" and ">>" operators as aliases for "shl" and "shr" work in any mode and can't be disabled anyway), so some things are simply kept that way to avoid disruptions of existing code while the implementation of new features became stricter in the last 6 years or so.

Regards,
Sven

Reply by email

Ondrej Pokorny
to Sven Barth
Sven Barth wrote 6 lines
Anyway, I had looked at your patch last Friday, but after some thinking I came to the conclusion that I definitely don't want the typehelpers modeswitch to enable inheritance on record helpers in mode Delphi cause that would be some unexpected sideeffect on that switch. However to implement this correctly I'll need to store the helper type in the PPU. It's nothing big, just something I need to find the time for...

Great. Thanks for the feedback. I appreciate it.

Show quoted text 22 lines
> Btw. when you are so strict about disabling helper inheritance due to > Delphi compatibility why do you allow C-like operators in Delphi mode by > default? > > program Cop; > > {$mode delphi} > > var > I: Integer; > begin > I := 0; > I += 1; > end. > > ... and they even have their COPERATORS directive. Two things: 1. If you compile with -n (and -Fupath/to/rtl) you'll see that it is not Delphi mode that enables the C-operators, but the default fpc.cfg (and no, I don't know who had the idea to enable that as default; maybe it was originally default and then moved to a directive, but kept set by default using the fpc.cfg... - for this however see the next point)

This is what I thought as well. I took a look into my fpc.cfg and saw -Sc is commented out:

#      -Sc        supports operators like C (*=,+=,/= and -=)

But I didn't look at the end of the section where it is defined: -Sgic

My apologies :) But there are still inconsistences that just feel strange :/

Ondrej

Reply by email

Sven Barth
"Ondrej Pokorny" wrote 12 lines
On 13.09.2017 22:08, Sven Barth via fpc-devel wrote: > > Anyway, I had looked at your patch last Friday, but after some thinking > I came to the conclusion that I definitely don't want the typehelpers > modeswitch to enable inheritance on record helpers in mode Delphi cause > that would be some unexpected sideeffect on that switch. However to > implement this correctly I'll need to store the helper type in the PPU. > It's nothing big, just something I need to find the time for... Great. Thanks for the feedback. I appreciate it.

As you might have seen I have now added the part about storing the helper type, so I can now adjust your patch for the final inclusion (either today or tomorrow if all goes well).

Show quoted text 26 lines
>> Btw. when you are so strict about disabling helper inheritance due to >> Delphi compatibility why do you allow C-like operators in Delphi mode by >> default? >> >> program Cop; >> >> {$mode delphi} >> >> var >> I: Integer; >> begin >> I := 0; >> I += 1; >> end. >> >> ... and they even have their COPERATORS directive. > > Two things: > 1. If you compile with -n (and -Fupath/to/rtl) you'll see that it is not > Delphi mode that enables the C-operators, but the default fpc.cfg (and > no, I don't know who had the idea to enable that as default; maybe it > was originally default and then moved to a directive, but kept set by > default using the fpc.cfg... - for this however see the next point) This is what I thought as well. I took a look into my fpc.cfg and saw -Sc

is commented out:

Show quoted text 7 lines
# -Sc supports operators like C (*=,+=,/= and -=) But I didn't look at the end of the section where it is defined: -Sgic My apologies :) But there are still inconsistences that just feel strange

:/

As said FPC has quite a history baggage to carry and the stances on the modes have only changed relatively recently (e.g. the ISO mode doesn't allow you to use units as they weren't defined there, so in that sense the mode is extremely strict).

Regards,
Sven

Reply by email