Jump to content
rgdawson

Case: Please Explain Why Inline Variable Prevents Compilation

Recommended Posts

I was experimenting with inline variable definitions and came across a case that I do not understand, so I made a very simple example.  See Foo1 and Foo2 below.  The only difference is where I define the variables.  No type inference going on, nothing that unusual to my eyes, except that the type IShared<T>, from Spring4D, is defined as reference to function: T.

 

Foo2 will not compile and I get an error: E2250 There is no overloaded version of 'Post' that can be called with these arguments.

 

procedure Foo1; {<--Compiles}
var
  Http: IShared<TIdHttp>;
  Request  : IShared<TStringStream>;
  Response : IShared<TStringStream>;
begin
  Http := Shared.Make(TIdHttp.Create);
  Request := Shared.Make(TStringStream.Create('Foo'));
  Response := Shared.Make(TStringStream.Create);

  Http.Post('Foo', Request, Response);
end;

procedure Foo2; {<-- Will not compile}
begin
  var Http: IShared<TIdHttp>;
  var Request: IShared<TStringStream>;
  var Response: IShared<TStringStream>;

  Http := Shared.Make(TIdHttp.Create);
  Request := Shared.Make(TStringStream.Create('Foo'));
  Response := Shared.Make(TStringStream.Create);

  Http.Post('Foo', Request, Response);  {<--Fails on this line}  
end;

Can someone explain what is going on here?

 

 

 

 

Share this post


Link to post

I can reproduce the problem in a simple example that doesn't involve Spring4D (however, I get an "E2010 Incompatible types" error instead of an E2250) :

 

type
  IShared<T> = reference to function: T;

  Shared = class
    class function Make<T: class>(AObj: T): IShared<T>;
  end;

  TSharedImpl<T: class> = class(TInterfacedObject, IShared<T>)
    FObj: T;
    constructor Create(AObj: T);
    destructor Destroy; override;
    function Invoke: T;
  end;

  TTest = class
  end;

  TTester = class
    procedure DoTest(AObj: TTest);
  end;

class function Shared.Make<T>(AObj: T): IShared<T>;
begin
  Result := TSharedImpl<T>.Create(AObj) as IShared<T>;
end;

constructor TSharedImpl<T>.Create(AObj: T);
begin
  inherited Create;
  FObj := AObj;
end;

destructor TSharedImpl<T>.Destroy;
begin
  FObj.Free;
  inherited Destroy;
end;

function TSharedImpl<T>.Invoke: T;
begin
  Result := FObj;
end;

procedure TTester.DoTest(AObj: TTest);
begin
  //...
end;

procedure Foo1;
var
  Tester  : IShared<TTester>;
  TestObj : IShared<TTest>;
begin
  Tester := Shared.Make(TTester.Create);
  TestObj := Shared.Make(TTest.Create);

  Tester.DoTest(TestObj); // <-- Compiles OK!
end;

procedure Foo2;
begin
  var Tester: IShared<TTester>;
  var TestObj: IShared<TTest>;

  Tester := Shared.Make(TTester.Create);
  TestObj := Shared.Make(TTest.Create);

  Tester.DoTest(TestObj); // <-- E2010 Incompatible types: 'TTest' and 'IShared<TTest>'
  Tester.DoTest(TestObj()); // <-- Compiles OK!
end;

I have now reported this issue to Embarcadero:

 

RSS-2613: Anonymous Method is called differently depending on whether it is declared as an Inline Variable or not

 

Edited by Remy Lebeau
  • Thanks 2

Share this post


Link to post

Most simple case to repro to compiler error:

procedure X(i: Integer);
begin
end;

procedure Y;
begin
  var f: TFunc<Integer>;
  X(f);
end;

 

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×