Watch, Follow, &
Connect with Us
Public Report
Report From: Delphi-BCB/Compiler/Delphi/Generics    [ Add a report in this area ]  
Report #:  105719   Status: Closed
F2084 Internal Error: D7837 with method resolution clause for ancestor of generic interface
Project:  Delphi Build #:  15.0.3953.35171
Version:    15.1 Submitted By:   Louis Kleiman
Report Type:  Crash / Data loss / Total failure Date Reported:  5/18/2012 11:34:35 AM
Severity:    Infrequently encountered problem Last Updated: 9/5/2012 7:49:38 PM
Platform:    All platforms Internal Tracking #:   28365
Resolution: Fixed (Resolution Comments) Resolved in Build: : 17.0.4625.53395
Duplicate of:  None
Voting and Rating
Overall Rating: No Ratings Yet
0.00 out of 5
Total Votes: 11
Description
By USc: When using unnecessarily a method resolution clause for a method of an ancestor of a generic interface leads to parser error D7837.

-> see steps

Original from reporter:
Compiling the attached unit failes with [DCC Fatal Error] uTestList.pas(49): F2084 Internal Error: D7837

I have been told that it fails in XE2 as well.
Steps to Reproduce:
By USc:
- dcc QC105719A.dpr

expected: it compiles
actual:
XE U#1: QC105719A.dpr(18) Fatal: F2084 Internal Error: D7837
XE2 U#4: QC105719A.dpr(18) Fatal: F2084 Internal Error: D8135

The error disappears with one of the following actions:
- remove type parameter from IBar<T> definition and TFooBar<T> and see it compiles
- comment out the method resolution clause for IBar<T>.Test (line with //#1)

- dcc QC105719B.dpr

expected: it compiles
actual:
XE U#1: QC105719B.dpr(22) Fatal: F2084 Internal Error: D7837
XE2 U#4: QC105719B.dpr(22) Fatal: F2084 Internal Error: D8135

The error disappears when commenting out the method resolution clause for IEnumerator<T2>.MoveNext and IEnumerator<T2>.Reset (lines #1 and #2)

//--- QC105719A.dpr ---
program QC105719A;

{$APPTYPE CONSOLE}

type
  IFoo = interface
    procedure Test;
  end;

  IBar<T> = interface(IFoo)
  end;

  TFooBar<T> = class(TInterfacedObject, IFoo, IBar<T>)
    procedure Test;
    procedure IBar<T>.Test = Test;//#1
  end;

procedure TFooBar<T>.Test;
begin
end;

begin
  WriteLn('PASS'); // on compile
end.
//--- QC105719B.dpr ---
program QC105719B;

{$APPTYPE CONSOLE}

type
  TOfTypeEnumerator<T, T2> = class(TInterfacedObject, IEnumerator, IEnumerator<T2>)
  protected
    { IEnumerator }
    function GetCurrent: TObject;
    function MoveNext: Boolean;
    procedure Reset;
    { IEnumerator<T2> }
    function GetCurrentT: T2;

    function IEnumerator<T2>.GetCurrent = GetCurrentT;
    function IEnumerator<T2>.MoveNext = MoveNext;//#1
    procedure IEnumerator<T2>.Reset = Reset;//#2
  end;

{ TOfTypeEnumerator<T, T2> }

function TOfTypeEnumerator<T, T2>.GetCurrent: TObject;
begin
  Result := nil;
end;

function TOfTypeEnumerator<T, T2>.GetCurrentT: T2;
begin
  Result := Default(T2);
end;

function TOfTypeEnumerator<T, T2>.MoveNext: Boolean;
begin
  Result := False;
end;

procedure TOfTypeEnumerator<T, T2>.Reset;
begin
end;

begin
  WriteLn('PASS'); // on compile
end.



From reporter:
1.  Add the attached unit uTestList.pas to a project
2.  Compile the project
3.  Compilation fails

Workarounds
Write the code a different way.
Attachment
QC105719.ZIP
Comments

Louis Kleiman at 5/18/2012 11:41:07 AM -
unit uTestList;

interface

uses Generics.Collections;

type
  TListItemBase = class(TObject)
  end; { TListItemBase }

  TListItemChild1 = class(TListItemBase)
  end;

  TListItemChild2 = class(TListItemBase)
  end;

  TTestList<T : TListItemBase> = class;

  TOfTypeEnumerator<T, TFilter> = class(TInterfacedObject, IEnumerator<TFilter>)
  private
    FTestList : TList<T>;
    FIndex : Integer;
  protected
    constructor Create(Owner : TList<T>); overload;

    function GetCurrent : TFilter;
    function MoveNext : Boolean;
    procedure Reset;

    function IEnumerator<TFilter>.GetCurrent = GetCurrent;
    function IEnumerator<TFilter>.MoveNext = MoveNext;
    procedure IEnumerator<TFilter>.Reset = Reset;
  end;

  TOfTypeEnumeratorFactory<T, TFilter> = class(TInterfacedObject, IEnumerable)
  private
    FTestList : TList<T>;
  public
    constructor Create(Owner : TList<T>); overload;
    function GetEnumerator : TOfTypeEnumerator<T, TFilter>;
  end;

  TTestList<T : TListItemBase> = class(TList<T>)
  public
    function OfType<TFilter : TListItemBase>() : IEnumerable;
  end; { TTestList }


implementation

{ TOfTypeEnumerator<T, TFilter> }

constructor TOfTypeEnumerator<T, TFilter>.Create(Owner: TList<T>);
begin
  inherited;
  FTestList := Owner;
  FIndex := -1;
end;

function TOfTypeEnumerator<T, TFilter>.GetCurrent: TFilter;
begin
  Result := TFilter(FTestList[FIndex]);
end;

function TOfTypeEnumerator<T, TFilter>.MoveNext: Boolean;
begin
  Inc(FIndex);
  while ((FIndex < FTestList.Count)
         and (not FTestList[FIndex].InheritsFrom(TFilter))) do
  begin
    Inc(FIndex);
  end; { while }
end;

{ TOfTypeEnumeratorFactory<T, TFilter> }

constructor TOfTypeEnumeratorFactory<T, TFilter>.Create(Owner: TList<T>);
begin
  inherited;
  FTestList := Owner;
end;

function TOfTypeEnumeratorFactory<T, TFilter>.GetEnumerator: TOfTypeEnumerator<T, TFilter>;
begin
  Result := TOfTypeEnumerator<T,TFilter>.Create(FTestList);
end;

{ TTestList<T> }

function TTestList<T>.OfType<TFilter>: IEnumerable;
begin
  Result := TOfTypeEnumeratorFactory<T,TFilter>.Create(self);
end;

end.

Tomohiro Takahashi at 5/21/2012 12:39:33 AM -
> ... attachments don't seem to work in the QC client.  Do you guys test ANYthing?
Could you please attach sample project(as a .zip) to this report?

Note:
Please use Windows Native QC Client to modify your existing report. The standalone client comes with Delphi.
Please try my step.
--------
1. start Windows Native QC Client which comes with C++Builder.
2. lookup QC#105719
3. activate [Attachments] tab.
4. show context menu
5. select [Add Attachment...] menu
6. select a .zip file
--------

Tomohiro Takahashi at 5/21/2012 12:28:28 AM -
This report was opened with valid Internal Tracking Number.
Thanks.

Server Response from: ETNACODE01