Strange overloads

2

Combining method overloading with implicit type conversion may lead to strange results. Consider the following innocent stub code for implementing a wrapper type for array of bytes:

unit Unit1;

interface

uses SysUtils;

type
  ByteArray = record
    class function Copy(const A: ByteArray; I: Cardinal): ByteArray; overload; static;
    class function Copy(const A: ByteArray; I, L: Cardinal): ByteArray; overload; static;
    function Copy(I: Cardinal): ByteArray; overload;
    function Copy(I, L: Cardinal): ByteArray; overload;

    class operator Implicit(const Value: LongWord): ByteArray;
    class operator Implicit(const Value: UInt64): ByteArray;
  end;


implementation

{ ByteArray }

class function ByteArray.Copy(const A: ByteArray; I, L: Cardinal): ByteArray;
begin
  Writeln('class func ByteArray.Copy(A, I, L)');
end;

class function ByteArray.Copy(const A: ByteArray; I: Cardinal): ByteArray;
begin
  Writeln('class func ByteArray.Copy(A, I)');
end;

function ByteArray.Copy(I, L: Cardinal): ByteArray;
begin
  Writeln('func A.Copy(I, L)');
end;

function ByteArray.Copy(I: Cardinal): ByteArray;
begin
  Writeln('func A.Copy(I)');
end;

class operator ByteArray.Implicit(const Value: UInt64): ByteArray;
begin
  Writeln('Implicit conversion from UInt64 to ByteArray');
end;

class operator ByteArray.Implicit(const Value: LongWord): ByteArray;
begin
  Writeln('Implicit conversion from LongWord to ByteArray');
end;

end.

The Copy methods are intended to copy a subarray starting from index I, either to the end of the array or (if the L parameter is present) a given number of bytes. The ByteArray type also implements implicit type conversion from integer types.

Now let us see what happens in the following test:

program Overloads;

{$APPTYPE CONSOLE}

uses
  SysUtils,
  Unit1 in 'Unit1.pas';

procedure Test;
var
  A, B: ByteArray;
  I: Integer;

begin
  I:= 0;
  B:= A.Copy(I, 4);
end;

begin
  try
    Test;
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
  Readln;
end.

One would expect that B:= A.Copy(I, 4) calls function Copy(I, L: Cardinal): ByteArray;
Quite unexpectedly the compiler (Delphi XE) outputs

Overl