Author Topic: New compile time operator "type of" (modeswitch TypeInquiry)  (Read 1141 times)

mattias

  • Administrator
  • Full Member
  • *
  • Posts: 221
    • http://www.lazarus.freepascal.org
New compile time operator "type of" (modeswitch TypeInquiry)
« on: September 28, 2026, 08:57:28 pm »
Hi all,

FPC trunk (3.3.1) has a new compile time operator:

type of <operand>

It gives the type of a variable, field, property, constant, function result or expression, and works wherever a type is allowed. The operand is only type checked, never evaluated.

It is on by default in {$mode objfpc} and {$mode extendedpascal}. In other modes use {$modeswitch typeinquiry}.

It is useful to refer to anonymous, combined or derived types.

Examples:

Code: Pascal  [Select][+][-]
  1. {$mode ObjFPC}
  2. var
  3.   Count: word;
  4.   List: array of type of Count;      // = array of word
  5.   Sum: type of (Count+Rec.X);        // type of an expression
  6.   v: type of Foo(SomeByte);          // result type, Foo is not called
  7.  
  8. type
  9.   TUniqueCount = type type of Count; // distinct type
  10.  
  11.   generic function Add<S,T>(a: S; b: T): type of (S+T);
  12.  
  13.   TRec = record
  14.     a: int64;
  15.     b: type of a;                    // sibling field
  16.   end;
  17.  
  18.   generic TGiraffe<PT> = class
  19.   public type
  20.     T = type of PT^;                 // TGiraffe<PWord>.T = word
  21.   end;
  22.  
  23.   x := type of Count(SomeLongint);   // type cast
  24.   n := SizeOf(type of Count);
  25.  

Notes:
- "type of Integer" is an error: the operand must not be a bare type.
- "type of a+b" means "(type of a)+b". Write "type of (a+b)".
- In generics the operand is resolved at specialization.

fcl-passrc and pas2js support it too.

jamie

  • Hero Member
  • *****
  • Posts: 8030
Re: New compile time operator "type of" (modeswitch TypeInquiry)
« Reply #1 on: September 28, 2026, 11:20:46 pm »
Great, I believe I asked for something like that long ago where I could reference a type by an instance.

Wonder if it would work with a untyped variable of a function parameter whereas Type of could be used within a parsing of a function?

Code: Pascal  [Select][+][-]
  1. Function Test(var item, Size:Integer = SizeOf(Type of Item));
  2. Begin
  3.  // with this, it would capture what the compiler passes at the time of call, since ITEM has no type attached to it
  4. end;
  5.  

Just A thought.
The only true wisdom is knowing you know nothing

PascalDragon

  • Hero Member
  • *****
  • Posts: 6451
  • Compiler Developer
Re: New compile time operator "type of" (modeswitch TypeInquiry)
« Reply #2 on: October 01, 2026, 10:47:35 pm »
Wonder if it would work with a untyped variable of a function parameter whereas Type of could be used within a parsing of a function?

No. Item does not have a type thus the type inquiry does not work for that.

For this specific use case a non-completed feature sleeping inside the compiler would be better: open type parameters.

Code: Pascal  [Select][+][-]
  1. procedure Test(var Item: type);
  2. begin
  3.   // evaluate size using TypeInfo(Item)
  4. end;

In contrast to formal parameters for open type parameters a hidden parameter would contain a reference to the type information of the passed in parameter, thus TypeInfo(Param) would work unlike for a formal parameter.

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 13018
  • FPC developer.
Re: New compile time operator "type of" (modeswitch TypeInquiry)
« Reply #3 on: October 02, 2026, 12:55:01 pm »
It gives the type of a variable, field, property, constant, function result or expression, and works wherever a type is allowed. The operand is only type checked, never evaluated.

I assume it follows usual type promotion rules in case of a mixed expression (uint32+int32 means int64) ?


zamtmn

  • Hero Member
  • *****
  • Posts: 703
Re: New compile time operator "type of" (modeswitch TypeInquiry)
« Reply #4 on: October 03, 2026, 02:58:16 pm »
>>is an error: the operand must not be a bare type
I propose allowing this for procedural types:
Code: Pascal  [Select][+][-]
  1. ...//in other unit:
  2. interface
  3. type
  4.   TMyMethod=function(AArg:integer):integer of object;
  5.   TMyFunc=function(AArg:integer):integer;
  6.  
  7.  
  8. ...//in my unit:
  9. type
  10.   TmyClass=class
  11.     MyMethod type of TMyMethod;
  12.   end;
  13.  
  14. TmyClass.MyMethod type of TMyFunc;
  15. begin
  16.   result:=0;
  17. end;
  18.  
  19. MyFunc type of TMyFunc;
  20. begin
  21.   result:=0;
  22. end;
  23. ...
  24.  
« Last Edit: October 03, 2026, 03:09:39 pm by zamtmn »

