Sign in Join

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

Mailing lists / fpc-pascal / 2019-01

Interface bug or some new feature

8 messages · 3 people ·

Reply by email Subscribe to this list Your subscription

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

denisgolovan

Hi all

I've been using 3.1.1 compiler for a long time and now I am trying to upgrade to 3.3.1 from trunk. However, I am stuck with some new behavior when using classes + interfaces. I've managed to reproduce it in a small example which follows.

Specifically 3.1.1 compiler compiles it and correctly prints "Double". 3.3.1 compiler refuses to compile comment if it's a bug or a new breaking feature.

//==================================================================
program project1;
{$mode objfpc}{$H+}
uses
  {$IFDEF UNIX}{$IFDEF UseCThreads}
  cthreads,
  {$ENDIF}{$ENDIF}
  Classes
  { you can add units after this };
type
  IIntf1 = interface
    procedure P(i:Integer);
  end;
  TClass1 = class(TInterfacedObject, IIntf1)
    procedure P(i:Integer);
  end;
  IIntf2 = interface(IIntf1)
    procedure P(f:Double);
  end;
  TClass2 = class(TClass1, IIntf2) // Error: No matching implementation for interface method "P(LongInt);" found
    procedure P(f:Double);
  end;
procedure TClass1.P(i:Integer);
begin
  WriteLn('Integer');
end;
procedure TClass2.P(f:Double);
begin
  WriteLn('Double');
end;
var v2:TClass2;
begin
  v2:=TClass2.Create;
  v2.P(0.0);
  v2.Free;
end.
//===================================================================
Regards, Denis Golovan
Sven Barth
to denisgolovan: Hi all I've been using 3.1.1 compiler for a long time and now I am trying to upgrade to…

Am So., 6. Jan. 2019, 11:42 hat denisgolovan
geschrieben:

Show quoted text 58 lines
Hi all I've been using 3.1.1 compiler for a long time and now I am trying to upgrade to 3.3.1 from trunk. However, I am stuck with some new behavior when using classes + interfaces. I've managed to reproduce it in a small example which follows. Specifically 3.1.1 compiler compiles it and correctly prints "Double". 3.3.1 compiler refuses to compile it at all. Please comment if it's a bug or a new breaking feature. //================================================================== program project1; {$mode objfpc}{$H+} uses {$IFDEF UNIX}{$IFDEF UseCThreads} cthreads, {$ENDIF}{$ENDIF} Classes { you can add units after this }; type IIntf1 = interface procedure P(i:Integer); end; TClass1 = class(TInterfacedObject, IIntf1) procedure P(i:Integer); end; IIntf2 = interface(IIntf1) procedure P(f:Double); end; TClass2 = class(TClass1, IIntf2) // Error: No matching implementation for interface method "P(LongInt);" found procedure P(f:Double); end; procedure TClass1.P(i:Integer); begin WriteLn('Integer'); end; procedure TClass2.P(f:Double); begin WriteLn('Double'); end; var v2:TClass2; begin v2:=TClass2.Create; v2.P(0.0); v2.Free; end.

The default visibility for classes without $M+ is private. Thus TClass1.P is private. An interface implementation does not have access to private methods of a parent class. So you need to declare P as protected for this to work.
Though to be fair in the specific example you gave I think that it should work as both are within the same unit. We'll need to check that...

Regards,
Sven

Sven Barth
to denisgolovan
denisgolovan wrote 12 lines
06.01.2019, 15:00, "Sven Barth via fpc-pascal" : > The default visibility for classes without $M+ is private. Thus > TClass1.P is private. An interface implementation does not have > access to private methods of a parent class. So you need to declare P > as protected for this to work. > Though to be fair in the specific example you gave I think that it > should work as both are within the same unit. We'll need to check > that... Yes. That was another real issue in my project. However I managed to get it. Thanks for quick help.

Slight correction: the default visibility is Public, not Private, so that shouldn't have been the problem with the specific example. :/

Regards,
Sven

Sven Barth
to Jonas Maebe: http://wiki.freepascal.org/User_Changes_Trunk#Methods_implementing_interface_methods_and_o…
Jonas Maebe wrote 8 lines
On 06/01/19 11:42, denisgolovan wrote: > Specifically 3.1.1 compiler compiles it and correctly prints "Double". > 3.3.1 compiler refuses to compile it at all. > Please comment if it's a bug or a new breaking feature. http://wiki.freepascal.org/User_Changes_Trunk#Methods_implementing_interface_methods_and_overloads

But shouldn't that specifc example work? TClass1.P is public here, not private.

Also unlike FPC Delphi does not give the following warning: Warning: An inherited method is hidden by "P(Double);"

Regards,
Sven

Jonas Maebe
to Sven Barth
Sven Barth wrote 12 lines
Am 06.01.2019 um 12:56 schrieb Jonas Maebe: > On 06/01/19 11:42, denisgolovan wrote: > >> Specifically 3.1.1 compiler compiles it and correctly prints "Double". >> 3.3.1 compiler refuses to compile it at all. >> Please comment if it's a bug or a new breaking feature. > > http://wiki.freepascal.org/User_Changes_Trunk#Methods_implementing_interface_methods_and_overloads > But shouldn't that specifc example work? TClass1.P is public here, not private.

It's unrelated to public and private (that is covered in http://wiki.freepascal.org/User_Changes_Trunk#Visibility_of_methods_implementing_interface_methods ). It's only about overloads. If you do not declare a method as "overload", the compiler will now stop searching the class hierarchy as soon as it finds a class that declares a method with the right name. It already did this when calling methods, now it also does it for interface method resolution.

Also unlike FPC Delphi does not give the following warning: Warning: An inherited method is hidden by "P(Double);"

At least Kylix fails to compile the test program:

Borland Delphi for Linux Version 14.5
Copyright (c) 1983,2002 Borland Software Corporation tt.pp(31) Error: Declaration of 'P' differs from declaration in interface 'IIntf2'
tt.pp(49)

Jonas