From lazarus at mfriebe.de Sun Jul 6 13:51:21 2025 From: lazarus at mfriebe.de (Martin Frb) Date: Sun, 6 Jul 2025 13:51:21 +0200 Subject: [fpc-devel] "class of TFoo".Create Message-ID: <14c3fc8c-a8b3-47e7-a105-a963db8f484a@mfriebe.de> I stumbled (by accident) on (maybe) a curiosity TFooClass = class of TFoo; can store a class (that must be TFoo or subclass of it). I would have expected that the type TFooClass itself is not a class. (Its a container for a class / for lack of better wording) Yet TFooClass.Create compiles. And creates an instance of type TFoo. Is that intentional. program Project1; {$mode objfpc} type TFoo = class end; ???? TFooClass = class of TFoo; var f: TFoo; ??? fc: TFooClass; begin ? fc := TFoo; ? f? := fc.Create; ? f? := TFooClass.Create;? // works end. From bartjunk64 at gmail.com Sun Jul 6 14:38:47 2025 From: bartjunk64 at gmail.com (Bart) Date: Sun, 6 Jul 2025 14:38:47 +0200 Subject: [fpc-devel] "class of TFoo".Create In-Reply-To: <14c3fc8c-a8b3-47e7-a105-a963db8f484a@mfriebe.de> References: <14c3fc8c-a8b3-47e7-a105-a963db8f484a@mfriebe.de> Message-ID: On Sun, Jul 6, 2025 at 1:57?PM Martin Frb via fpc-devel wrote: > program Project1; > {$mode objfpc} > type TFoo = class end; > TFooClass = class of TFoo; > var f: TFoo; > fc: TFooClass; > begin > fc := TFoo; > f := fc.Create; > f := TFooClass.Create; // works > end. Delphi (7) happily compiles that as well. And f is of type TFoo there as well. -- Bart From gareth at moreton-family.com Sun Jul 6 15:11:58 2025 From: gareth at moreton-family.com (J. Gareth Moreton) Date: Sun, 6 Jul 2025 14:11:58 +0100 Subject: [fpc-devel] "class of TFoo".Create In-Reply-To: References: <14c3fc8c-a8b3-47e7-a105-a963db8f484a@mfriebe.de> Message-ID: <399c0ad6-dfb0-4f32-a685-3d29eb576060@moreton-family.com> I would personally call that unusual at best.? Logically I would consider it a type mismatch or a syntax error of some kind, since TFoo is a class and TFooClass is a metaclass.? Also, if I saw such code in a project, I would think someone made a mistake that didn't get caught, since TFoo.Create would make much more sense. I'd wonder if, under OBJFPC mode, such a construct should raise a compiler error because I honestly can't see a situation where it would be correct and intentional over using the associated class in its place. Kit On 06/07/2025 13:38, Bart via fpc-devel wrote: > On Sun, Jul 6, 2025 at 1:57?PM Martin Frb via fpc-devel > wrote: > > >> program Project1; >> {$mode objfpc} >> type TFoo = class end; >> TFooClass = class of TFoo; >> var f: TFoo; >> fc: TFooClass; >> begin >> fc := TFoo; >> f := fc.Create; >> f := TFooClass.Create; // works >> end. > Delphi (7) happily compiles that as well. > And f is of type TFoo there as well. > -- This email has been checked for viruses by Avast antivirus software. www.avast.com From zoe at scootersoftware.com Sun Jul 6 16:17:42 2025 From: zoe at scootersoftware.com (=?utf-8?Q?Zo=C3=AB_Peterson?=) Date: Sun, 6 Jul 2025 17:17:42 +0300 Subject: [fpc-devel] "class of TFoo".Create In-Reply-To: <399c0ad6-dfb0-4f32-a685-3d29eb576060@moreton-family.com> References: <399c0ad6-dfb0-4f32-a685-3d29eb576060@moreton-family.com> Message-ID: > ?I would personally call that unusual at best What do you two expect this construct to do that you think the current behavior is wrong? It?sobviously correct and expected to me as a fundamental part of Object Pascal?s polymorphism. Constructing an object from a class reference is the entire reason that constructors are virtual. It?s how things like TPicture.Graphic are implemented to create the correct image loading object. Zo? Peterson Scooter Software From gareth at moreton-family.com Sun Jul 6 16:31:05 2025 From: gareth at moreton-family.com (J. Gareth Moreton) Date: Sun, 6 Jul 2025 15:31:05 +0100 Subject: [fpc-devel] "class of TFoo".Create In-Reply-To: References: <399c0ad6-dfb0-4f32-a685-3d29eb576060@moreton-family.com> Message-ID: <804965b0-3f9c-4bf9-8a30-8d792622d922@moreton-family.com> What I mean is that if you want to instantiate an object of class TFoo, you'd call TFoo.Create, not TFooClass.Create. If you want to take advantage of Object Pascal's unique polymorphism and instantiate a descendant class of TFoo, you'd call MetaClassVariable.Create rather than TFooClass.Create, where MetaClassVariable is defined somewhere as "var MetaClassVariable: TFooClass;" and then set it accordingly before the instantiation. To just call TFooClass.Create, and TFooClass is implicitly converted to TFoo, feels a bit 'off' and is asking for trouble, while seeing "TFooClass.Create" in the code would be indictive of a bug in my opinion, since the programmer either meant "TFoo" or a variable of type TFooClass instead of "TFooClass" itself. On 06/07/2025 15:17, Zo? Peterson via fpc-devel wrote: >> ?I would personally call that unusual at best > > What do you two expect this construct to do that you think the current behavior is wrong? It?sobviously correct and expected to me as a fundamental part of Object Pascal?s polymorphism. Constructing an object from a class reference is the entire reason that constructors are virtual. It?s how things like TPicture.Graphic are implemented to create the correct image loading object. > > Zo? Peterson > Scooter Software > > > _______________________________________________ > fpc-devel maillist - fpc-devel at lists.freepascal.org > https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel > -- This email has been checked for viruses by Avast antivirus software. www.avast.com From lazarus at mfriebe.de Sun Jul 6 16:33:50 2025 From: lazarus at mfriebe.de (Martin Frb) Date: Sun, 6 Jul 2025 16:33:50 +0200 Subject: [fpc-devel] "class of TFoo".Create In-Reply-To: References: <399c0ad6-dfb0-4f32-a685-3d29eb576060@moreton-family.com> Message-ID: <5a8e99eb-9aa5-4354-9687-499c5c9fb7d1@mfriebe.de> On 06/07/2025 16:17, Zo? Peterson via fpc-devel wrote: >> ?I would personally call that unusual at best > > What do you two expect this construct to do that you think the current behavior is wrong? It?sobviously correct and expected to me as a fundamental part of Object Pascal?s polymorphism. Constructing an object from a class reference is the entire reason that constructors are virtual. It?s how things like TPicture.Graphic are implemented to create the correct image loading object. > In the below, calling ? fc.Create; is ok. fc is a variable, and its value is a class. (that can be TFoo, or TFooChild) Calling ? TFooClass.Create on the otherhand... TFooClass is not a class. Its a type for a variable that then as value can have a class. And, it also seems to Statically translate into ? TFooClass.Create == TFoo.Create. The type TFooClass itself can not be assigned a value. So it is always the same. To answer your question: I expected it to be an error. But if for cautious reasons that is not going to be, then at least a warning, nothing less program?Project1; {$mode?objfpc} type?TFoo?=?class?end; ?????TFooClass?=?class?of?TFoo; var?f:?TFoo; ????fc:?TFooClass; begin ??fc?:=?TFoo; ??f??:=?fc.Create; ??f??:=?TFooClass.Create;??//?works end. -------------- next part -------------- An HTML attachment was scrubbed... URL: From fpc at pascalprogramming.org Sun Jul 6 16:41:53 2025 From: fpc at pascalprogramming.org (Marco van de Voort) Date: Sun, 6 Jul 2025 16:41:53 +0200 Subject: [fpc-devel] "class of TFoo".Create In-Reply-To: <804965b0-3f9c-4bf9-8a30-8d792622d922@moreton-family.com> References: <399c0ad6-dfb0-4f32-a685-3d29eb576060@moreton-family.com> <804965b0-3f9c-4bf9-8a30-8d792622d922@moreton-family.com> Message-ID: <48168436-691d-4666-ba3d-091c6bc97251@pascalprogramming.org> Op 6-7-2025 om 16:31 schreef J. Gareth Moreton via fpc-devel: > What I mean is that if you want to instantiate an object of class > TFoo, you'd call TFoo.Create, not TFooClass.Create. I also don't see the real value of that "feature", but iirc it was added since Delphi allows it. From gareth at moreton-family.com Sun Jul 6 16:52:15 2025 From: gareth at moreton-family.com (J. Gareth Moreton) Date: Sun, 6 Jul 2025 15:52:15 +0100 Subject: [fpc-devel] "class of TFoo".Create In-Reply-To: <48168436-691d-4666-ba3d-091c6bc97251@pascalprogramming.org> References: <399c0ad6-dfb0-4f32-a685-3d29eb576060@moreton-family.com> <804965b0-3f9c-4bf9-8a30-8d792622d922@moreton-family.com> <48168436-691d-4666-ba3d-091c6bc97251@pascalprogramming.org> Message-ID: Going by what Martin just said, should this throw a warning, at least if not in Delphi mode?? Or an error?? This "feature" being used is more likely due to a programming bug and I feel that the developer's attention should be drawn to it so it can be replaced with TFoo.Create if that's what they meant, or a metaclass variable. Kit On 06/07/2025 15:41, Marco van de Voort via fpc-devel wrote: > > Op 6-7-2025 om 16:31 schreef J. Gareth Moreton via fpc-devel: >> What I mean is that if you want to instantiate an object of class >> TFoo, you'd call TFoo.Create, not TFooClass.Create. > > I also don't see the real value of that "feature", but iirc it was > added since Delphi allows it. > > > _______________________________________________ > fpc-devel maillist? -? fpc-devel at lists.freepascal.org > https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel > -- This email has been checked for viruses by Avast antivirus software. www.avast.com From lazarus at mfriebe.de Fri Jul 25 13:44:21 2025 From: lazarus at mfriebe.de (Martin Frb) Date: Fri, 25 Jul 2025 13:44:21 +0200 Subject: [fpc-devel] generic constraints... Message-ID: Currently you can't do type ? generic TFoo = class ???? procedure Bar; virtual; ? end; ? generic FooChild = class(F) ???? procedure Bar; override; ? end; However, without giving the TFoo you can't do the "Bar; override", because it wont know that the base class has a virtual Bar method. In many case you can make the first class non generic. But if you have several generics like that and they all take base classes as generic param, in order to then do something like TFinal = class( ?? specialize TBase1< ? ?? specialize TBase2< ??? ? ?? specialize TBase3 ?? ? > ?? > ) end; Then they all must be generics.... So in that case it would be nice to allow the generic as constraint. --------------------------- On a related note, if building classes like that, there is another problem... ? generic TClassExtender = class(B) ???? constructor Create; // override ???? // same for other methods ? end; ?? constructor TClassExtender.Create; ?? begin ???? inherited; ???? MyInit; ? end; the? base class used in specialization may have a constructor that takes arguments.... Then you can't override/reintroduce those, because you don't yet know all the base classes. It would be nice to have something (idea wise / not syntax wise) ? generic TClassExtender = class(B) ???? generic override constructor Create; // override ???? // same for other methods ? end; That would create the same constructor for each version the base class has. - call the correct inherited - have the same code around the inherit Not sure if this should be limited for virtual/override / or be for any method. (same for ordinary methods) From nc-gaertnma at netcologne.de Fri Jul 25 15:20:54 2025 From: nc-gaertnma at netcologne.de (Mattias Gaertner) Date: Fri, 25 Jul 2025 15:20:54 +0200 Subject: [fpc-devel] generic constraints... In-Reply-To: References: Message-ID: <86fbbd34-adde-4f42-b456-2526c8e584ac@netcologne.de> On 7/25/25 13:44, Martin Frb via fpc-devel wrote: > Currently you can't do > > type > ? generic TFoo = class > ???? procedure Bar; virtual; > ? end; > > ? generic FooChild = class(F) > ???? procedure Bar; override; > ? end; Can you use: generic FooChild = class(specialize TFoo) procedure Bar; override; end; ? Mattias From lazarus at mfriebe.de Fri Jul 25 16:31:12 2025 From: lazarus at mfriebe.de (Martin Frb) Date: Fri, 25 Jul 2025 16:31:12 +0200 Subject: [fpc-devel] generic constraints... In-Reply-To: <86fbbd34-adde-4f42-b456-2526c8e584ac@netcologne.de> References: <86fbbd34-adde-4f42-b456-2526c8e584ac@netcologne.de> Message-ID: On 25/07/2025 15:20, Mattias Gaertner via fpc-devel wrote: > > > On 7/25/25 13:44, Martin Frb via fpc-devel wrote: >> Currently you can't do >> >> type >> ?? generic TFoo = class >> ????? procedure Bar; virtual; >> ?? end; >> >> ?? generic FooChild = class(F) >> ????? procedure Bar; override; >> ?? end; > > Can you use: > > ?? generic FooChild = class(specialize TFoo) > ????? procedure Bar; override; > ?? end; > ? No. One example is that I have several ? TItem1, TItem2, TItem3,... and for each a ? ? TItem1List = specialize TFpgList; But I don't actually use TItem1, .... I use ? TMyFinalItem1 = ?????? specialize TFeatureX< ?????????? specialize TFeatureY< ?????????????? specialize TFeatureZ< TItem1 > ????????? > ????? >; And each list needs to be ? TMyFinalItem1 = ?????? specialize TFeatureXForList< ?????????? specialize TFeatureYForList< ?????????????? specialize TFeatureZForList< specialize TFpgList ? > ????????? > ????? >; Currently I can swap the order, and git it working by creating a non generic base.... But that introduces dependencies that were not wanted... Also, the error by the compiler is ???? Error: Generics without specialization cannot be used as a type for a variable But ?? generic FooChild = class(F) - F is not a variable - TFoo in not a type (for somethnig), TFoo is a constraint If that syntax was allowed, it should mean that -? F must be of any type that is (a descendand of) a specialization of TFoo. So this is NOT to allow FooChild to be specialized with another generic, but with a (any) specialization of that generic. From lazarus at mfriebe.de Tue Jul 29 09:18:16 2025 From: lazarus at mfriebe.de (Martin Frb) Date: Tue, 29 Jul 2025 09:18:16 +0200 Subject: [fpc-devel] generic forward declaration? Message-ID: <3be55a53-f6d6-4aaa-87c6-e9b7feea33bf@mfriebe.de> Are there? Or is there something else? The below compiles. No duplicate TBar. Looks like a forward declaration... program Project1;{$Mode objfpc} type ? generic TBar = class; // forward ? generic TBar = class ??? F:A; ??? X:B; ? end; begin end. But the next does not compile "Identifier not found TBar" (inside TFoo). Yet the identifier is clearly there. https://gitlab.com/freepascal.org/fpc/source/-/issues/24097 seems to say it is supported since 2022? program Project1; {$Mode objfpc} type ? generic TBar = class; // forward ? generic TFoo = class ??? F:specialize TBar; ??? X:B; ? end; ? generic TBar = class ??? F:specialize TFoo; ??? X:B; ? end; begin end. From michael at freepascal.org Tue Jul 29 09:36:41 2025 From: michael at freepascal.org (Michael Van Canneyt) Date: Tue, 29 Jul 2025 09:36:41 +0200 (CEST) Subject: [fpc-devel] generic forward declaration? In-Reply-To: <3be55a53-f6d6-4aaa-87c6-e9b7feea33bf@mfriebe.de> References: <3be55a53-f6d6-4aaa-87c6-e9b7feea33bf@mfriebe.de> Message-ID: <696b2b02-db2e-0d55-2c4e-37f22d58a248@freepascal.org> On Tue, 29 Jul 2025, Martin Frb via fpc-devel wrote: > Are there? Or is there something else? > > The below compiles. No duplicate TBar. Looks like a forward declaration... > > program Project1;{$Mode objfpc} > type > ? generic TBar = class; // forward > > ? generic TBar = class > ??? F:A; > ??? X:B; > ? end; > > begin > end. > > > > But the next does not compile "Identifier not found TBar" (inside TFoo). > Yet the identifier is clearly there. > > https://gitlab.com/freepascal.org/fpc/source/-/issues/24097 seems to say > it is supported since 2022? > > program Project1; > {$Mode objfpc} > type > > ? generic TBar = class; // forward > > ? generic TFoo = class > ??? F:specialize TBar; You're missing a type parameter here. According to the definition, TBar needs 2 type parameters. > ??? X:B; > ? end; > > ? generic TBar = class > ??? F:specialize TFoo; Same here, you're missing a type parameter. TFoo needs 2 type parameters. if you fix that (I added B in both cases, just to test) it compiles. Michael. From nc-gaertnma at netcologne.de Tue Jul 29 09:53:32 2025 From: nc-gaertnma at netcologne.de (Mattias Gaertner) Date: Tue, 29 Jul 2025 09:53:32 +0200 Subject: [fpc-devel] generic constraints... In-Reply-To: References: <86fbbd34-adde-4f42-b456-2526c8e584ac@netcologne.de> Message-ID: <6f50168d-6e0d-420a-910f-9214bbf9282f@netcologne.de> On 7/25/25 16:31, Martin Frb via fpc-devel wrote: > On 25/07/2025 15:20, Mattias Gaertner via fpc-devel wrote: >> >> >> On 7/25/25 13:44, Martin Frb via fpc-devel wrote: >>> Currently you can't do >>> >>> type >>> ?? generic TFoo = class >>> ????? procedure Bar; virtual; >>> ?? end; >>> >>> ?? generic FooChild = class(F) >>> ????? procedure Bar; override; >>> ?? end; >[...] > No. > > One example is that I have several > ? TItem1, TItem2, TItem3,... > and for each a > ? ? TItem1List = specialize TFpgList; > > But I don't actually use TItem1, .... > > I use > ? TMyFinalItem1 = > ?????? specialize TFeatureX< > ?????????? specialize TFeatureY< > ?????????????? specialize TFeatureZ< TItem1 > > ????????? > > ????? >; > > And each list needs to be > ? TMyFinalItem1 = > ?????? specialize TFeatureXForList< > ?????????? specialize TFeatureYForList< > ?????????????? specialize TFeatureZForList< specialize TFpgList > ? > > ????????? > > ????? >; IMO that does not look human friendly for reading and debugging. > Currently I can swap the order, and git it working by creating a non > generic base.... But that introduces dependencies that were not wanted... > > > Also, the error by the compiler is > ???? Error: Generics without specialization cannot be used as a type > for a variable > > But > ?? generic FooChild = class(F) > > - F is not a variable > - TFoo in not a type (for somethnig), TFoo is a constraint The problem is the ambiguity of TFoo, because Delphi (aka modeswitch) distinguishes TFoo, TFoo<> and TFoo<,>: type generic TFoo = class procedure Bar; virtual; end; generic TFoo = class procedure NoBar; virtual; end; generic FooChild = class(F) procedure Bar; override; end; So you have to be more specific: generic FooChild> = class(F) procedure Bar; override; end; > If that syntax was allowed, it should mean that > -? F must be of any type that is (a descendand of) a specialization of > TFoo. > > So this is NOT to allow FooChild to be specialized with another generic, > but with a (any) specialization of that generic. AFAIK there is currently no "Any" placeholder in constraints. It would be something like generic FooChild> = ... Although that looks like something was forgotten. Maybe better: generic FooChild> = ... Mattias From michael at freepascal.org Tue Jul 29 09:58:44 2025 From: michael at freepascal.org (Michael Van Canneyt) Date: Tue, 29 Jul 2025 09:58:44 +0200 (CEST) Subject: [fpc-devel] generic constraints... In-Reply-To: <6f50168d-6e0d-420a-910f-9214bbf9282f@netcologne.de> References: <86fbbd34-adde-4f42-b456-2526c8e584ac@netcologne.de> <6f50168d-6e0d-420a-910f-9214bbf9282f@netcologne.de> Message-ID: <73e3439a-a962-72c0-f356-c1e2c75b5fd1@freepascal.org> On Tue, 29 Jul 2025, Mattias Gaertner via fpc-devel wrote: >> >> And each list needs to be >> ? TMyFinalItem1 = >> ?????? specialize TFeatureXForList< >> ?????????? specialize TFeatureYForList< >> ?????????????? specialize TFeatureZForList< specialize TFpgList >> ? > >> ????????? > >> ????? >; > > IMO that does not look human friendly for reading and debugging. Let's hope it was a contrived example :-) > > >> Currently I can swap the order, and git it working by creating a non >> generic base.... But that introduces dependencies that were not wanted... >> >> >> Also, the error by the compiler is >> ???? Error: Generics without specialization cannot be used as a type >> for a variable >> >> But >> ?? generic FooChild = class(F) >> >> - F is not a variable >> - TFoo in not a type (for somethnig), TFoo is a constraint > > The problem is the ambiguity of TFoo, because Delphi (aka modeswitch) > distinguishes TFoo, TFoo<> and TFoo<,>: > > type > generic TFoo = class > procedure Bar; virtual; > end; > generic TFoo = class > procedure NoBar; virtual; > end; > > generic FooChild = class(F) > procedure Bar; override; > end; > > So you have to be more specific: > > generic FooChild> = class(F) > procedure Bar; override; > end; > > >> If that syntax was allowed, it should mean that >> -? F must be of any type that is (a descendand of) a specialization of >> TFoo. >> >> So this is NOT to allow FooChild to be specialized with another generic, >> but with a (any) specialization of that generic. > > AFAIK there is currently no "Any" placeholder in constraints. It would > be something like > generic FooChild> = ... > > Although that looks like something was forgotten. Maybe better: > > generic FooChild> = ... it seems to me that 'specialized' is not compatible with 'any', as specialized needs a specific type: it actually creates the type. So that would need to become something like generic FooChild> = .. Michael. From lazarus at mfriebe.de Tue Jul 29 10:03:20 2025 From: lazarus at mfriebe.de (Martin Frb) Date: Tue, 29 Jul 2025 10:03:20 +0200 Subject: [fpc-devel] generic constraints... In-Reply-To: <6f50168d-6e0d-420a-910f-9214bbf9282f@netcologne.de> References: <86fbbd34-adde-4f42-b456-2526c8e584ac@netcologne.de> <6f50168d-6e0d-420a-910f-9214bbf9282f@netcologne.de> Message-ID: <5103b439-9ebe-4128-91b9-3e9e440589fd@mfriebe.de> On 29/07/2025 09:53, Mattias Gaertner via fpc-devel wrote: > > On 7/25/25 16:31, Martin Frb via fpc-devel wrote: >> >> But >> ??? generic FooChild = class(F) >> >> - F is not a variable >> - TFoo in not a type (for somethnig), TFoo is a constraint > > The problem is the ambiguity of TFoo, because Delphi (aka modeswitch) > distinguishes TFoo, TFoo<> and TFoo<,>: Ok, yes. If ever a generic parameter can refer to an (non specialized) generic ??? generic Foo = class ? ? ? type TSome = G ; Then the name of the generic can not be used as "any specialized type of that generic" Unless it then needs to be prefixed ??? generic Foo = class And/or less constrained ??? generic Foo = class > > AFAIK there is currently no "Any" placeholder in constraints. It would > be something like > ? generic FooChild> = ... > > Although that looks like something was forgotten. Maybe better: > > ? generic FooChild> = ... Would be nice to have. It also needs the placeholders to be able to distinguish ? generic TBar ? generic TBar ? generic FooChild) = ... ? generic FooChild) = ... not sure if it should really say "specialize" (even in objfpc) because it isn't doing it, it is expecting it to be done elsewhere. @FPC Team: Worth a feature request? From lazarus at mfriebe.de Tue Jul 29 20:57:27 2025 From: lazarus at mfriebe.de (Martin Frb) Date: Tue, 29 Jul 2025 20:57:27 +0200 Subject: [fpc-devel] generic forward declaration? In-Reply-To: <696b2b02-db2e-0d55-2c4e-37f22d58a248@freepascal.org> References: <3be55a53-f6d6-4aaa-87c6-e9b7feea33bf@mfriebe.de> <696b2b02-db2e-0d55-2c4e-37f22d58a248@freepascal.org> Message-ID: <8a1a9a41-c6d3-4b4d-9c6e-9c2c150ac46c@mfriebe.de> On 29/07/2025 09:36, Michael Van Canneyt wrote: > Same here, you're missing a type parameter. TFoo needs 2 type parameters. Ups, thanks. Any obvious? (or non obvious) mistake of mine in the below? Because either of the 2 commented specialize cause errors in the generics... (but only if TFoo.F? SWAPS the order of param). It compiles fine - with both the specialize commented - or with TBar replacing "F" with the commented "F" program Project1; {$Mode objfpc} type ? generic TBar = class; // forward?? // LINE 5 ? generic TFoo = class ??? F:specialize TBar; ??? X:B; ? end;????? // LINE 10 ? generic TBar = class ??? F:specialize TFoo; ??? //F:specialize TFoo; ??? X:B; ? end; ? //x1 = specialize TBar;? // project1.lpr(5,28) Fatal: Syntax error, "identifier" expected but ";" found ? //x2 = specialize TFoo; // project1.lpr(10,6) Fatal: Syntax error, "identifier" expected but ";" found begin end. From pascaldragon at googlemail.com Tue Jul 29 23:39:13 2025 From: pascaldragon at googlemail.com (Sven Barth) Date: Tue, 29 Jul 2025 23:39:13 +0200 Subject: [fpc-devel] generic forward declaration? In-Reply-To: <8a1a9a41-c6d3-4b4d-9c6e-9c2c150ac46c@mfriebe.de> References: <3be55a53-f6d6-4aaa-87c6-e9b7feea33bf@mfriebe.de> <696b2b02-db2e-0d55-2c4e-37f22d58a248@freepascal.org> <8a1a9a41-c6d3-4b4d-9c6e-9c2c150ac46c@mfriebe.de> Message-ID: Martin Frb via fpc-devel schrieb am Di., 29. Juli 2025, 20:57: > On 29/07/2025 09:36, Michael Van Canneyt wrote: > > Same here, you're missing a type parameter. TFoo needs 2 type parameters. > > Ups, thanks. > > Any obvious (or non obvious) mistake of mine in the below? > > Because either of the 2 commented specialize cause errors in the > generics... (but only if TFoo.F SWAPS the order of param). > > It compiles fine > - with both the specialize commented > - or with TBar replacing "F" with the commented "F" > > > > program Project1; > {$Mode objfpc} > type > > generic TBar = class; // forward // LINE 5 > > generic TFoo = class > F:specialize TBar; > X:B; > end; // LINE 10 > > generic TBar = class > F:specialize TFoo; > //F:specialize TFoo; > X:B; > end; > > //x1 = specialize TBar; // project1.lpr(5,28) Fatal: > Syntax error, "identifier" expected but ";" found > //x2 = specialize TFoo; // project1.lpr(10,6) Fatal: > Syntax error, "identifier" expected but ";" found > > begin > > end. > Please report a bug. Though this might end up not compiling nevertheless due to the specialization chain going ad infinitum... Regards, Sven > -------------- next part -------------- An HTML attachment was scrubbed... URL: From lazarus at mfriebe.de Wed Jul 30 11:44:59 2025 From: lazarus at mfriebe.de (Martin Frb) Date: Wed, 30 Jul 2025 11:44:59 +0200 Subject: [fpc-devel] generic forward declaration? In-Reply-To: References: <3be55a53-f6d6-4aaa-87c6-e9b7feea33bf@mfriebe.de> <696b2b02-db2e-0d55-2c4e-37f22d58a248@freepascal.org> <8a1a9a41-c6d3-4b4d-9c6e-9c2c150ac46c@mfriebe.de> Message-ID: <9ad1f881-4925-4d4b-9615-4848ba388e9c@mfriebe.de> On 29/07/2025 23:39, Sven Barth via fpc-devel wrote: > > Please report a bug. Though this might end up not compiling > nevertheless due to the specialization chain going ad infinitum... > https://gitlab.com/freepascal.org/fpc/source/-/issues/41349 It does not need to go ad infinitum. In the interface, when it encounters the circle, it only needs to know that this is a class (as it does for normal circular class references.) However, I can see that it is trickier. Because it does need to do the specialisation at some point, so it's available during compiling the implementation. And because the circle can be any amount of steps (greater than 2), it can't defer it until implementation, because if there are more than one step left, then the issue would likely happen then. I can (with my non existing knowledge of the internals) **imagine** 2 scenarios. It goes into recursion immediately, but - detects when it needs to specialize something that is "in progress" - it does not go into recursion, but adds it to a "todo list", which is processed after the currents specialize. Of course, it still needs an abort for endless recursion, if it keeps creating new types (e.g. each loop inherits and extends the passed in type) From nc-gaertnma at netcologne.de Wed Jul 30 12:23:59 2025 From: nc-gaertnma at netcologne.de (Mattias Gaertner) Date: Wed, 30 Jul 2025 12:23:59 +0200 Subject: [fpc-devel] generic forward declaration? In-Reply-To: <9ad1f881-4925-4d4b-9615-4848ba388e9c@mfriebe.de> References: <3be55a53-f6d6-4aaa-87c6-e9b7feea33bf@mfriebe.de> <696b2b02-db2e-0d55-2c4e-37f22d58a248@freepascal.org> <8a1a9a41-c6d3-4b4d-9c6e-9c2c150ac46c@mfriebe.de> <9ad1f881-4925-4d4b-9615-4848ba388e9c@mfriebe.de> Message-ID: <81f07e2e-e05e-48bc-94fb-baa40511da6a@netcologne.de> On 7/30/25 11:44, Martin Frb via fpc-devel wrote: > On 29/07/2025 23:39, Sven Barth via fpc-devel wrote: >> >> Please report a bug. Though this might end up not compiling >> nevertheless due to the specialization chain going ad infinitum... >> > https://gitlab.com/freepascal.org/fpc/source/-/issues/41349 > > It does not need to go ad infinitum. It depends on the compiler implementation. pas2js compiles it. OTOH pas2js currently creates 3 internal specializations for each TFoo and TBar. Mattias From lazarus at mfriebe.de Wed Jul 30 13:01:43 2025 From: lazarus at mfriebe.de (Martin Frb) Date: Wed, 30 Jul 2025 13:01:43 +0200 Subject: [fpc-devel] generic forward declaration? In-Reply-To: <81f07e2e-e05e-48bc-94fb-baa40511da6a@netcologne.de> References: <3be55a53-f6d6-4aaa-87c6-e9b7feea33bf@mfriebe.de> <696b2b02-db2e-0d55-2c4e-37f22d58a248@freepascal.org> <8a1a9a41-c6d3-4b4d-9c6e-9c2c150ac46c@mfriebe.de> <9ad1f881-4925-4d4b-9615-4848ba388e9c@mfriebe.de> <81f07e2e-e05e-48bc-94fb-baa40511da6a@netcologne.de> Message-ID: <66a67b93-104d-44e6-b963-18cd008335ec@mfriebe.de> On 30/07/2025 12:23, Mattias Gaertner via fpc-devel wrote: > > > On 7/30/25 11:44, Martin Frb via fpc-devel wrote: >> On 29/07/2025 23:39, Sven Barth via fpc-devel wrote: >>> >>> Please report a bug. Though this might end up not compiling >>> nevertheless due to the specialization chain going ad infinitum... >>> >> https://gitlab.com/freepascal.org/fpc/source/-/issues/41349 >> >> It does not need to go ad infinitum. > > It depends on the compiler implementation. > > pas2js compiles it. > OTOH pas2js currently creates 3 internal specializations for each TFoo > and TBar. There should only be TFoo TFoo If you got 3 then you got one of them twice. And if they are different types, then at some point you get issues with assigning them to the fields? From nc-gaertnma at netcologne.de Wed Jul 30 13:34:54 2025 From: nc-gaertnma at netcologne.de (Mattias Gaertner) Date: Wed, 30 Jul 2025 13:34:54 +0200 Subject: [fpc-devel] generic forward declaration? In-Reply-To: <66a67b93-104d-44e6-b963-18cd008335ec@mfriebe.de> References: <3be55a53-f6d6-4aaa-87c6-e9b7feea33bf@mfriebe.de> <696b2b02-db2e-0d55-2c4e-37f22d58a248@freepascal.org> <8a1a9a41-c6d3-4b4d-9c6e-9c2c150ac46c@mfriebe.de> <9ad1f881-4925-4d4b-9615-4848ba388e9c@mfriebe.de> <81f07e2e-e05e-48bc-94fb-baa40511da6a@netcologne.de> <66a67b93-104d-44e6-b963-18cd008335ec@mfriebe.de> Message-ID: <6671a481-05e6-439c-aa1e-186967bc5b5a@netcologne.de> On 7/30/25 13:01, Martin Frb via fpc-devel wrote: > On 30/07/2025 12:23, Mattias Gaertner via fpc-devel wrote: >>[...] >> pas2js compiles it. >> OTOH pas2js currently creates 3 internal specializations for each TFoo >> and TBar. > > There should only be > > TFoo > TFoo Yes. Well, actually, in your example you don't use them, so pas2js omits a lot. But internally while resolving the code it already creates a specialization for F generic TFoo = class F:specialize TBar; with the generic template parameter A and B, so it can resolve and check the generic code. This specialization is never transpiled to code. It merely exists for type checking. It's a todo to create less of these internal specializations. > If you got 3 then you got one of them twice. And if they are different > types, then at some point you get issues with assigning them to the fields? Each generic type in pas2js has a list of specializations with each combination of parameters unique. This is enough for simple programs, but for packages Delphi supports duplicate specializations. Mattias