Thaddy

  • Hero Member
  • *****
  • Posts: 19966
  • Pointless static linking author
Re: New compile time operator "type of" (modeswitch TypeInquiry)
« Reply #5 on: October 03, 2026, 04:21:03 pm »
>>is an error: the operand must not be a bare type
I propose allowing this for procedural types:
Code: Pascal  [Select][+][-]
  1. ...//in other unit:
  2. interface
  3. type
  4.   TMyMethod=function(AArg:integer):integer of object;
  5.   TMyFunc=function(AArg:integer):integer;
  6.  
  7.  
  8. ...//in my unit:
  9. type
  10.   TmyClass=class
  11.     MyMethod type of TMyMethod;
  12.   end;
  13.  
  14. TmyClass.MyMethod type of TMyFunc;
  15. begin
  16.   result:=0;
  17. end;
  18.  
  19. MyFunc type of TMyFunc;
  20. begin
  21.   result:=0;
  22. end;
  23. ...
  24.  
That is a misunderstanding of the feature. In the above you connect the type to an instance. That is bogus. The feature constructs a type from an instance.

That said, this compiles cleanly, but throws an exception:
Code: Pascal  [Select][+][-]
  1. {$mode objfpc}{$modeswitch advancedrecords}
  2. type
  3.   Tproc = procedure;
  4.  
  5.   procedure test;
  6.   begin
  7.     writeln('proc');
  8.   end;
  9.  
  10. const
  11.   proc:Tproc = @Test;
  12. type
  13.   TRecord = record
  14.     p:type of proc;
  15.     c,d:double;
  16.   end;
  17.  
  18. var
  19.   a:TRecord;
  20. begin
  21.   a.p();
  22. end.
And that is legal syntax...
« Last Edit: October 03, 2026, 05:02:50 pm by Thaddy »
Any "programmer" that knows only one programming language is not a programmer

jamie

  • Hero Member
  • *****
  • Posts: 8030
Re: New compile time operator "type of" (modeswitch TypeInquiry)
« Reply #6 on: October 03, 2026, 06:36:10 pm »
>>is an error: the operand must not be a bare type
I propose allowing this for procedural types:
Code: Pascal  [Select][+][-]
  1. ...//in other unit:
  2. interface
  3. type
  4.   TMyMethod=function(AArg:integer):integer of object;
  5.   TMyFunc=function(AArg:integer):integer;
  6.  
  7.  
  8. ...//in my unit:
  9. type
  10.   TmyClass=class
  11.     MyMethod type of TMyMethod;
  12.   end;
  13.  
  14. TmyClass.MyMethod type of TMyFunc;
  15. begin
  16.   result:=0;
  17. end;
  18.  
  19. MyFunc type of TMyFunc;
  20. begin
  21.   result:=0;
  22. end;
  23. ...
  24.  

That looks counter intuitive?

In the case you presented, that Type is already known because you just gave it that.

Jamie

The only true wisdom is knowing you know nothing

zamtmn

  • Hero Member
  • *****
  • Posts: 703
Re: New compile time operator "type of" (modeswitch TypeInquiry)
« Reply #7 on: October 03, 2026, 07:06:38 pm »
@Thaddy
As usual, you’re on some wavelength that only you understand

@jamie
The point is to avoid writing the function signature in many different places.

Thaddy

  • Hero Member
  • *****
  • Posts: 19966
  • Pointless static linking author
Re: New compile time operator "type of" (modeswitch TypeInquiry)
« Reply #8 on: October 05, 2026, 06:15:41 pm »
@Thaddy
As usual, you’re on some wavelength that only you understand
Hence my example: Compiles. Doesn't run. Should run.
Any "programmer" that knows only one programming language is not a programmer

PascalDragon

  • Hero Member
  • *****
  • Posts: 6451
  • Compiler Developer
Re: New compile time operator "type of" (modeswitch TypeInquiry)
« Reply #9 on: October 05, 2026, 10:18:01 pm »
>>is an error: the operand must not be a bare type
I propose allowing this for procedural types:
Code: Pascal  [Select][+][-]
  1. ...//in other unit:
  2. interface
  3. type
  4.   TMyMethod=function(AArg:integer):integer of object;
  5.   TMyFunc=function(AArg:integer):integer;
  6.  
  7.  
  8. ...//in my unit:
  9. type
  10.   TmyClass=class
  11.     MyMethod type of TMyMethod;
  12.   end;
  13.  
  14. TmyClass.MyMethod type of TMyFunc;
  15. begin
  16.   result:=0;
  17. end;
  18.  
  19. MyFunc type of TMyFunc;
  20. begin
  21.   result:=0;
  22. end;
  23. ...
  24.  

A method declaration is not a type, so no, something like this will not be added. Pascal is intended for ease of readability, your suggestion is anything but.

