Recent

Author Topic: Set var to a procedure with a different param type  (Read 303 times)

OkobaPatino

  • Full Member
  • ***
  • Posts: 165
Set var to a procedure with a different param type
« on: November 22, 2020, 10:44:05 am »
Why compiler allows setting T to TestInt2, considering it should not get TInt1? I thought the correct way is to raise an error just like setting it to TestString.
Is this a bug, or am I missing something?

Code: Pascal  [Select][+][-]
  1. program Project1;
  2.  
  3. type
  4.   TInt1 = type integer;
  5.   PInt1 = ^TInt1;
  6.   TInt2 = type integer;
  7.   PInt2 = ^TInt2;
  8.   TTestInt1 = procedure(A: PInt1);
  9.   TTestInt2 = procedure(A: PInt2);
  10.  
  11.   procedure TestInt1(A: PInt1);
  12.   begin
  13.     WriteLn('1');
  14.   end;
  15.  
  16.   procedure TestInt2(A: PInt2);
  17.   begin
  18.     WriteLn('2');
  19.   end;
  20.  
  21.   procedure TestString(A: PString);
  22.   begin
  23.  
  24.   end;
  25.  
  26. var
  27.   T: TTestInt1;
  28. begin
  29.   T := @TestInt2;   //Allows this
  30.   T := @TestString; //Does not allow this
  31. end.

lucamar

  • Hero Member
  • *****
  • Posts: 3188
Re: Set var to a procedure with a different param type
« Reply #1 on: November 22, 2020, 01:31:01 pm »
Most probably because they are both "aliases" to the same type, rather than two new types. IIRC the compiler ends up treating both types of pointers as if they were both PInt = ^Integer.

Try declaring them as:

Code: Pascal  [Select][+][-]
  1. type
  2.   TInt1 = integer;
  3.   PInt1 = ^TInt1;
  4.   TInt2 = integer;
  5.   PInt2 = ^TInt2;

and you might see the difference.

