views:

127

answers:

2

In some code I am fixing up, which makes heavy use of generics and interfaced types, I am getting error

 E2134, Type '<void>' has no type info.

I believe it is because I am in the middle of a refactor where some deeply nested set of units that all use generics are out of sync, but the error is not happening in a place where I can make use of the error message to fix the code, because there is nothing wrong with the code, at the location where the error is appearing.

Here is the context, mocked up, because I can not post the code, there is too much:

 unit GenericThing;
 ...
 interface
 ...
 type
 ...
 IThingListOf<ThingT> = interface( IThingContainer )
    function  getEnumerator: TEnumerator<ThingT>;
    function  getCount: Integer;
    function  getThing( Index: integer ): ThingT;
    function  getFirst: ThingT;
      function  IndexOf( value: ThingT): integer;
    function  addItem( const Thing: ThingT ): ThingT;
      function  removeItem( const Thing: ThingT ): Integer;
    procedure clear;
    procedure Sort; overload;
    procedure Sort(const AComparer: IComparer<ThingT>); overload;
    property  Count: integer read getCount;
    property  First: ThingT read getFirst;
    property  Items[Index: integer]: ThingT read getThing; default;
  end;

 // error appears on whatever line number comes after the declaration of  IThingListOf<ThingT>...end; 
  function AnythingYouLikeHere:Integer; // there is nothign wrong with this line, but you get the E2134 here.

It appears that the problem is in IThingContainer itself:

   IThingContainer = interface ...
       ...
       procedure DoSomething(const Param);
   end;

THe above "const Param" has no type information. This is a weird (armpit) of Pascal/Delphi in my opinion, where you completely violate Wirth's idea of strong typing. It is about as weakly typed as a "void *" pointer in C, or the "Pointer" type in Delphi, but it is rarely used, except for in places like the standard pre-object-pascal RTL functions like Move, and so on. In my opinion, untyped parameters in interfaces, used in generics, should either be allowed, or disallowed, but not allowed sometimes, and disallowed other times.

This is a case of a Pascal feature from 1978 mixing badly with an ObjectPascal feature from 2009.

+1  A: 

It's kinda hard to say from this, especially without the definition of IThingContainer available. If you comment the interface definition out, will it compile past that point? Obviously it will break when you try to create a class that implements the interface, but does commenting it out fix this problem?

If so, then the compiler's choking on something in the interface definition. Try commenting out parts of it to figure out where the problem is. If not, then you'll have to look somewhere else.

Mason Wheeler
It appears to happen only when IThingContainer defines interface methods that contain untyped parameters in functions. What is really odd, is that sometimes you can define untyped parameters in functions, and some times you can not. I am looking at a codebase that uses untyped parameters heavily. Changing all parameters in IThingContainer to be typed fixes the problem, but I can find nothing out about why this is happening.
Warren P
+10  A: 

The error message means there's no type info available for the given type.

Here's a minimal program which produces the message:

type
  {$M+}
  IThing = interface
    procedure P(const X);
  end;
  {$M-}
begin
end.

The problem, it would appear, is that IThingListOf<>, or one of its ancestors, was compiled with {$M+} active. The compiler presumes from this that you really want full type info for the interface; originally it was used by SOAP etc. support to produce stubs etc. The interface RTTI doesn't support untyped parameters (logically enough, they can't be marshalled by SOAP etc.) - and they show up as being of void type, and you end up with this error message.

The solution is to either not use {$M+} - though presumably the RTTI is being used, otherwise it wouldn't be enabled - or use e.g. Pointer instead, and pass the address explicitly.

Barry Kelly
BRILLIANT. Thank you.
Warren P