zamtmn

  • Hero Member
  • *****
  • Posts: 703
Re: New compile time operator "type of" (modeswitch TypeInquiry)
« Reply #10 on: October 05, 2026, 10:23:44 pm »
>>your suggestion is anything but

I agree that this syntax is not the most suitable. But having the ability to declare a procedure/method of an already known signature instead of copy‑pasting is a necessary feature.

Thaddy

  • Hero Member
  • *****
  • Posts: 19966
  • Pointless static linking author
Re: New compile time operator "type of" (modeswitch TypeInquiry)
« Reply #11 on: October 06, 2026, 06:29:56 am »
>>your suggestion is anything but

I agree that this syntax is not the most suitable. But having the ability to declare a procedure/method of an already known signature instead of copy‑pasting is a necessary feature.
We have already procedure variables for that:
Code: Pascal  [Select][+][-]
  1. {$mode delphi}
  2. type
  3.   Tproc = procedure; // or some more complex signature
  4.  
  5.   procedure p1;
  6.   begin
  7.     writeln('p1');
  8.   end;
  9.  
  10.   procedure p2;
  11.   begin
  12.     writeln('p2');
  13.   end;
  14.  
  15.   procedure Doit(const proc:Tproc);
  16.   begin
  17.     proc()
  18.   end;
  19.    
  20. begin
  21.   DoIt(p1);
  22.   DoIt(p2);
  23. end.
« Last Edit: October 06, 2026, 06:32:05 am by Thaddy »
Any "programmer" that knows only one programming language is not a programmer

H₂SO₄

  • Hero Member
  • *****
  • Posts: 511
Re: New compile time operator "type of" (modeswitch TypeInquiry)
« Reply #12 on: October 06, 2026, 07:04:46 am »
But having the ability to declare a procedure/method of an already known signature instead of copy‑pasting is a necessary feature.

Pascal's separation of interface and implementation invariably leads to copy-pasting method signatures, so yes - it's annoying, but I can't think of a worse hindrance to readability than having the parameter list be hidden behind a type alias.

There's a reason why copy-paste reduction in the form of macros is generally frowned upon:

Code: Pascal  [Select][+][-]
  1. {$macro on}
  2.  
  3. type
  4.   {$define TRead := (var Buffer; Count: Integer): Integer}
  5.   TWrapper = class(TStream)
  6.   private
  7.     Stream: TStream;
  8.   public
  9.     function Read {=} TRead; override;
  10.   end;
  11.  
  12. function TWrapper.Read {=} TRead;
  13. begin
  14.   Result := Stream.Read(Buffer, Count);
  15. end;

zamtmn

  • Hero Member
  • *****
  • Posts: 703
Re: New compile time operator "type of" (modeswitch TypeInquiry)
« Reply #13 on: October 06, 2026, 08:37:07 am »
Thaddy
>>We have already procedure variables for that:
I don’t know how to explain to you what I mean
Code: Pascal  [Select][+][-]
  1. program Project1;
  2. uses SysUtils;
  3. //You’ll copypaste next line from objpash.inc
  4. procedure youExceptProc(Obj : TObject; Addr : CodePointer; FrameCount:Longint; Frame: PCodePointer);
  5. begin
  6. end;
  7. //I suggest finding a way to avoid copy-pasting, for example:
  8. procedure myExceptProc type of TExceptProc;
  9. begin
  10. end;
  11. begin
  12.   ExceptProc:=@myExceptProc;
  13. end.

H₂SO₄
>>but I can't think of a worse hindrance to readability than having the
>>parameter list be hidden behind a type alias.
The signature is available in the IDE with a single click.
« Last Edit: October 06, 2026, 08:44:11 am by zamtmn »

Hobbit00

  • New Member
  • *
  • Posts: 45
Re: New compile time operator "type of" (modeswitch TypeInquiry)
« Reply #14 on: October 06, 2026, 09:31:18 am »
I don’t know how to explain to you what I mean
Code: Pascal  [Select][+][-]
  1. program Project1;
  2. //I suggest finding a way to avoid copy-pasting, for example:
  3. procedure myExceptProc type of TExceptProc;
  4. begin
  5. end;
  6. end.

Writing the implementation this way carries a significant risk, and I strongly urge you not to consider it.
Why?
Because if the definition of "TExceptProc" were to change—for instance—the procedure's implementation would automatically adapt... but its internal code almost certainly would not. This could lead to issues that are extremely difficult to diagnose.

Currently, the definition can be expressed in generic terms (as in Thaddy's example), but the implementation must explicitly list every single parameter—and that is a good thing. If the definition changes (for example, a type switches from Integer to UInt64), the code will fail to compile until someone reviews the implementation (hopefully checking the code itself) and updates the signature.
« Last Edit: October 06, 2026, 09:34:10 am by Hobbit00 »

 

TinyPortal © 2005-2018