Fix generic return type on interface free functions
A unit interface-section free function returning a generic instantiation (e.g. function MakeList: TList<string>) failed with 'Unknown return type' because the free-function return-type resolution used FTable.FindType, which only matches already-registered types and never instantiates a generic on demand. Class-method return types already resolved correctly via FindTypeOrInstantiate; this aligns the free-function paths (interface and implementation, in both AnalyseUnit and AnalyseUnitForExport) with that. The change is additive — FindTypeOrInstantiate tries FindType first — so non-generic returns are unaffected. Adds an e2e regression test.
This commit is contained in:
parent
5e42020faf
commit
c81d65bb78
|
|
@ -1177,7 +1177,7 @@ begin
|
|||
|
||||
if MDecl.ReturnTypeName <> '' then
|
||||
begin
|
||||
ParType := FTable.FindType(MDecl.ReturnTypeName);
|
||||
ParType := FindTypeOrInstantiate(MDecl.ReturnTypeName);
|
||||
if ParType = nil then
|
||||
SemanticError(
|
||||
Format('Unknown return type ''%s'' for ''%s''',
|
||||
|
|
@ -1268,7 +1268,7 @@ begin
|
|||
|
||||
if ImplDecl.ReturnTypeName <> '' then
|
||||
begin
|
||||
ParType := FTable.FindType(ImplDecl.ReturnTypeName);
|
||||
ParType := FindTypeOrInstantiate(ImplDecl.ReturnTypeName);
|
||||
if ParType = nil then
|
||||
SemanticError(
|
||||
Format('Unknown return type ''%s'' for ''%s''',
|
||||
|
|
@ -1500,7 +1500,7 @@ begin
|
|||
|
||||
if MDecl.ReturnTypeName <> '' then
|
||||
begin
|
||||
ParType := FTable.FindType(MDecl.ReturnTypeName);
|
||||
ParType := FindTypeOrInstantiate(MDecl.ReturnTypeName);
|
||||
if ParType = nil then
|
||||
SemanticError(
|
||||
Format('Unknown return type ''%s'' for ''%s''',
|
||||
|
|
@ -1585,7 +1585,7 @@ begin
|
|||
|
||||
if ImplDecl.ReturnTypeName <> '' then
|
||||
begin
|
||||
ParType := FTable.FindType(ImplDecl.ReturnTypeName);
|
||||
ParType := FindTypeOrInstantiate(ImplDecl.ReturnTypeName);
|
||||
if ParType = nil then
|
||||
SemanticError(
|
||||
Format('Unknown return type ''%s'' for ''%s''',
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ type
|
|||
procedure TestRun_TObjectList_Delete;
|
||||
procedure TestRun_Collections_Valgrind;
|
||||
procedure TestRun_TwoDictInstancesInUnit_BothLink;
|
||||
procedure TestRun_IntfFreeFunc_GenericReturn_Compiles;
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
|
@ -319,6 +320,50 @@ begin
|
|||
AssertEquals('Ints(2) + Bools(1) = 3', '3' + #10, Output);
|
||||
end;
|
||||
|
||||
{ Regression: a unit's INTERFACE-section free function (not a class method)
|
||||
whose return type is a generic instantiation such as TList<string> used to
|
||||
fail semantic analysis with "Unknown return type 'TList<string>'". The
|
||||
interface free-function path resolved the return type through a plain
|
||||
FindType lookup, which never attempts generic instantiation, whereas the
|
||||
class-method path goes through FindTypeOrInstantiate. Switching the
|
||||
free-function path to FindTypeOrInstantiate fixes it. The same generic
|
||||
return type as a class method, and as an impl-section free function, already
|
||||
worked — those must keep working. }
|
||||
procedure TE2ECollections2Tests.TestRun_IntfFreeFunc_GenericReturn_Compiles;
|
||||
const
|
||||
UnitSrc = '''
|
||||
unit freefunc;
|
||||
interface
|
||||
uses Generics.Collections;
|
||||
function MakeList: TList<string>;
|
||||
implementation
|
||||
function MakeList: TList<string>;
|
||||
begin
|
||||
Result := TList<string>.Create();
|
||||
Result.Add('a');
|
||||
Result.Add('b')
|
||||
end;
|
||||
end.
|
||||
''';
|
||||
DrvSrc = '''
|
||||
program P;
|
||||
uses Generics.Collections, freefunc;
|
||||
var L: TList<string>;
|
||||
begin
|
||||
L := MakeList();
|
||||
WriteLn(L.Count);
|
||||
L.Free()
|
||||
end.
|
||||
''';
|
||||
var Output: string; RCode: Integer;
|
||||
begin
|
||||
if not ToolchainAvailable() then begin Ignore('toolchain unavailable'); Exit; end;
|
||||
AssertTrue('compile+link+run',
|
||||
CompileAndRunWithUnit('freefunc', UnitSrc, DrvSrc, Output, RCode));
|
||||
AssertEquals('exit code 0', 0, RCode);
|
||||
AssertEquals('list count', '2' + #10, Output);
|
||||
end;
|
||||
|
||||
initialization
|
||||
RegisterTest(TE2ECollections2Tests);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue