fcl-passrc: typecast generic template type to generic template type

git-svn-id: trunk@47836 -
This commit is contained in:
Mattias Gaertner 2020-12-23 01:07:00 +00:00
parent 01691e9ecb
commit ed3741f06e
2 changed files with 58 additions and 15 deletions

View File

@ -16652,8 +16652,28 @@ end;
function TPasResolver.CreateSpecializedTypeName(Item: TPRSpecializedItem): string; function TPasResolver.CreateSpecializedTypeName(Item: TPRSpecializedItem): string;
function Get_ProcName(aProc: TPasProcedure): string; forward;
function GetTypeName(aType: TPasType): string; forward; function GetTypeName(aType: TPasType): string; forward;
function GetParentName(El: TPasElement): string;
begin
if El.Parent is TPasType then
Result:=GetTypeName(TPasType(El.Parent))
else if El is TPasUnresolvedSymbolRef then
Result:='System'
else if El.Parent is TPasProcedure then
Result:=Get_ProcName(TPasProcedure(El.Parent))
else
Result:=El.GetModule.Name;
end;
function Get_ProcName(aProc: TPasProcedure): string;
begin
Result:=GetParentName(aProc);
if aProc.Name<>'' then
Result:=Result+'.'+aProc.Name;
end;
function GetSpecParams(Item: TPRSpecializedItem): string; function GetSpecParams(Item: TPRSpecializedItem): string;
var var
i: Integer; i: Integer;
@ -16692,13 +16712,7 @@ function TPasResolver.CreateSpecializedTypeName(Item: TPRSpecializedItem): strin
end end
else else
begin begin
if aType.Parent is TPasType then Result:=GetParentName(aType)+'.'+aType.Name;
Result:=GetTypeName(TPasType(aType.Parent))
else if aType is TPasUnresolvedSymbolRef then
Result:='System'
else
Result:=aType.GetModule.Name;
Result:=Result+'.'+aType.Name;
if (aType.CustomData is TPasGenericScope) and (Pos('<',aType.Name)<1) then if (aType.CustomData is TPasGenericScope) and (Pos('<',aType.Name)<1) then
begin begin
ChildItem:=TPasGenericScope(aType.CustomData).SpecializedFromItem; ChildItem:=TPasGenericScope(aType.CustomData).SpecializedFromItem;
@ -26738,7 +26752,7 @@ function TPasResolver.CheckTypeCastRes(const FromResolved,
end; end;
var var
ToTypeEl, ToType, FromType, FromTypeEl: TPasType; ToTypeEl, FromTypeEl: TPasType;
ToTypeBaseType: TResolverBaseType; ToTypeBaseType: TResolverBaseType;
C: TClass; C: TClass;
ToProcType, FromProcType: TPasProcedureType; ToProcType, FromProcType: TPasProcedureType;
@ -26763,9 +26777,12 @@ begin
begin begin
if ToTypeEl.CustomData is TResElDataBaseType then if ToTypeEl.CustomData is TResElDataBaseType then
begin begin
// base type cast, e.g. double(aninteger) // type cast to base type, e.g. double(aninteger)
if ToTypeEl=FromResolved.LoTypeEl then if ToTypeEl=FromResolved.LoTypeEl then
exit(cExact); exit(cExact);
if (FromResolved.BaseType=btContext)
and (FromResolved.LoTypeEl.ClassType=TPasGenericTemplateType) then
exit(cExact); // e.g. double(T) -> will be checked when specialized
ToTypeBaseType:=(ToTypeEl.CustomData as TResElDataBaseType).BaseType; ToTypeBaseType:=(ToTypeEl.CustomData as TResElDataBaseType).BaseType;
if ToTypeBaseType=FromResolved.BaseType then if ToTypeBaseType=FromResolved.BaseType then
Result:=cExact Result:=cExact
@ -26950,6 +26967,9 @@ begin
// e.g. T(var) // e.g. T(var)
TemplType:=TPasGenericTemplateType(ToTypeEl); TemplType:=TPasGenericTemplateType(ToTypeEl);
FromTypeEl:=FromResolved.LoTypeEl; FromTypeEl:=FromResolved.LoTypeEl;
if (FromTypeEl<>nil)
and (FromTypeEl.ClassType=TPasGenericTemplateType) then
exit(cExact); // e.g. T(S) -> will be checked when specialized
for i:=0 to length(TemplType.Constraints)-1 do for i:=0 to length(TemplType.Constraints)-1 do
begin begin
ConEl:=TemplType.Constraints[i]; ConEl:=TemplType.Constraints[i];
@ -26984,9 +27004,9 @@ begin
if (FromResolved.IdentEl is TPasType) then if (FromResolved.IdentEl is TPasType) then
RaiseMsg(20170404162604,nCannotTypecastAType,sCannotTypecastAType,[],ErrorEl); RaiseMsg(20170404162604,nCannotTypecastAType,sCannotTypecastAType,[],ErrorEl);
// type cast classof(classof-var) upwards or downwards // type cast classof(classof-var) upwards or downwards
ToType:=TPasClassOfType(ToTypeEl).DestType; ToTypeEl:=TPasClassOfType(ToTypeEl).DestType;
FromType:=TPasClassOfType(FromResolved.LoTypeEl).DestType; FromTypeEl:=TPasClassOfType(FromResolved.LoTypeEl).DestType;
Result:=CheckClassesAreRelated(ToType,FromType); Result:=CheckClassesAreRelated(ToTypeEl,FromTypeEl);
end; end;
end end
else if FromResolved.BaseType=btPointer then else if FromResolved.BaseType=btPointer then
@ -27171,9 +27191,8 @@ begin
and (ToTypeEl=ToResolved.IdentEl) then and (ToTypeEl=ToResolved.IdentEl) then
begin begin
// for example class-of(Self) in a class function // for example class-of(Self) in a class function
ToType:=TPasClassOfType(ToTypeEl).DestType; ToTypeEl:=TPasClassOfType(ToTypeEl).DestType;
FromType:=TPasClassType(FromTypeEl); Result:=CheckClassesAreRelated(ToTypeEl,FromTypeEl);
Result:=CheckClassesAreRelated(ToType,FromType);
end; end;
end; end;
end; end;

View File

@ -185,6 +185,7 @@ type
procedure TestGenMethod_OverloadTypeParamCntObjFPC; procedure TestGenMethod_OverloadTypeParamCntObjFPC;
procedure TestGenMethod_OverloadTypeParamCntDelphi; procedure TestGenMethod_OverloadTypeParamCntDelphi;
procedure TestGenMethod_OverloadArgs; procedure TestGenMethod_OverloadArgs;
procedure TestGenMethod_TypeCastParam;
end; end;
implementation implementation
@ -2982,6 +2983,29 @@ begin
ParseProgram; ParseProgram;
end; end;
procedure TTestResolveGenerics.TestGenMethod_TypeCastParam;
begin
StartUnit(false);
Add([
'{$mode delphi}',
'interface',
'type',
' TObject = class end;',
' TArray<T> = array of T;',
' TBird = class',
' F: TArray<TObject>;',
' procedure Run<S>(a: TArray<S>);',
' end;',
'implementation',
'procedure TBird.Run<S>(a: TArray<S>);',
'begin',
' a:=TArray<S>(a);',
//' F:=TArray<TObject>(a);',
'end;',
'']);
ParseUnit;
end;
initialization initialization
RegisterTests([TTestResolveGenerics]); RegisterTests([TTestResolveGenerics]);