Though I might be wrong; this is off the top of my head, whch is rather full right now :-[
Turbo Pascal 3 CP/M - Amstrad PCW 8256 (512 KB !!!) :P
Lazarus/FPC 2.0.8/3.0.4 & 2.0.10/3.2.0 - 32/64 bits on:
(K|L|X)Ubuntu 12..18, Windows XP, 7, 10 and various DOSes.

PascalDragon

  • Hero Member
  • *****
  • Posts: 2405
  • Compiler Developer
Re: Set var to a procedure with a different param type
« Reply #2 on: November 22, 2020, 01:33:34 pm »
Is this a bug, or am I missing something?

I would say that it is a bug. Delphi doesn't allow it either (at least as long as one doesn't forget to remove the @-operators, otherwise it won't complain for either one...)

Most probably because they are both "aliases" to the same type, rather than two new types.

Exactly that is the point of the type modifier however.

OkobaPatino

  • Full Member
  • ***
  • Posts: 165
Re: Set var to a procedure with a different param type
« Reply #3 on: November 22, 2020, 01:42:45 pm »
Tried Delphi and with @ operator, it will allow for compile.
Here is the report: https://bugs.freepascal.org/view.php?id=38115

Kays

  • Full Member
  • ***
  • Posts: 229
  • Whasup!?
    • KaiBurghardt.de
Re: Set var to a procedure with a different param type
« Reply #4 on: November 22, 2020, 01:58:24 pm »
[…] I thought the correct way is to raise an error just like setting it to TestString.
Is this a bug, or am I missing something? […]
I would expect that too.

Maybe this is because the “different” types are still assignment-compatible, i.e. something like this works:
Code: Pascal  [Select][+][-]
  1. var
  2.         Int1: TInt1;
  3.         Int2: TInt2;
  4.         Int1Loc: PInt1;
  5.         Int2Loc: PInt2;
  6. begin
  7.         Int1 := 42;
  8.         Int2 := Int1;
  9.        
  10.         Int1Loc := @Int1;
  11.         Int2Loc := Int1Loc;
  12. end.
Implicit typecasts (the := operator) also apply to parameter lists, so it’d be legal to use TestInt2 with a PInt1. I can call TestInt2(Int1Loc);. Hence, FPC has no reason to complain.

To my surprise though, they are nevertheless different:
Code: Pascal  [Select][+][-]
  1. if typeInfo(TInt1) <> typeInfo(TInt2) then
  2. begin
  3.         writeLn('TInt1 and TInt2 are different');
  4. end;
  5. if typeInfo(PInt1) <> typeInfo(PInt2) then
  6. begin
  7.         writeLn('PInt1 and PInt2 are different');
  8. end;
So, technically the type modifier does work.
« Last Edit: November 22, 2020, 02:08:46 pm by Kays »
Yours Sincerely
Kai Burghardt

PascalDragon

  • Hero Member
  • *****
  • Posts: 2405
  • Compiler Developer
Re: Set var to a procedure with a different param type
« Reply #5 on: November 22, 2020, 02:01:36 pm »
Tried Delphi and with @ operator, it will allow for compile.

Yes, because the @-operator simply returns a pointer. For example the following will compile without error as well:

Code: Pascal  [Select][+][-]
  1. type
  2.   TInt1 = type Integer;
  3.   PInt1 = ^TInt1;
  4.   TTestInt1 = procedure(A: PInt1);
  5.  
  6. var
  7.   i: LongInt;
  8.   T: TTestInt1;
  9. begin
  10.   T := @i;
  11. end.

This will only fail if {$T+} or {$TypedAddress On} is set which is not the case by default.

Kays

  • Full Member
  • ***
  • Posts: 229
  • Whasup!?
    • KaiBurghardt.de
Re: Set var to a procedure with a different param type
« Reply #6 on: November 22, 2020, 02:31:01 pm »
[…]
Yes, because the @-operator simply returns a pointer. For example the following will compile without error as well:

[…]

This will only fail if {$T+} or {$TypedAddress On} is set which is not the case by default.
That’s inconsistent then. OkobaPatino’s program should compile without errors then, too. Nevertheless, FPC does not accept the address of the TestString procedure to be assigned to a procedural variable that only accepts TTestInt1 procedures. FPC’s error message is pretty specific about that:
Code: Text  [Select][+][-]
  1. project1.pas(30,8) Error: Incompatible types: got "<address of procedure(PString);Register>" expected "<procedure variable type of procedure(PInt1);Register>"
I guess the @ we are using here is not the “real” address operator you can control by {$typedAddress on}. After all, the {$modeSwitch classicProcVars+} does allow you to omit it, so the fact that we are writing @ before routine names is just some random syntax requirement, but the compiler can theoretically do without it, you don’t need to write an operator.

I think the actual issue is that there is no operator definition
Code: Pascal  [Select][+][-]
  1. operator := (p: PInt2): PString;
« Last Edit: November 22, 2020, 02:46:02 pm by Kays »
Yours Sincerely
Kai Burghardt

jamie

  • Hero Member
  • *****
  • Posts: 3790
Re: Set var to a procedure with a different param type
« Reply #7 on: November 22, 2020, 02:34:29 pm »
Code: Pascal  [Select][+][-]
  1. /// As was code above
  2.  var
  3.  T: TTestInt1;
  4.  begin
  5.    T := @TestInt2;   //Allows this
  6.    Pointer(T):= @TestString; //Does not allow this << changes here.
  7.  end;                                                        
  8.  

I would like to know what campaign trip he is on.


The only true wisdom is knowing you know nothing

PascalDragon

  • Hero Member
  • *****
  • Posts: 2405
  • Compiler Developer
Re: Set var to a procedure with a different param type
« Reply #8 on: November 22, 2020, 06:17:21 pm »
[…]
Yes, because the @-operator simply returns a pointer. For example the following will compile without error as well:

[…]

This will only fail if {$T+} or {$TypedAddress On} is set which is not the case by default.
That’s inconsistent then. OkobaPatino’s program should compile without errors then, too.

FPC accepts it in mode Delphi. However if you use mode ObjFPC the compiler stays strict (except for this - in my opinion - bug).

I think the actual issue is that there is no operator definition
Code: Pascal  [Select][+][-]
  1. operator := (p: PInt2): PString;

And that is complete nonsense. The assignment operator of a type that's a parameter type is not at all inolved when assigning a procedure to a procedure variable.

Code: Pascal  [Select][+][-]
  1. /// As was code above
  2.  var
  3.  T: TTestInt1;
  4.  begin
  5.    T := @TestInt2;   //Allows this
  6.    Pointer(T):= @TestString; //Does not allow this << changes here.
  7.  end;                                                        
  8.  

I would like to know what campaign trip he is on.

The compiler assumes that it's a call to the procedure variable T. This is Delphi compatible.

 

TinyPortal © 2005-2018