tcresolvegenerics.pas 70 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013
  1. unit tcresolvegenerics;
  2. {$mode objfpc}{$H+}
  3. interface
  4. uses
  5. Classes, SysUtils, testregistry, tcresolver, PasResolveEval, PParser,
  6. PScanner;
  7. type
  8. { TTestResolveGenerics }
  9. TTestResolveGenerics = Class(TCustomTestResolver)
  10. Published
  11. // generic types
  12. procedure TestGen_MissingTemplateFail;
  13. procedure TestGen_VarTypeWithoutSpecializeFail;
  14. procedure TestGen_GenTypeWithWrongParamCountFail;
  15. procedure TestGen_GenericNotFoundFail;
  16. procedure TestGen_SameNameSameParamCountFail;
  17. procedure TestGen_TypeAliasWithoutSpecializeFail;
  18. procedure TestGen_TemplNameEqTypeNameFail; // type T<T>
  19. // constraints
  20. procedure TestGen_ConstraintStringFail;
  21. procedure TestGen_ConstraintMultiClassFail;
  22. procedure TestGen_ConstraintRecordExpectedFail;
  23. procedure TestGen_ConstraintClassRecordFail;
  24. procedure TestGen_ConstraintRecordClassFail;
  25. procedure TestGen_ConstraintArrayFail;
  26. procedure TestGen_ConstraintConstructor;
  27. procedure TestGen_ConstraintUnit;
  28. // ToDo: constraint T:Unit2.specialize TGen<word>
  29. procedure TestGen_ConstraintSpecialize;
  30. procedure TestGen_ConstraintTSpecializeWithT;
  31. procedure TestGen_ConstraintTSpecializeAsTFail; // TBird<T; U: T<word>> and no T<>
  32. procedure TestGen_ConstraintTSpecializeWithTFail; // TBird<T: TAnt<T>>
  33. procedure TestGen_ConstraintSameNameFail; // TAnt<T:T>
  34. procedure TestGen_ConstraintInheritedMissingRecordFail;
  35. procedure TestGen_ConstraintInheritedMissingClassTypeFail;
  36. procedure TestGen_ConstraintMultiParam;
  37. procedure TestGen_ConstraintMultiParamClassMismatch;
  38. procedure TestGen_ConstraintClassType_DotIsAsTypeCast;
  39. procedure TestGen_ConstraintClassType_ForInT;
  40. procedure TestGen_ConstraintClassType_IsAs;
  41. // generic record
  42. procedure TestGen_RecordLocalNameDuplicateFail;
  43. procedure TestGen_Record;
  44. procedure TestGen_RecordDelphi;
  45. procedure TestGen_RecordNestedSpecialize_ClassRecord;
  46. procedure TestGen_RecordNestedSpecialize_Self;
  47. procedure TestGen_Record_SpecializeSelfInsideFail;
  48. procedure TestGen_Record_ReferGenericSelfFail;
  49. procedure TestGen_RecordAnoArray;
  50. // ToDo: unitname.specialize TBird<word>.specialize TAnt<word>
  51. // generic class
  52. procedure TestGen_Class;
  53. procedure TestGen_ClassDelphi;
  54. procedure TestGen_ClassDelphi_TypeOverload;
  55. procedure TestGen_ClassObjFPC;
  56. procedure TestGen_ClassObjFPC_OverloadFail;
  57. procedure TestGen_ClassObjFPC_OverloadOtherUnit;
  58. procedure TestGen_ClassGenAncestorWithoutParamFail;
  59. procedure TestGen_ClassForward;
  60. procedure TestGen_ClassForwardConstraints;
  61. procedure TestGen_ClassForwardConstraintNameMismatch;
  62. procedure TestGen_ClassForwardConstraintKeywordMismatch;
  63. procedure TestGen_ClassForwardConstraintTypeMismatch;
  64. procedure TestGen_ClassForward_Circle;
  65. procedure TestGen_Class_RedeclareInUnitImplFail;
  66. procedure TestGen_Class_TypeOverloadInUnitImpl;
  67. procedure TestGen_Class_MethodObjFPC;
  68. procedure TestGen_Class_MethodOverride;
  69. procedure TestGen_Class_MethodDelphi;
  70. procedure TestGen_Class_MethodDelphiTypeParamMissing;
  71. procedure TestGen_Class_MethodImplConstraintFail;
  72. procedure TestGen_Class_MethodImplTypeParamNameMismatch;
  73. procedure TestGen_Class_SpecializeSelfInside;
  74. procedure TestGen_Class_AncestorTFail;
  75. procedure TestGen_Class_GenAncestor;
  76. procedure TestGen_Class_AncestorSelfFail;
  77. procedure TestGen_ClassOfSpecializeFail;
  78. // ToDo: UnitA.impl uses UnitB.intf uses UnitA.intf, UnitB has specialize of UnitA
  79. procedure TestGen_Class_NestedType;
  80. procedure TestGen_Class_NestedRecord;
  81. procedure TestGen_Class_NestedClass;
  82. procedure TestGen_Class_Enums_NotPropagating;
  83. procedure TestGen_Class_Self;
  84. procedure TestGen_Class_MemberTypeConstructor;
  85. procedure TestGen_Class_AliasMemberType;
  86. procedure TestGen_Class_AccessGenericMemberTypeFail;
  87. procedure TestGen_Class_ReferenceTo;
  88. procedure TestGen_Class_TwoSpecsAreNotRelatedWarn;
  89. procedure TestGen_Class_List;
  90. procedure TestGen_Class_Typecast;
  91. // ToDo: different modeswitches at parse time and specialize time
  92. // generic external class
  93. procedure TestGen_ExtClass_Array;
  94. procedure TestGen_ExtClass_VarargsOfType;
  95. // generic interface
  96. procedure TestGen_ClassInterface;
  97. procedure TestGen_ClassInterface_Method;
  98. // generic array
  99. procedure TestGen_DynArray;
  100. procedure TestGen_StaticArray;
  101. procedure TestGen_Array_Anoynmous;
  102. // generic procedure type
  103. procedure TestGen_ProcType;
  104. procedure TestGen_ProcType_AnonymousFunc_Delphi;
  105. // pointer of generic
  106. procedure TestGen_PointerDirectSpecializeFail;
  107. // ToDo: helpers for generics
  108. procedure TestGen_HelperForArray;
  109. // ToDo: default class prop array helper: arr<b>[c]
  110. // generic statements
  111. procedure TestGen_LocalVar;
  112. procedure TestGen_Statements;
  113. procedure TestGen_InlineSpecializeExpr;
  114. // ToDo: a.b<c>(d)
  115. // ToDo: with a do b<c>
  116. procedure TestGen_TryExcept;
  117. procedure TestGen_Call;
  118. procedure TestGen_NestedProc;
  119. // ToDo: obj<b>[c]
  120. // generic functions
  121. procedure TestGenProc_Function;
  122. procedure TestGenProc_FunctionDelphi;
  123. procedure TestGenProc_OverloadDuplicate;
  124. procedure TestGenProc_MissingTemplatesFail;
  125. procedure TestGenProc_SpecializeNonGenericFail;
  126. procedure TestGenProc_Forward;
  127. procedure TestGenProc_External;
  128. procedure TestGenProc_UnitIntf;
  129. procedure TestGenProc_BackRef1Fail;
  130. procedure TestGenProc_BackRef2Fail;
  131. procedure TestGenProc_BackRef3Fail;
  132. procedure TestGenProc_CallSelf;
  133. procedure TestGenProc_CallSelfNoParams;
  134. procedure TestGenProc_ForwardConstraints;
  135. procedure TestGenProc_ForwardConstraintsRepeatFail;
  136. procedure TestGenProc_ForwardTempNameMismatch;
  137. procedure TestGenProc_ForwardOverload;
  138. procedure TestGenProc_NestedFail;
  139. procedure TestGenProc_TypeParamCntOverload;
  140. procedure TestGenProc_TypeParamCntOverloadNoParams;
  141. procedure TestGenProc_TypeParamWithDefaultParamDelphiFail;
  142. procedure TestGenProc_ParamSpecWithT; // ToDo: Func<T>(Bird: TBird<T>)
  143. // ToDo: NestedResultAssign
  144. // generic function infer types
  145. procedure TestGenProc_Infer_NeedExplicitFail;
  146. procedure TestGenProc_Infer_Overload;
  147. procedure TestGenProc_Infer_OverloadForward;
  148. procedure TestGenProc_Infer_Var_Overload;
  149. procedure TestGenProc_Infer_Widen;
  150. procedure TestGenProc_Infer_DefaultValue;
  151. procedure TestGenProc_Infer_DefaultValueMismatch;
  152. procedure TestGenProc_Infer_ProcT;
  153. procedure TestGenProc_Infer_Mismatch;
  154. procedure TestGenProc_Infer_ArrayOfT;
  155. procedure TestGenProc_Infer_PassAsArgDelphi;
  156. procedure TestGenProc_Infer_PassAsArgObjFPC;
  157. // ToDo procedure TestGenProc_Infer_ProcType;
  158. // generic methods
  159. procedure TestGenMethod_VirtualFail;
  160. procedure TestGenMethod_PublishedFail;
  161. procedure TestGenMethod_ClassInterfaceMethodFail;
  162. procedure TestGenMethod_ClassConstructorFail;
  163. procedure TestGenMethod_TemplNameDifferFail;
  164. procedure TestGenMethod_ImplConstraintFail;
  165. procedure TestGenMethod_NestedSelf;
  166. procedure TestGenMethod_OverloadTypeParamCntObjFPC;
  167. procedure TestGenMethod_OverloadTypeParamCntDelphi;
  168. procedure TestGenMethod_OverloadArgs;
  169. procedure TestGenMethod_TypeCastParam;
  170. end;
  171. implementation
  172. { TTestResolveGenerics }
  173. procedure TTestResolveGenerics.TestGen_MissingTemplateFail;
  174. begin
  175. StartProgram(false);
  176. Add([
  177. 'type generic g< > = array of word;',
  178. 'begin',
  179. '']);
  180. CheckParserException('Expected "Identifier"',nParserExpectTokenError);
  181. end;
  182. procedure TTestResolveGenerics.TestGen_VarTypeWithoutSpecializeFail;
  183. begin
  184. StartProgram(false);
  185. Add([
  186. 'type generic TBird<T> = record end;',
  187. 'var b: TBird;',
  188. 'begin',
  189. '']);
  190. CheckResolverException('Generics without specialization cannot be used as a type for a variable',
  191. nGenericsWithoutSpecializationAsType);
  192. end;
  193. procedure TTestResolveGenerics.TestGen_GenTypeWithWrongParamCountFail;
  194. begin
  195. StartProgram(false);
  196. Add([
  197. 'type generic TBird<T> = record end;',
  198. 'var b: specialize TBird<word, byte>;',
  199. 'begin',
  200. '']);
  201. CheckResolverException('identifier not found "TBird<,>"',
  202. nIdentifierNotFound);
  203. end;
  204. procedure TTestResolveGenerics.TestGen_GenericNotFoundFail;
  205. begin
  206. StartProgram(false);
  207. Add([
  208. '{$mode objfpc}',
  209. 'type',
  210. ' TBird = specialize TAnimal<word>;',
  211. 'begin',
  212. '']);
  213. CheckResolverException('identifier not found "TAnimal<>"',
  214. nIdentifierNotFound);
  215. end;
  216. procedure TTestResolveGenerics.TestGen_SameNameSameParamCountFail;
  217. begin
  218. StartProgram(false);
  219. Add([
  220. '{$mode delphi}',
  221. 'type',
  222. ' TBird<S,T> = record w: T; end;',
  223. ' TBird<X,Y> = record f: X; end;',
  224. 'begin',
  225. '']);
  226. CheckResolverException('Duplicate identifier "TBird" at afile.pp(4,8)',
  227. nDuplicateIdentifier);
  228. end;
  229. procedure TTestResolveGenerics.TestGen_TypeAliasWithoutSpecializeFail;
  230. begin
  231. StartProgram(false);
  232. Add([
  233. '{$mode delphi}',
  234. 'type',
  235. ' TBird<T> = record w: T; end;',
  236. ' TBirdAlias = TBird;',
  237. 'begin',
  238. '']);
  239. CheckResolverException('Generics without specialization cannot be used as a type for a variable',
  240. nGenericsWithoutSpecializationAsType);
  241. end;
  242. procedure TTestResolveGenerics.TestGen_TemplNameEqTypeNameFail;
  243. begin
  244. StartProgram(false);
  245. Add([
  246. '{$mode objfpc}',
  247. 'type',
  248. ' generic TBird<TBird> = record v: T; end;',
  249. 'var r: specialize TBird<word>;',
  250. 'begin',
  251. '']);
  252. CheckResolverException('Duplicate identifier "TBird" at afile.pp(4,16)',
  253. nDuplicateIdentifier);
  254. end;
  255. procedure TTestResolveGenerics.TestGen_ConstraintStringFail;
  256. begin
  257. StartProgram(false);
  258. Add([
  259. 'type generic TRec<T:string> = record end;',
  260. 'begin',
  261. '']);
  262. CheckResolverException('"String" is not a valid constraint',
  263. nXIsNotAValidConstraint);
  264. end;
  265. procedure TTestResolveGenerics.TestGen_ConstraintMultiClassFail;
  266. begin
  267. StartProgram(false);
  268. Add([
  269. '{$mode objfpc}',
  270. 'type',
  271. ' TObject = class end;',
  272. ' TBird = class end;',
  273. ' TBear = class end;',
  274. ' generic TRec<T: TBird, TBear> = record end;',
  275. 'begin',
  276. '']);
  277. CheckResolverException('"TBird" constraint and "TBear" constraint cannot be specified together',
  278. nConstraintXAndConstraintYCannotBeTogether);
  279. end;
  280. procedure TTestResolveGenerics.TestGen_ConstraintRecordExpectedFail;
  281. begin
  282. StartProgram(false);
  283. Add([
  284. '{$mode objfpc}',
  285. 'type',
  286. ' generic TBird<T:record> = record v: T; end;',
  287. 'var r: specialize TBird<word>;',
  288. 'begin',
  289. '']);
  290. CheckResolverException('record type expected, but Word found',
  291. nXExpectedButYFound);
  292. end;
  293. procedure TTestResolveGenerics.TestGen_ConstraintClassRecordFail;
  294. begin
  295. StartProgram(false);
  296. Add([
  297. '{$mode objfpc}',
  298. 'type',
  299. ' TRec = record end;',
  300. ' generic TBird<T:class> = record v: T; end;',
  301. 'var r: specialize TBird<TRec>;',
  302. 'begin',
  303. '']);
  304. CheckResolverException('class type expected, but TRec found',
  305. nXExpectedButYFound);
  306. end;
  307. procedure TTestResolveGenerics.TestGen_ConstraintRecordClassFail;
  308. begin
  309. StartProgram(false);
  310. Add([
  311. '{$mode objfpc}',
  312. 'type',
  313. ' TObject = class end;',
  314. ' generic TBird<T:record> = record v: T; end;',
  315. 'var r: specialize TBird<TObject>;',
  316. 'begin',
  317. '']);
  318. CheckResolverException('record type expected, but TObject found',
  319. nXExpectedButYFound);
  320. end;
  321. procedure TTestResolveGenerics.TestGen_ConstraintArrayFail;
  322. begin
  323. StartProgram(false);
  324. Add([
  325. '{$mode objfpc}',
  326. 'type',
  327. ' TArr = array of word;',
  328. ' generic TBird<T:TArr> = record v: T; end;',
  329. 'begin',
  330. '']);
  331. CheckResolverException('"array of Word" is not a valid constraint',
  332. nXIsNotAValidConstraint);
  333. end;
  334. procedure TTestResolveGenerics.TestGen_ConstraintConstructor;
  335. begin
  336. StartProgram(true,[supTObject]);
  337. Add([
  338. '{$mode objfpc}',
  339. 'type',
  340. ' generic TBird<T:constructor> = class',
  341. ' o: T;',
  342. ' procedure Fly;',
  343. ' end;',
  344. ' TAnt = class end;',
  345. 'var a: specialize TBird<TAnt>;',
  346. 'procedure TBird.Fly;',
  347. 'begin',
  348. ' o:=T.Create;',
  349. 'end;',
  350. 'begin',
  351. '']);
  352. ParseProgram;
  353. end;
  354. procedure TTestResolveGenerics.TestGen_ConstraintUnit;
  355. begin
  356. AddModuleWithIntfImplSrc('unit1.pas',
  357. LinesToStr([
  358. 'type',
  359. ' TBird = class b1: word; end;',
  360. ' generic TAnt<T> = class a1: T; end;',
  361. '']),
  362. LinesToStr([
  363. '']));
  364. StartProgram(true,[supTObject]);
  365. Add([
  366. 'uses unit1;',
  367. 'type',
  368. ' generic TCat<T: unit1.TBird> = class v: T; end;',
  369. ' generic TFish<T: specialize TAnt<word>> = class v: T; end;',
  370. ' TEagle = class(unit1.TBird);',
  371. ' TRedAnt = specialize TAnt<word>;',
  372. 'var',
  373. ' eagle: TEagle;',
  374. ' redant: TRedAnt;',
  375. ' cat: specialize TCat<TEagle>;',
  376. ' fish: specialize TFish<TRedAnt>;',
  377. 'begin',
  378. ' cat.v:=eagle;',
  379. ' fish.v:=redant;',
  380. '']);
  381. ParseProgram;
  382. end;
  383. procedure TTestResolveGenerics.TestGen_ConstraintSpecialize;
  384. begin
  385. StartProgram(false);
  386. Add([
  387. '{$mode objfpc}',
  388. 'type',
  389. ' TObject = class end;',
  390. ' generic TAnt<S> = class m: S; end;',
  391. ' generic TBird<T:specialize TAnt<word>> = class',
  392. ' o: T;',
  393. ' end;',
  394. ' TFireAnt = class(specialize TAnt<word>) end;',
  395. 'var',
  396. ' a: specialize TBird<TFireAnt>;',
  397. ' f: TFireAnt;',
  398. 'begin',
  399. ' a.o:=f;',
  400. '']);
  401. ParseProgram;
  402. end;
  403. procedure TTestResolveGenerics.TestGen_ConstraintTSpecializeWithT;
  404. begin
  405. StartProgram(false);
  406. Add([
  407. '{$mode delphi}',
  408. 'type',
  409. ' TObject = class end;',
  410. ' TAnt<S> = class m: S; end;',
  411. ' TBird<X; Y: TAnt<X>> = class',
  412. ' Ant: Y;',
  413. ' end;',
  414. ' TEagle<X; Y:X> = class',
  415. ' e: Y;',
  416. ' end;',
  417. ' TFireAnt<F> = class(TAnt<F>) end;',
  418. ' TAntWord = TAnt<word>;',
  419. ' TBirdAntWord = TBird<word, TAnt<word>>;',
  420. 'var',
  421. ' a: TAnt<word>;',
  422. ' b: TBird<word, TAntWord>;',
  423. ' c: TBird<TBirdAntWord, TAnt<TBirdAntWord>>;',
  424. ' f: TEagle<TAnt<boolean>, TFireAnt<boolean>>;',
  425. ' fb: TFireAnt<boolean>;',
  426. 'begin',
  427. ' b.Ant:=a;',
  428. ' f.e:=fb;',
  429. '']);
  430. ParseProgram;
  431. end;
  432. procedure TTestResolveGenerics.TestGen_ConstraintTSpecializeAsTFail;
  433. begin
  434. StartProgram(false);
  435. Add([
  436. '{$mode objfpc}',
  437. 'type',
  438. ' TObject = class end;',
  439. // Note: would work if generic T<S> exists
  440. ' generic TBird<T; U: specialize T<word>> = record v: T; end;',
  441. 'begin',
  442. '']);
  443. CheckResolverException('identifier not found "T<>"',nIdentifierNotFound);
  444. end;
  445. procedure TTestResolveGenerics.TestGen_ConstraintTSpecializeWithTFail;
  446. begin
  447. StartProgram(false);
  448. Add([
  449. '{$mode objfpc}',
  450. 'type',
  451. ' TObject = class end;',
  452. ' generic TAnt<S> = class v: S; end;',
  453. ' generic TBird<T: specialize TAnt<T>> = class v: T; end;',
  454. ' TEagle = specialize TBird<specialize TAnt<word>>;',
  455. 'begin',
  456. '']);
  457. CheckResolverException('identifier not found "T"',nIdentifierNotFound);
  458. end;
  459. procedure TTestResolveGenerics.TestGen_ConstraintSameNameFail;
  460. begin
  461. StartProgram(false);
  462. Add([
  463. '{$mode objfpc}',
  464. 'type',
  465. ' TObject = class end;',
  466. ' T = TObject;',
  467. ' generic TAnt<T:T> = record v: word; end;',
  468. 'begin',
  469. '']);
  470. CheckResolverException(sTypeCycleFound,nTypeCycleFound);
  471. end;
  472. procedure TTestResolveGenerics.TestGen_ConstraintInheritedMissingRecordFail;
  473. begin
  474. StartProgram(false);
  475. Add([
  476. '{$mode objfpc}',
  477. 'type',
  478. ' TObject = class end;',
  479. ' generic TBird<T: record> = class v: T; end;',
  480. ' generic TEagle<U> = class(specialize TBird<U>)',
  481. ' end;',
  482. 'begin',
  483. '']);
  484. CheckResolverException('Type parameter "U" is missing constraint "record"',
  485. nTypeParamXIsMissingConstraintY);
  486. end;
  487. procedure TTestResolveGenerics.TestGen_ConstraintInheritedMissingClassTypeFail;
  488. begin
  489. StartProgram(false);
  490. Add([
  491. '{$mode objfpc}',
  492. 'type',
  493. ' TObject = class end;',
  494. ' TAnt = class end;',
  495. ' generic TBird<T: TAnt> = class v: T; end;',
  496. ' generic TEagle<U> = class(specialize TBird<U>)',
  497. ' end;',
  498. 'begin',
  499. '']);
  500. CheckResolverException('Type parameter "U" is not compatible with type "TAnt"',
  501. nTypeParamXIsNotCompatibleWithY);
  502. end;
  503. procedure TTestResolveGenerics.TestGen_ConstraintMultiParam;
  504. begin
  505. StartProgram(false);
  506. Add([
  507. '{$mode objfpc}',
  508. 'type',
  509. ' TObject = class end;',
  510. ' TAnt = class end;',
  511. ' generic TBird<S,T: TAnt> = class',
  512. ' x: S;',
  513. ' y: T;',
  514. ' end;',
  515. ' TRedAnt = class(TAnt) end;',
  516. ' TEagle = specialize TBird<TRedAnt,TAnt>;',
  517. 'begin',
  518. '']);
  519. ParseProgram;
  520. end;
  521. procedure TTestResolveGenerics.TestGen_ConstraintMultiParamClassMismatch;
  522. begin
  523. StartProgram(false);
  524. Add([
  525. '{$mode objfpc}',
  526. 'type',
  527. ' TObject = class end;',
  528. ' TAnt = class end;',
  529. ' TRedAnt = class(TAnt) end;',
  530. ' generic TBird<S,T: TRedAnt> = class',
  531. ' x: S;',
  532. ' y: T;',
  533. ' end;',
  534. ' TEagle = specialize TBird<TRedAnt,TAnt>;',
  535. 'begin',
  536. '']);
  537. CheckResolverException('Incompatible types: got "TAnt" expected "TRedAnt"',
  538. nIncompatibleTypesGotExpected);
  539. end;
  540. procedure TTestResolveGenerics.TestGen_ConstraintClassType_DotIsAsTypeCast;
  541. begin
  542. StartProgram(false);
  543. Add([
  544. '{$mode objfpc}',
  545. 'type',
  546. ' TObject = class end;',
  547. ' TAnt = class',
  548. ' procedure Run; external; overload;',
  549. ' end;',
  550. ' TRedAnt = class(TAnt)',
  551. ' procedure Run(w: word); external; overload;',
  552. ' end;',
  553. ' generic TBird<T: TRedAnt> = class',
  554. ' y: T;',
  555. ' procedure Fly;',
  556. ' end;',
  557. ' TFireAnt = class(TRedAnt);',
  558. ' generic TEagle<U: TRedAnt> = class(specialize TBird<U>) end;',
  559. ' TRedEagle = specialize TEagle<TRedAnt>;',
  560. 'procedure TBird.Fly;',
  561. 'var f: TFireAnt;',
  562. 'begin',
  563. ' y.Run;',
  564. ' y.Run(3);',
  565. ' if y is TFireAnt then',
  566. ' f:=y as TFireAnt;',
  567. ' f:=TFireAnt(y);',
  568. ' y:=T(f);',
  569. 'end;',
  570. 'begin',
  571. '']);
  572. ParseProgram;
  573. end;
  574. procedure TTestResolveGenerics.TestGen_ConstraintClassType_ForInT;
  575. begin
  576. StartProgram(false);
  577. Add([
  578. '{$mode objfpc}',
  579. 'type',
  580. ' TObject = class end;',
  581. ' generic TEnumerator<TItem> = class',
  582. ' FCurrent: TItem;',
  583. ' property Current: TItem read FCurrent;',
  584. ' function MoveNext: boolean;',
  585. ' end;',
  586. ' generic TAnt<U> = class',
  587. ' function GetEnumerator: specialize TEnumerator<U>;',
  588. ' end;',
  589. ' generic TBird<S; T: specialize TAnt<S>> = class',
  590. ' m: T;',
  591. ' procedure Fly;',
  592. ' end;',
  593. 'function TEnumerator.MoveNext: boolean;',
  594. 'begin',
  595. 'end;',
  596. 'function TAnt.GetEnumerator: specialize TEnumerator<U>;',
  597. 'begin',
  598. 'end;',
  599. 'procedure TBird.Fly;',
  600. 'var i: S;',
  601. 'begin',
  602. ' for i in m do ;',
  603. 'end;',
  604. 'var',
  605. ' a: specialize TAnt<word>;',
  606. ' w: word;',
  607. ' b: specialize TBird<word,specialize TAnt<word>>;',
  608. 'begin',
  609. ' for w in a do ;',
  610. ' for w in b.m do ;',
  611. '']);
  612. ParseProgram;
  613. end;
  614. procedure TTestResolveGenerics.TestGen_ConstraintClassType_IsAs;
  615. begin
  616. StartProgram(false);
  617. Add([
  618. '{$mode objfpc}',
  619. 'type',
  620. ' TObject = class end;',
  621. ' generic TAnt<U> = class',
  622. ' v: U;',
  623. ' function Run: U;',
  624. ' end;',
  625. 'function TAnt.Run: U;',
  626. 'var a: specialize TAnt<U>;',
  627. 'begin',
  628. ' if v is TObject then ;',
  629. ' if v is specialize TAnt<TObject> then',
  630. ' specialize TAnt<TObject>(v).v:=nil;',
  631. ' a:=v as specialize TAnt<U>;',
  632. ' if (v as specialize TAnt<TObject>).v=nil then ;',
  633. ' if nil=(v as specialize TAnt<TObject>).v then ;',
  634. 'end;',
  635. 'begin',
  636. '']);
  637. ParseProgram;
  638. end;
  639. procedure TTestResolveGenerics.TestGen_RecordLocalNameDuplicateFail;
  640. begin
  641. StartProgram(false);
  642. Add([
  643. '{$mode objfpc}',
  644. 'type',
  645. ' generic TBird<T> = record T: word; end;',
  646. 'begin',
  647. '']);
  648. CheckResolverException('Duplicate identifier "T" at afile.pp(4,18)',
  649. nDuplicateIdentifier);
  650. end;
  651. procedure TTestResolveGenerics.TestGen_Record;
  652. begin
  653. StartProgram(false);
  654. Add([
  655. '{$mode objfpc}',
  656. 'type',
  657. ' {#Typ}T = word;',
  658. ' generic TRec<{#Templ}T> = record',
  659. ' {=Templ}v: T;',
  660. ' end;',
  661. 'var',
  662. ' r: specialize TRec<word>;',
  663. ' {=Typ}w: T;',
  664. 'begin',
  665. ' r.v:=w;',
  666. '']);
  667. ParseProgram;
  668. end;
  669. procedure TTestResolveGenerics.TestGen_RecordDelphi;
  670. begin
  671. StartProgram(false);
  672. Add([
  673. '{$mode delphi}',
  674. 'type',
  675. ' {#Typ}T = word;',
  676. ' TRec<{#Templ}T> = record',
  677. ' {=Templ}v: T;',
  678. ' end;',
  679. 'var',
  680. ' r: TRec<word>;',
  681. ' {=Typ}w: T;',
  682. 'begin',
  683. ' r.v:=w;',
  684. '']);
  685. ParseProgram;
  686. end;
  687. procedure TTestResolveGenerics.TestGen_RecordNestedSpecialize_ClassRecord;
  688. begin
  689. StartProgram(false);
  690. Add([
  691. '{$mode objfpc}',
  692. 'type',
  693. ' TObject = class end;',
  694. ' generic TBird<T> = class v: T; end;',
  695. ' generic TFish<T:class> = record v: T; end;',
  696. 'var f: specialize TFish<specialize TBird<word>>;',
  697. 'begin',
  698. '']);
  699. ParseProgram;
  700. end;
  701. procedure TTestResolveGenerics.TestGen_RecordNestedSpecialize_Self;
  702. begin
  703. StartProgram(false);
  704. Add([
  705. '{$mode objfpc}',
  706. 'type',
  707. ' generic TBird<T> = record v: T; end;',
  708. 'var',
  709. ' a: specialize TBird<specialize TBird<word>>;',
  710. 'begin',
  711. ' a.v.v:=3;',
  712. '']);
  713. ParseProgram;
  714. end;
  715. procedure TTestResolveGenerics.TestGen_Record_SpecializeSelfInsideFail;
  716. begin
  717. StartProgram(false);
  718. Add([
  719. '{$mode objfpc}',
  720. 'type',
  721. ' generic TBird<T> = record',
  722. ' v: specialize TBird<word>;',
  723. ' end;',
  724. 'begin',
  725. '']);
  726. CheckResolverException('type "TBird<>" is not yet completely defined',
  727. nTypeXIsNotYetCompletelyDefined);
  728. end;
  729. procedure TTestResolveGenerics.TestGen_Record_ReferGenericSelfFail;
  730. begin
  731. StartProgram(false);
  732. Add([
  733. '{$mode delphi}',
  734. 'Type',
  735. ' TBird<T> = record',
  736. ' b: TBird<T>;',
  737. ' end;',
  738. 'begin',
  739. '']);
  740. CheckResolverException('type "TBird<>" is not yet completely defined',
  741. nTypeXIsNotYetCompletelyDefined);
  742. end;
  743. procedure TTestResolveGenerics.TestGen_RecordAnoArray;
  744. begin
  745. StartProgram(false);
  746. Add([
  747. '{$mode objfpc}',
  748. 'type',
  749. ' generic TBird<T> = record v: T; end;',
  750. 'var',
  751. ' a: specialize TBird<array of word>;',
  752. ' b: specialize TBird<array of word>;',
  753. 'begin',
  754. ' a:=b;',
  755. '']);
  756. ParseProgram;
  757. end;
  758. procedure TTestResolveGenerics.TestGen_Class;
  759. begin
  760. StartProgram(false);
  761. Add([
  762. '{$mode objfpc}',
  763. 'type',
  764. ' TObject = class end;',
  765. ' {#Typ}T = word;',
  766. ' generic TBird<{#Templ}T> = class',
  767. ' {=Templ}v: T;',
  768. ' end;',
  769. 'var',
  770. ' b: specialize TBird<word>;',
  771. ' {=Typ}w: T;',
  772. 'begin',
  773. ' b.v:=w;',
  774. '']);
  775. ParseProgram;
  776. end;
  777. procedure TTestResolveGenerics.TestGen_ClassDelphi;
  778. begin
  779. StartProgram(false);
  780. Add([
  781. '{$mode delphi}',
  782. 'type',
  783. ' TObject = class end;',
  784. ' {#Typ}T = word;',
  785. ' TBird<{#Templ}T> = class',
  786. ' {=Templ}v: T;',
  787. ' end;',
  788. 'var',
  789. ' b: TBird<word>;',
  790. ' {=Typ}w: T;',
  791. 'begin',
  792. ' b.v:=w;',
  793. '']);
  794. ParseProgram;
  795. end;
  796. procedure TTestResolveGenerics.TestGen_ClassDelphi_TypeOverload;
  797. begin
  798. StartProgram(false);
  799. Add([
  800. '{$mode delphi}',
  801. 'type',
  802. ' TObject = class end;',
  803. ' {#a}TBird = word;',
  804. ' {#b}TBird<T> = class',
  805. ' v: T;',
  806. ' end;',
  807. ' {=b}TEagle = TBird<word>;',
  808. 'var',
  809. ' b: {@b}TBird<word>;',
  810. ' {=a}w: TBird;',
  811. 'begin',
  812. ' b.v:=w;',
  813. '']);
  814. ParseProgram;
  815. end;
  816. procedure TTestResolveGenerics.TestGen_ClassObjFPC;
  817. begin
  818. StartProgram(false);
  819. Add([
  820. '{$mode objfpc}',
  821. 'type',
  822. ' TObject = class end;',
  823. ' generic TBird<T> = class',
  824. ' v: TBird;',
  825. ' end;',
  826. 'var',
  827. ' b: specialize TBird<word>;',
  828. 'begin',
  829. ' b.v:=b;',
  830. '']);
  831. ParseProgram;
  832. end;
  833. procedure TTestResolveGenerics.TestGen_ClassObjFPC_OverloadFail;
  834. begin
  835. StartProgram(false);
  836. Add([
  837. '{$mode objfpc}',
  838. 'type',
  839. ' TObject = class end;',
  840. ' TBird = word;',
  841. ' generic TBird<T> = class',
  842. ' v: T;',
  843. ' end;',
  844. 'begin',
  845. '']);
  846. CheckResolverException('Duplicate identifier "TBird" at afile.pp(5,8)',nDuplicateIdentifier);
  847. end;
  848. procedure TTestResolveGenerics.TestGen_ClassObjFPC_OverloadOtherUnit;
  849. begin
  850. AddModuleWithIntfImplSrc('unit1.pas',
  851. LinesToStr([
  852. 'type',
  853. ' TBird = class b1: word; end;',
  854. ' generic TAnt<T> = class a1: T; end;',
  855. '']),
  856. LinesToStr([
  857. '']));
  858. AddModuleWithIntfImplSrc('unit2.pas',
  859. LinesToStr([
  860. 'type',
  861. ' generic TBird<T> = class b2:T; end;',
  862. ' TAnt = class a2:word; end;',
  863. '']),
  864. LinesToStr([
  865. '']));
  866. StartProgram(true,[supTObject]);
  867. Add([
  868. 'uses unit1, unit2;',
  869. 'var',
  870. ' b1: TBird;',
  871. ' b2: specialize TBird<word>;',
  872. ' a1: specialize TAnt<word>;',
  873. ' a2: TAnt;',
  874. 'begin',
  875. ' b1.b1:=1;',
  876. ' b2.b2:=2;',
  877. ' a1.a1:=3;',
  878. ' a2.a2:=4;',
  879. '']);
  880. ParseProgram;
  881. end;
  882. procedure TTestResolveGenerics.TestGen_ClassGenAncestorWithoutParamFail;
  883. begin
  884. StartProgram(false);
  885. Add([
  886. '{$mode objfpc}',
  887. 'type',
  888. ' TObject = class end;',
  889. ' generic TBird<T> = class end;',
  890. ' generic TEagle<T> = class(TBird)',
  891. ' end;',
  892. 'begin',
  893. '']);
  894. CheckResolverException('Generics without specialization cannot be used as a type for a variable',
  895. nGenericsWithoutSpecializationAsType);
  896. end;
  897. procedure TTestResolveGenerics.TestGen_ClassForward;
  898. begin
  899. StartProgram(false);
  900. Add([
  901. '{$mode objfpc}',
  902. 'type',
  903. ' TObject = class end;',
  904. ' {#Typ}T = word;',
  905. ' generic TBird<{#Templ_Forward}T> = class;',
  906. ' TRec = record',
  907. ' b: specialize TBird<T>;',
  908. ' end;',
  909. ' generic TBird<{#Templ}T> = class',
  910. ' {=Templ}v: T;',
  911. ' r: TRec;',
  912. ' end;',
  913. 'var',
  914. ' s: TRec;',
  915. ' {=Typ}w: T;',
  916. 'begin',
  917. ' s.b.v:=w;',
  918. ' s.b.r:=s;',
  919. '']);
  920. ParseProgram;
  921. end;
  922. procedure TTestResolveGenerics.TestGen_ClassForwardConstraints;
  923. begin
  924. StartProgram(false);
  925. Add([
  926. '{$mode objfpc}',
  927. 'type',
  928. ' TObject = class end;',
  929. ' TAnt = class end;',
  930. ' generic TBird<T: class; U; V: TAnt> = class;',
  931. ' TRec = record',
  932. ' b: specialize TBird<TAnt,word,TAnt>;',
  933. ' end;',
  934. ' generic TBird<T: class; U; V: TAnt> = class',
  935. ' i: U;',
  936. ' r: TRec;',
  937. ' end;',
  938. 'var',
  939. ' s: TRec;',
  940. ' w: word;',
  941. 'begin',
  942. ' s.b.i:=w;',
  943. ' s.b.r:=s;',
  944. '']);
  945. ParseProgram;
  946. end;
  947. procedure TTestResolveGenerics.TestGen_ClassForwardConstraintNameMismatch;
  948. begin
  949. StartProgram(false);
  950. Add([
  951. '{$mode objfpc}',
  952. 'type',
  953. ' TObject = class end;',
  954. ' generic TBird<T> = class;',
  955. ' generic TBird<U> = class',
  956. ' i: U;',
  957. ' end;',
  958. 'begin',
  959. '']);
  960. CheckResolverException('Declaration of "U" differs from previous declaration at afile.pp(5,18)',
  961. nDeclOfXDiffersFromPrevAtY);
  962. end;
  963. procedure TTestResolveGenerics.TestGen_ClassForwardConstraintKeywordMismatch;
  964. begin
  965. StartProgram(false);
  966. Add([
  967. '{$mode objfpc}',
  968. 'type',
  969. ' TObject = class end;',
  970. ' generic TBird<T: class, constructor> = class;',
  971. ' generic TBird<U: class> = class',
  972. ' i: U;',
  973. ' end;',
  974. 'begin',
  975. '']);
  976. CheckResolverException('Declaration of "U" differs from previous declaration at afile.pp(5,18)',
  977. nDeclOfXDiffersFromPrevAtY);
  978. end;
  979. procedure TTestResolveGenerics.TestGen_ClassForwardConstraintTypeMismatch;
  980. begin
  981. StartProgram(false);
  982. Add([
  983. '{$mode objfpc}',
  984. 'type',
  985. ' TObject = class end;',
  986. ' TAnt = class end;',
  987. ' TFish = class end;',
  988. ' generic TBird<T: TAnt> = class;',
  989. ' generic TBird<T: TFish> = class',
  990. ' i: U;',
  991. ' end;',
  992. 'begin',
  993. '']);
  994. CheckResolverException('Declaration of "T" differs from previous declaration at afile.pp(7,18)',
  995. nDeclOfXDiffersFromPrevAtY);
  996. end;
  997. procedure TTestResolveGenerics.TestGen_ClassForward_Circle;
  998. begin
  999. StartProgram(false);
  1000. Add([
  1001. '{$mode objfpc}',
  1002. 'type',
  1003. ' TObject = class end;',
  1004. ' generic TAnt<T> = class;',
  1005. ' generic TFish<U> = class',
  1006. ' private type AliasU = U;',
  1007. ' var a: specialize TAnt<AliasU>;',
  1008. ' Size: AliasU;',
  1009. ' end;',
  1010. ' generic TAnt<T> = class',
  1011. ' private type AliasT = T;',
  1012. ' var f: specialize TFish<AliasT>;',
  1013. ' Speed: AliasT;',
  1014. ' end;',
  1015. 'var',
  1016. ' WordFish: specialize TFish<word>;',
  1017. ' BoolAnt: specialize TAnt<boolean>;',
  1018. ' w: word;',
  1019. ' b: boolean;',
  1020. 'begin',
  1021. ' WordFish.Size:=w;',
  1022. ' WordFish.a.Speed:=w;',
  1023. ' WordFish.a.f.Size:=w;',
  1024. ' BoolAnt.Speed:=b;',
  1025. ' BoolAnt.f.Size:=b;',
  1026. ' BoolAnt.f.a.Speed:=b;',
  1027. '']);
  1028. ParseProgram;
  1029. end;
  1030. procedure TTestResolveGenerics.TestGen_Class_RedeclareInUnitImplFail;
  1031. begin
  1032. StartUnit(false);
  1033. Add([
  1034. 'interface',
  1035. 'type',
  1036. ' TObject = class end;',
  1037. ' generic TBird<T> = class v: T; end;',
  1038. 'implementation',
  1039. 'type generic TBird<T> = record v: T; end;',
  1040. '']);
  1041. CheckResolverException('Duplicate identifier "TBird" at afile.pp(5,16)',
  1042. nDuplicateIdentifier);
  1043. end;
  1044. procedure TTestResolveGenerics.TestGen_Class_TypeOverloadInUnitImpl;
  1045. begin
  1046. StartUnit(false);
  1047. Add([
  1048. 'interface',
  1049. 'type',
  1050. ' TObject = class end;',
  1051. ' generic TBird<T> = class v: T; end;',
  1052. 'implementation',
  1053. 'type generic TBird<T,U> = record x: T; y: U; end;',
  1054. '']);
  1055. ParseUnit;
  1056. end;
  1057. procedure TTestResolveGenerics.TestGen_Class_MethodObjFPC;
  1058. begin
  1059. StartProgram(false);
  1060. Add([
  1061. '{$mode objfpc}',
  1062. 'type',
  1063. ' TObject = class end;',
  1064. ' {#Typ}T = word;',
  1065. ' generic TBird<{#Templ}T> = class',
  1066. ' function Fly(p:T): T; virtual; abstract;',
  1067. ' function Run(p:T): T;',
  1068. ' procedure Jump(p:T);',
  1069. ' class procedure Go(p:T);',
  1070. ' end;',
  1071. 'function TBird.Run(p:T): T;',
  1072. 'begin',
  1073. 'end;',
  1074. 'generic procedure TBird<T>.Jump(p:T);',
  1075. 'begin',
  1076. 'end;',
  1077. 'generic class procedure TBird<T>.Go(p:T);',
  1078. 'begin',
  1079. 'end;',
  1080. 'var',
  1081. ' b: specialize TBird<word>;',
  1082. ' {=Typ}w: T;',
  1083. 'begin',
  1084. ' w:=b.Fly(w);',
  1085. ' w:=b.Run(w);',
  1086. '']);
  1087. ParseProgram;
  1088. end;
  1089. procedure TTestResolveGenerics.TestGen_Class_MethodOverride;
  1090. begin
  1091. StartProgram(false);
  1092. Add([
  1093. '{$mode objfpc}',
  1094. 'type',
  1095. ' TObject = class end;',
  1096. ' generic TBird<T> = class',
  1097. ' function Fly(p:T): T; virtual; abstract;',
  1098. ' end;',
  1099. ' generic TEagle<S> = class(specialize TBird<S>)',
  1100. ' function Fly(p:S): S; override;',
  1101. ' end;',
  1102. 'function TEagle.Fly(p:S): S;',
  1103. 'begin',
  1104. 'end;',
  1105. 'var',
  1106. ' e: specialize TEagle<word>;',
  1107. ' w: word;',
  1108. 'begin',
  1109. ' w:=e.Fly(w);',
  1110. '']);
  1111. ParseProgram;
  1112. end;
  1113. procedure TTestResolveGenerics.TestGen_Class_MethodDelphi;
  1114. begin
  1115. StartProgram(false);
  1116. Add([
  1117. '{$mode delphi}',
  1118. 'type',
  1119. ' TObject = class end;',
  1120. ' {#Typ}T = word;',
  1121. ' TBird<{#Templ}T> = class',
  1122. ' function Fly(p:T): T; virtual; abstract;',
  1123. ' function Run(p:T): T;',
  1124. ' end;',
  1125. 'function TBird<T>.Run(p:T): T;',
  1126. 'begin',
  1127. 'end;',
  1128. 'var',
  1129. ' b: TBird<word>;',
  1130. ' {=Typ}w: T;',
  1131. 'begin',
  1132. ' w:=b.Fly(w);',
  1133. ' w:=b.Run(w);',
  1134. '']);
  1135. ParseProgram;
  1136. end;
  1137. procedure TTestResolveGenerics.TestGen_Class_MethodDelphiTypeParamMissing;
  1138. begin
  1139. StartProgram(false);
  1140. Add([
  1141. '{$mode delphi}',
  1142. 'type',
  1143. ' TObject = class end;',
  1144. ' TBird<T> = class',
  1145. ' function Run(p:T): T;',
  1146. ' end;',
  1147. 'function TBird.Run(p:T): T;',
  1148. 'begin',
  1149. 'end;',
  1150. 'begin',
  1151. '']);
  1152. CheckResolverException('TBird<> expected, but TBird found',nXExpectedButYFound);
  1153. end;
  1154. procedure TTestResolveGenerics.TestGen_Class_MethodImplConstraintFail;
  1155. begin
  1156. StartProgram(false);
  1157. Add([
  1158. '{$mode delphi}',
  1159. 'type',
  1160. ' TObject = class end;',
  1161. ' TBird<T: record> = class',
  1162. ' function Run(p:T): T;',
  1163. ' end;',
  1164. 'function TBird<T: record>.Run(p:T): T;',
  1165. 'begin',
  1166. 'end;',
  1167. 'begin',
  1168. '']);
  1169. CheckResolverException('illegal qualifier ":" after "T"',nIllegalQualifierAfter);
  1170. end;
  1171. procedure TTestResolveGenerics.TestGen_Class_MethodImplTypeParamNameMismatch;
  1172. begin
  1173. StartProgram(false);
  1174. Add([
  1175. '{$mode delphi}',
  1176. 'type',
  1177. ' TObject = class end;',
  1178. ' TBird<T> = class',
  1179. ' procedure DoIt;',
  1180. ' end;',
  1181. 'procedure TBird<S>.DoIt;',
  1182. 'begin',
  1183. 'end;',
  1184. 'begin',
  1185. '']);
  1186. CheckResolverException('T expected, but S found',nXExpectedButYFound);
  1187. end;
  1188. procedure TTestResolveGenerics.TestGen_Class_SpecializeSelfInside;
  1189. begin
  1190. StartProgram(false);
  1191. Add([
  1192. '{$mode objfpc}',
  1193. 'type',
  1194. ' TObject = class end;',
  1195. ' generic TBird<T> = class',
  1196. ' e: T;',
  1197. ' v: specialize TBird<boolean>;',
  1198. ' end;',
  1199. 'var',
  1200. ' b: specialize TBird<word>;',
  1201. ' w: word;',
  1202. 'begin',
  1203. ' b.e:=w;',
  1204. ' if b.v.e then ;',
  1205. '']);
  1206. ParseProgram;
  1207. end;
  1208. procedure TTestResolveGenerics.TestGen_Class_AncestorTFail;
  1209. begin
  1210. StartProgram(false);
  1211. Add([
  1212. '{$mode objfpc}',
  1213. 'type',
  1214. ' TObject = class end;',
  1215. ' TBird = class end;',
  1216. ' generic TFish<T: TBird> = class(T)',
  1217. ' v: T;',
  1218. ' end;',
  1219. 'begin',
  1220. '']);
  1221. CheckResolverException('class type expected, but T found',nXExpectedButYFound);
  1222. end;
  1223. procedure TTestResolveGenerics.TestGen_Class_GenAncestor;
  1224. begin
  1225. StartProgram(false);
  1226. Add([
  1227. '{$mode objfpc}',
  1228. 'type',
  1229. ' TObject = class end;',
  1230. ' generic TBird<T> = class',
  1231. ' i: T;',
  1232. ' end;',
  1233. ' generic TEagle<T> = class(specialize TBird<T>)',
  1234. ' j: T;',
  1235. ' end;',
  1236. 'var',
  1237. ' e: specialize TEagle<word>;',
  1238. 'begin',
  1239. ' e.i:=e.j;',
  1240. '']);
  1241. ParseProgram;
  1242. end;
  1243. procedure TTestResolveGenerics.TestGen_Class_AncestorSelfFail;
  1244. begin
  1245. StartProgram(false);
  1246. Add([
  1247. '{$mode objfpc}',
  1248. 'type',
  1249. ' TObject = class end;',
  1250. ' generic TBird<T> = class(specialize TBird<word>)',
  1251. ' e: T;',
  1252. ' end;',
  1253. 'var',
  1254. ' b: specialize TBird<word>;',
  1255. 'begin',
  1256. '']);
  1257. CheckResolverException('type "TBird<>" is not yet completely defined',nTypeXIsNotYetCompletelyDefined);
  1258. end;
  1259. procedure TTestResolveGenerics.TestGen_ClassOfSpecializeFail;
  1260. begin
  1261. StartProgram(false);
  1262. Add([
  1263. '{$mode objfpc}',
  1264. 'type',
  1265. ' TObject = class end;',
  1266. ' generic TBird<T> = class',
  1267. ' e: T;',
  1268. ' end;',
  1269. ' TBirdClass = class of specialize TBird<word>;',
  1270. 'begin',
  1271. '']);
  1272. CheckParserException('Expected "Identifier" at token "specialize" in file afile.pp at line 8 column 25',nParserExpectTokenError);
  1273. end;
  1274. procedure TTestResolveGenerics.TestGen_Class_NestedType;
  1275. begin
  1276. StartProgram(false);
  1277. Add([
  1278. '{$mode objfpc}',
  1279. 'type',
  1280. ' TObject = class end;',
  1281. ' generic TBird<T> = class',
  1282. ' public type',
  1283. ' TArrayEvent = reference to procedure(El: T);',
  1284. ' public',
  1285. ' p: TArrayEvent;',
  1286. ' end;',
  1287. ' TBirdWord = specialize TBird<word>;',
  1288. 'var',
  1289. ' b: TBirdWord;',
  1290. 'begin',
  1291. ' b.p:=procedure(El: word) begin end;']);
  1292. ParseProgram;
  1293. end;
  1294. procedure TTestResolveGenerics.TestGen_Class_NestedRecord;
  1295. begin
  1296. StartProgram(false);
  1297. Add([
  1298. '{$mode objfpc}',
  1299. '{$modeswitch advancedrecords}',
  1300. 'type',
  1301. ' TObject = class end;',
  1302. ' generic TBird<T> = class',
  1303. ' public type TWing = record',
  1304. ' s: T;',
  1305. ' function GetIt: T;',
  1306. ' end;',
  1307. ' public',
  1308. ' w: TWing;',
  1309. ' end;',
  1310. ' TBirdWord = specialize TBird<word>;',
  1311. 'function TBird.TWing.GetIt: T;',
  1312. 'begin',
  1313. 'end;',
  1314. 'var',
  1315. ' b: TBirdWord;',
  1316. ' i: word;',
  1317. 'begin',
  1318. ' b.w.s:=i;',
  1319. ' i:=b.w.GetIt;',
  1320. '']);
  1321. ParseProgram;
  1322. end;
  1323. procedure TTestResolveGenerics.TestGen_Class_NestedClass;
  1324. begin
  1325. StartProgram(false);
  1326. Add([
  1327. '{$mode objfpc}',
  1328. 'type',
  1329. ' TObject = class end;',
  1330. ' generic TBird<T> = class',
  1331. ' public type TWing = class',
  1332. ' s: T;',
  1333. ' function GetIt: T;',
  1334. ' end;',
  1335. ' public',
  1336. ' w: TWing;',
  1337. ' end;',
  1338. ' TBirdWord = specialize TBird<word>;',
  1339. 'function TBird.TWing.GetIt: T;',
  1340. 'begin',
  1341. 'end;',
  1342. 'var',
  1343. ' b: TBirdWord;',
  1344. ' i: word;',
  1345. 'begin',
  1346. ' b.w.s:=3;',
  1347. ' i:=b.w.GetIt;',
  1348. '']);
  1349. ParseProgram;
  1350. end;
  1351. procedure TTestResolveGenerics.TestGen_Class_Enums_NotPropagating;
  1352. begin
  1353. StartProgram(false);
  1354. Add([
  1355. '{$mode objfpc}',
  1356. 'type',
  1357. ' TObject = class end;',
  1358. ' generic TBird<T> = class',
  1359. ' public type',
  1360. ' TEnum = (red, blue);',
  1361. ' const',
  1362. ' e = blue;',
  1363. ' end;',
  1364. 'const',
  1365. ' r = red;',
  1366. 'begin']);
  1367. CheckResolverException('identifier not found "red"',nIdentifierNotFound);
  1368. end;
  1369. procedure TTestResolveGenerics.TestGen_Class_Self;
  1370. begin
  1371. StartProgram(false);
  1372. Add([
  1373. '{$mode objfpc}',
  1374. 'type',
  1375. ' TObject = class',
  1376. ' end;',
  1377. ' generic TAnimal<T> = class end;',
  1378. ' generic TBird<T> = class(specialize TAnimal<T>)',
  1379. ' function GetObj: TObject;',
  1380. ' procedure Fly(Obj: TObject); virtual; abstract;',
  1381. ' end;',
  1382. ' TProc = procedure(Obj: TObject) of object;',
  1383. ' TWordBird = specialize TBird<word>;',
  1384. 'function TBird.GetObj: TObject;',
  1385. 'var p: TProc;',
  1386. 'begin',
  1387. ' Result:=Self;',
  1388. ' if Self.GetObj=Result then ;',
  1389. ' Fly(Self);',
  1390. ' p:=@Fly;',
  1391. ' p(Self);',
  1392. 'end;',
  1393. 'begin']);
  1394. ParseProgram;
  1395. end;
  1396. procedure TTestResolveGenerics.TestGen_Class_MemberTypeConstructor;
  1397. begin
  1398. StartProgram(false);
  1399. Add([
  1400. '{$mode delphi}',
  1401. 'type',
  1402. ' TObject = class end;',
  1403. ' TAnimal<A> = class',
  1404. ' end;',
  1405. ' TAnt<L> = class',
  1406. ' constructor Create(A: TAnimal<L>);',
  1407. ' end;',
  1408. ' TBird<T> = class(TAnimal<T>)',
  1409. ' type TMyAnt = TAnt<T>;',
  1410. ' function Fly: TMyAnt;',
  1411. ' end;',
  1412. ' TWordBird = TBird<word>;',
  1413. 'constructor TAnt<L>.Create(A: TAnimal<L>);',
  1414. 'begin',
  1415. 'end;',
  1416. 'function TBird<T>.Fly: TMyAnt;',
  1417. 'begin',
  1418. ' Result:=TMyAnt.Create(Self);',
  1419. 'end;',
  1420. 'begin']);
  1421. ParseProgram;
  1422. end;
  1423. procedure TTestResolveGenerics.TestGen_Class_AliasMemberType;
  1424. begin
  1425. StartProgram(false);
  1426. Add([
  1427. '{$mode objfpc}',
  1428. '{$modeswitch externalclass}',
  1429. 'type',
  1430. ' TObject = class end;',
  1431. '',
  1432. ' generic TBird<T> = class',
  1433. ' public type',
  1434. ' TRun = reference to function (aValue : T) : T;',
  1435. ' end;',
  1436. ' TBirdWord = specialize TBird<Word>;',
  1437. ' TBirdWordRun = TBirdWord.TRun;',
  1438. '',
  1439. ' generic TExt<T> = class external name ''Ext''',
  1440. ' public type',
  1441. ' TRun = reference to function (aValue : T) : T;',
  1442. ' end;',
  1443. ' TExtWord = specialize TExt<Word>;',
  1444. ' TExtWordRun = TExtWord.TRun;',
  1445. 'begin',
  1446. '']);
  1447. ParseProgram;
  1448. end;
  1449. procedure TTestResolveGenerics.TestGen_Class_AccessGenericMemberTypeFail;
  1450. begin
  1451. StartProgram(false);
  1452. Add([
  1453. '{$mode objfpc}',
  1454. 'type',
  1455. ' TObject = class end;',
  1456. '',
  1457. ' generic TBird<T> = class',
  1458. ' public type',
  1459. ' TRun = reference to function (aValue : T) : T;',
  1460. ' end;',
  1461. ' TBirdRun = TBird.TRun;',
  1462. 'begin',
  1463. '']);
  1464. CheckResolverException('Generics without specialization cannot be used as a type for a reference',
  1465. nGenericsWithoutSpecializationAsType);
  1466. end;
  1467. procedure TTestResolveGenerics.TestGen_Class_ReferenceTo;
  1468. begin
  1469. StartProgram(false);
  1470. Add([
  1471. '{$mode objfpc}',
  1472. 'type',
  1473. ' TObject = class end;',
  1474. ' generic TGJSPromise<T> = class',
  1475. ' public type',
  1476. ' TGJSPromiseResolver = reference to function (aValue : T) : T;',
  1477. ' TGJSPromiseExecutor = reference to procedure (resolve,reject : TGJSPromiseResolver);',
  1478. ' public',
  1479. ' constructor new(Executor : TGJSPromiseExecutor);',
  1480. ' end;',
  1481. 'constructor TGJSPromise.new(Executor : TGJSPromiseExecutor);',
  1482. 'begin',
  1483. 'end;',
  1484. '',
  1485. 'type',
  1486. ' TJSPromise = specialize TGJSPromise<Word>;',
  1487. ' TJSPromiseResolver = reference to function (aValue : Word) : Word;',
  1488. '',
  1489. ' TURLLoader = Class(TObject)',
  1490. ' procedure dofetch(resolve, reject: TJSPromiseResolver); virtual; abstract;',
  1491. ' Function fetch : TJSPromise;',
  1492. ' end;',
  1493. 'function TURLLoader.fetch : TJSPromise;',
  1494. 'begin',
  1495. ' Result:=TJSPromise.New(@Dofetch);',
  1496. 'end;',
  1497. 'begin',
  1498. '']);
  1499. ParseProgram;
  1500. end;
  1501. procedure TTestResolveGenerics.TestGen_Class_TwoSpecsAreNotRelatedWarn;
  1502. begin
  1503. StartProgram(false);
  1504. Add([
  1505. '{$mode delphi}',
  1506. 'type',
  1507. ' TObject = class end;',
  1508. ' TBird<T> = class F: T; end;',
  1509. ' TBirdWord = TBird<Word>;',
  1510. ' TBirdChar = TBird<Char>;',
  1511. 'var',
  1512. ' w: TBirdWord;',
  1513. ' c: TBirdChar;',
  1514. 'begin',
  1515. ' w:=TBirdWord(c);',
  1516. '']);
  1517. ParseProgram;
  1518. CheckResolverHint(mtWarning,nClassTypesAreNotRelatedXY,'Class types "TBird<System.Char>" and "TBird<System.Word>" are not related');
  1519. end;
  1520. procedure TTestResolveGenerics.TestGen_Class_List;
  1521. begin
  1522. StartProgram(false);
  1523. Add([
  1524. '{$mode objfpc}',
  1525. 'type',
  1526. ' TObject = class end;',
  1527. ' generic TList<T> = class',
  1528. ' strict private',
  1529. ' FItems: array of T;',
  1530. ' function GetItems(Index: longint): T;',
  1531. ' procedure SetItems(Index: longint; Value: T);',
  1532. ' public',
  1533. ' procedure Alter(w: T);',
  1534. ' property Items[Index: longint]: T read GetItems write SetItems; default;',
  1535. ' end;',
  1536. ' TWordList = specialize TList<word>;',
  1537. 'function TList.GetItems(Index: longint): T;',
  1538. 'begin',
  1539. ' Result:=FItems[Index];',
  1540. 'end;',
  1541. 'procedure TList.SetItems(Index: longint; Value: T);',
  1542. 'begin',
  1543. ' FItems[Index]:=Value;',
  1544. 'end;',
  1545. 'procedure TList.Alter(w: T);',
  1546. 'begin',
  1547. ' SetLength(FItems,length(FItems)+1);',
  1548. ' Insert(w,FItems,2);',
  1549. ' Delete(FItems,2,3);',
  1550. 'end;',
  1551. 'var l: TWordList;',
  1552. ' w: word;',
  1553. 'begin',
  1554. ' l[1]:=w;',
  1555. ' w:=l[2];']);
  1556. ParseProgram;
  1557. end;
  1558. procedure TTestResolveGenerics.TestGen_Class_Typecast;
  1559. begin
  1560. StartProgram(false);
  1561. Add([
  1562. '{$mode delphi}',
  1563. 'type',
  1564. ' TObject = class end;',
  1565. ' TList<T> = class',
  1566. ' end;',
  1567. ' TEagle = class;',
  1568. ' TBird = class',
  1569. ' FLegs: TList<TBird>;',
  1570. ' property Legs: TList<TBird> read FLegs write FLegs;',
  1571. ' end;',
  1572. ' TEagle = class(TBird)',
  1573. ' end;',
  1574. 'var',
  1575. ' B: TBird;',
  1576. ' List: TList<TEagle>;',
  1577. 'begin',
  1578. ' List:=TList<TEagle>(B.Legs);',
  1579. ' TList<TEagle>(B.Legs):=List;',
  1580. '',
  1581. '']);
  1582. ParseProgram;
  1583. // FPC/pas2js: Class types "TList<afile.TBird>" and "TList<afile.TEagle>" are not related
  1584. // Delphi: no warning
  1585. end;
  1586. procedure TTestResolveGenerics.TestGen_ExtClass_Array;
  1587. begin
  1588. StartProgram(false);
  1589. Add([
  1590. '{$mode delphi}',
  1591. '{$ModeSwitch externalclass}',
  1592. 'type',
  1593. ' NativeInt = longint;',
  1594. ' TJSGenArray<T> = Class external name ''Array''',
  1595. ' private',
  1596. ' function GetElements(Index: NativeInt): T; external name ''[]'';',
  1597. ' procedure SetElements(Index: NativeInt; const AValue: T); external name ''[]'';',
  1598. ' public',
  1599. ' type TSelfType = TJSGenArray<T>;',
  1600. ' TArrayEvent = reference to function(El: T; Arr: TSelfType): Boolean;',
  1601. ' TArrayCallback = TArrayEvent;',
  1602. ' public',
  1603. ' FLength : NativeInt; external name ''length'';',
  1604. ' constructor new; overload;',
  1605. ' constructor new(aLength : NativeInt); overload;',
  1606. ' class function _of() : TSelfType; varargs; external name ''of'';',
  1607. ' function every(const aCallback: TArrayCallBack): boolean; overload;',
  1608. ' function fill(aValue : T) : TSelfType; overload;',
  1609. ' function fill(aValue : T; aStartIndex : NativeInt) : TSelfType; overload;',
  1610. ' function fill(aValue : T; aStartIndex,aEndIndex : NativeInt) : TSelfType; overload;',
  1611. ' property Length : NativeInt Read FLength Write FLength;',
  1612. ' property Elements[Index: NativeInt]: T read GetElements write SetElements; default;',
  1613. ' end;',
  1614. ' TJSWordArray = TJSGenArray<word>;',
  1615. 'var',
  1616. ' wa: TJSWordArray;',
  1617. ' w: word;',
  1618. 'begin',
  1619. ' wa:=TJSWordArray.new;',
  1620. ' wa:=TJSWordArray.new(3);',
  1621. ' wa:=TJSWordArray._of(4,5);',
  1622. ' wa:=wa.fill(7);',
  1623. ' wa:=wa.fill(7,8,9);',
  1624. ' w:=wa.length;',
  1625. ' wa.length:=10;',
  1626. ' wa[11]:=w;',
  1627. ' w:=wa[12];',
  1628. ' wa.every(function(El: word; Arr: TJSWordArray): Boolean',
  1629. ' begin',
  1630. ' end',
  1631. ' );',
  1632. '']);
  1633. ParseProgram;
  1634. end;
  1635. procedure TTestResolveGenerics.TestGen_ExtClass_VarargsOfType;
  1636. begin
  1637. StartProgram(false);
  1638. Add([
  1639. '{$mode objfpc}',
  1640. '{$modeswitch externalclass}',
  1641. 'type',
  1642. ' TJSObject = class external name ''Object''',
  1643. ' end;',
  1644. ' generic TGJSSet<T> = class external name ''Set''',
  1645. ' constructor new(aElement1: T); varargs of T; overload;',
  1646. ' function bind(thisArg: TJSObject): T; varargs of T;',
  1647. ' end;',
  1648. ' TJSWordSet = specialize TGJSSet<word>;',
  1649. 'var',
  1650. ' s: TJSWordSet;',
  1651. ' w: word;',
  1652. 'begin',
  1653. ' s:=TJSWordSet.new(3);',
  1654. ' s:=TJSWordSet.new(3,5);',
  1655. ' w:=s.bind(nil);',
  1656. ' w:=s.bind(nil,6);',
  1657. ' w:=s.bind(nil,7,8);',
  1658. '']);
  1659. ParseProgram;
  1660. end;
  1661. procedure TTestResolveGenerics.TestGen_ClassInterface;
  1662. begin
  1663. StartProgram(false);
  1664. Add([
  1665. 'type',
  1666. ' {$interfaces corba}',
  1667. ' generic ICorbaIntf<T> = interface',
  1668. ' procedure Fly(a: T);',
  1669. ' end;',
  1670. ' {$interfaces com}',
  1671. ' IUnknown = interface',
  1672. ' end;',
  1673. ' IInterface = IUnknown;',
  1674. ' generic IComIntf<T> = interface',
  1675. ' procedure Run(b: T);',
  1676. ' end;',
  1677. 'begin']);
  1678. ParseProgram;
  1679. end;
  1680. procedure TTestResolveGenerics.TestGen_ClassInterface_Method;
  1681. begin
  1682. StartProgram(false);
  1683. Add([
  1684. 'type',
  1685. ' {$interfaces corba}',
  1686. ' generic IBird<T> = interface',
  1687. ' procedure Fly(a: T);',
  1688. ' end;',
  1689. ' TObject = class end;',
  1690. ' generic TBird<U> = class(specialize IBird<U>)',
  1691. ' procedure Fly(a: U);',
  1692. ' end;',
  1693. 'procedure TBird.Fly(a: U);',
  1694. 'begin',
  1695. 'end;',
  1696. 'var b: specialize IBird<word>;',
  1697. 'begin',
  1698. ' b.Fly(3);']);
  1699. ParseProgram;
  1700. end;
  1701. procedure TTestResolveGenerics.TestGen_DynArray;
  1702. begin
  1703. StartProgram(false);
  1704. Add([
  1705. 'type',
  1706. ' generic TArray<T> = array of T;',
  1707. ' TWordArray = specialize TArray<word>;',
  1708. 'var',
  1709. ' a: specialize TArray<word>;',
  1710. ' b: TWordArray;',
  1711. ' w: word;',
  1712. 'begin',
  1713. ' a[1]:=2;',
  1714. ' b[2]:=a[3]+b[4];',
  1715. ' a:=b;',
  1716. ' b:=a;',
  1717. ' SetLength(a,5);',
  1718. ' SetLength(b,6);',
  1719. ' w:=length(a)+low(a)+high(a);',
  1720. '']);
  1721. ParseProgram;
  1722. end;
  1723. procedure TTestResolveGenerics.TestGen_StaticArray;
  1724. begin
  1725. StartProgram(false);
  1726. Add([
  1727. 'type',
  1728. ' generic TBird<T> = array[T] of word;',
  1729. ' TByteBird = specialize TBird<byte>;',
  1730. 'var',
  1731. ' a: specialize TBird<byte>;',
  1732. ' b: TByteBird;',
  1733. ' i: byte;',
  1734. 'begin',
  1735. ' a[1]:=2;',
  1736. ' b[2]:=a[3]+b[4];',
  1737. ' a:=b;',
  1738. ' b:=a;',
  1739. ' i:=low(a);',
  1740. ' i:=high(a);',
  1741. ' for i in a do ;',
  1742. '']);
  1743. ParseProgram;
  1744. end;
  1745. procedure TTestResolveGenerics.TestGen_Array_Anoynmous;
  1746. begin
  1747. StartProgram(false);
  1748. Add([
  1749. 'type',
  1750. ' generic TRec<T> = record',
  1751. ' a: array of T;',
  1752. ' end;',
  1753. ' TWordRec = specialize TRec<word>;',
  1754. 'var',
  1755. ' a: specialize TRec<word>;',
  1756. ' b: TWordRec;',
  1757. ' w: word;',
  1758. 'begin',
  1759. ' a:=b;',
  1760. ' a.a:=b.a;',
  1761. ' a.a[1]:=2;',
  1762. ' b.a[2]:=a.a[3]+b.a[4];',
  1763. ' b:=a;',
  1764. ' SetLength(a.a,5);',
  1765. ' SetLength(b.a,6);',
  1766. ' w:=length(a.a)+low(a.a)+high(a.a);',
  1767. '']);
  1768. ParseProgram;
  1769. end;
  1770. procedure TTestResolveGenerics.TestGen_ProcType;
  1771. begin
  1772. StartProgram(false);
  1773. Add([
  1774. 'type',
  1775. ' generic TFunc<T> = function(v: T): T;',
  1776. ' TWordFunc = specialize TFunc<word>;',
  1777. 'function GetIt(w: word): word;',
  1778. 'begin',
  1779. 'end;',
  1780. 'var',
  1781. ' a: specialize TFunc<word>;',
  1782. ' b: TWordFunc;',
  1783. ' w: word;',
  1784. 'begin',
  1785. ' a:=nil;',
  1786. ' b:=nil;',
  1787. ' a:=b;',
  1788. ' b:=a;',
  1789. ' w:=a(w);',
  1790. ' w:=b(w);',
  1791. ' a:=@GetIt;',
  1792. ' b:=@GetIt;',
  1793. '']);
  1794. ParseProgram;
  1795. end;
  1796. procedure TTestResolveGenerics.TestGen_ProcType_AnonymousFunc_Delphi;
  1797. begin
  1798. StartProgram(false);
  1799. Add([
  1800. '{$mode delphi}',
  1801. 'type',
  1802. ' TObject = class',
  1803. ' end;',
  1804. ' IInterface = interface',
  1805. ' end;',
  1806. ' Integer = longint;',
  1807. ' IComparer<T> = interface',
  1808. ' function Compare(const Left, Right: T): Integer; overload;',
  1809. ' end;',
  1810. ' TOnComparison<T> = function(const Left, Right: T): Integer of object;',
  1811. ' TComparisonFunc<T> = reference to function(const Left, Right: T): Integer;',
  1812. ' TComparer<T> = class(TObject, IComparer<T>)',
  1813. ' public',
  1814. ' function Compare(const Left, Right: T): Integer; overload;',
  1815. ' class function Construct(const AComparison: TOnComparison<T>): IComparer<T>; overload;',
  1816. ' class function Construct(const AComparison: TComparisonFunc<T>): IComparer<T>; overload;',
  1817. ' end;',
  1818. 'function TComparer<T>.Compare(const Left, Right: T): Integer; overload;',
  1819. 'begin',
  1820. 'end;',
  1821. 'class function TComparer<T>.Construct(const AComparison: TOnComparison<T>): IComparer<T>;',
  1822. 'begin',
  1823. 'end;',
  1824. 'class function TComparer<T>.Construct(const AComparison: TComparisonFunc<T>): IComparer<T>;',
  1825. 'begin',
  1826. 'end;',
  1827. 'procedure Test;',
  1828. 'var',
  1829. ' aComparer : IComparer<Integer>;',
  1830. 'begin',
  1831. ' aComparer:=TComparer<Integer>.Construct(function (Const a,b : integer) : integer',
  1832. ' begin',
  1833. ' Result:=a-b;',
  1834. ' end);',
  1835. 'end;',
  1836. 'begin',
  1837. ' Test;']);
  1838. ParseModule;
  1839. end;
  1840. procedure TTestResolveGenerics.TestGen_PointerDirectSpecializeFail;
  1841. begin
  1842. StartProgram(false);
  1843. Add([
  1844. 'type',
  1845. ' generic TRec<T> = record v: T; end;',
  1846. ' PRec = ^specialize TRec<word>;',
  1847. 'begin',
  1848. '']);
  1849. CheckParserException('Expected "Identifier or file"',nParserExpectTokenError);
  1850. end;
  1851. procedure TTestResolveGenerics.TestGen_HelperForArray;
  1852. begin
  1853. StartProgram(false);
  1854. Add([
  1855. '{$ModeSwitch typehelpers}',
  1856. 'type',
  1857. ' generic TArr<T> = array[1..2] of T;',
  1858. ' TWordArrHelper = type helper for specialize TArr<word>',
  1859. ' procedure Fly(w: word);',
  1860. ' end;',
  1861. 'procedure TWordArrHelper.Fly(w: word);',
  1862. 'begin',
  1863. 'end;',
  1864. 'var',
  1865. ' a: specialize TArr<word>;',
  1866. 'begin',
  1867. ' a.Fly(3);',
  1868. '']);
  1869. ParseProgram;
  1870. end;
  1871. procedure TTestResolveGenerics.TestGen_LocalVar;
  1872. begin
  1873. StartProgram(false);
  1874. Add([
  1875. '{$mode objfpc}',
  1876. 'type',
  1877. ' TObject = class end;',
  1878. ' generic TBird<{#Templ}T> = class',
  1879. ' function Fly(p:T): T;',
  1880. ' end;',
  1881. 'function TBird.Fly(p:T): T;',
  1882. 'var l: T;',
  1883. 'begin',
  1884. ' l:=p;',
  1885. ' p:=l;',
  1886. ' Result:=p;',
  1887. ' Result:=l;',
  1888. ' l:=Result;',
  1889. 'end;',
  1890. 'var',
  1891. ' b: specialize TBird<word>;',
  1892. ' w: word;',
  1893. 'begin',
  1894. ' w:=b.Fly(w);',
  1895. '']);
  1896. ParseProgram;
  1897. end;
  1898. procedure TTestResolveGenerics.TestGen_Statements;
  1899. begin
  1900. StartProgram(false);
  1901. Add([
  1902. '{$mode objfpc}',
  1903. 'type',
  1904. ' TObject = class end;',
  1905. ' generic TBird<{#Templ}T> = class',
  1906. ' function Fly(p:T): T;',
  1907. ' end;',
  1908. 'function TBird.Fly(p:T): T;',
  1909. 'var',
  1910. ' v1,v2,v3:T;',
  1911. 'begin',
  1912. ' v1:=1;',
  1913. ' v2:=v1+v1*v1+v1 div p;',
  1914. ' v3:=-v1;',
  1915. ' repeat',
  1916. ' v1:=v1+1;',
  1917. ' until v1>=5;',
  1918. ' while v1>=0 do',
  1919. ' v1:=v1-v2;',
  1920. ' for v1:=v2 to v3 do v2:=v1;',
  1921. ' if v1<v2 then v3:=v1 else v3:=v2;',
  1922. ' if v1<v2 then else ;',
  1923. ' case v1 of',
  1924. ' 1: v3:=3;',
  1925. ' end;',
  1926. 'end;',
  1927. 'var',
  1928. ' b: specialize TBird<word>;',
  1929. 'begin',
  1930. ' b.Fly(2);',
  1931. '']);
  1932. ParseProgram;
  1933. end;
  1934. procedure TTestResolveGenerics.TestGen_InlineSpecializeExpr;
  1935. begin
  1936. StartProgram(false);
  1937. Add([
  1938. '{$mode objfpc}',
  1939. 'type',
  1940. ' TObject = class end;',
  1941. ' generic TBird<T> = class',
  1942. ' constructor Create;',
  1943. ' end;',
  1944. ' generic TAnt<U> = class',
  1945. ' constructor Create;',
  1946. ' end;',
  1947. 'constructor TBird.Create;',
  1948. 'var',
  1949. ' a: specialize TAnt<T>;',
  1950. ' b: specialize TAnt<word>;',
  1951. 'begin',
  1952. ' a:=specialize TAnt<T>.create;',
  1953. ' b:=specialize TAnt<word>.create;',
  1954. 'end;',
  1955. 'constructor TAnt.Create;',
  1956. 'var',
  1957. ' i: specialize TBird<U>;',
  1958. ' j: specialize TBird<word>;',
  1959. ' k: specialize TAnt<U>;',
  1960. 'begin',
  1961. ' i:=specialize TBird<U>.create;',
  1962. ' j:=specialize TBird<word>.create;',
  1963. ' k:=specialize TAnt<U>.create;',
  1964. 'end;',
  1965. 'var a: specialize TAnt<word>;',
  1966. 'begin',
  1967. ' a:=specialize TAnt<word>.create;',
  1968. '']);
  1969. ParseProgram;
  1970. end;
  1971. procedure TTestResolveGenerics.TestGen_TryExcept;
  1972. begin
  1973. StartProgram(false);
  1974. Add([
  1975. '{$mode objfpc}',
  1976. 'type',
  1977. ' TObject = class end;',
  1978. ' generic TBird<{#Templ}T> = class',
  1979. ' function Fly(p:T): T;',
  1980. ' end;',
  1981. ' Exception = class',
  1982. ' end;',
  1983. ' generic EMsg<T> = class',
  1984. ' Msg: T;',
  1985. ' end;',
  1986. 'function TBird.Fly(p:T): T;',
  1987. 'var',
  1988. ' v1,v2,v3:T;',
  1989. 'begin',
  1990. ' try',
  1991. ' finally',
  1992. ' end;',
  1993. ' try',
  1994. ' v1:=v2;',
  1995. ' finally',
  1996. ' v2:=v1;',
  1997. ' end;',
  1998. ' try',
  1999. ' except',
  2000. ' on Exception do ;',
  2001. ' on E: Exception do ;',
  2002. ' on E: specialize EMsg<boolean> do E.Msg:=true;',
  2003. ' on E: specialize EMsg<T> do E.Msg:=1;',
  2004. ' end;',
  2005. 'end;',
  2006. 'var',
  2007. ' b: specialize TBird<word>;',
  2008. 'begin',
  2009. ' b.Fly(2);',
  2010. '']);
  2011. ParseProgram;
  2012. end;
  2013. procedure TTestResolveGenerics.TestGen_Call;
  2014. begin
  2015. StartProgram(false);
  2016. Add([
  2017. '{$mode objfpc}',
  2018. 'type',
  2019. ' TObject = class end;',
  2020. ' generic TBird<T> = class',
  2021. ' function Fly(p:T): T;',
  2022. ' end;',
  2023. 'procedure Run(b: boolean); overload;',
  2024. 'begin end;',
  2025. 'procedure Run(w: word); overload;',
  2026. 'begin end;',
  2027. 'function TBird.Fly(p:T): T;',
  2028. 'begin',
  2029. ' Run(p);',
  2030. ' Run(Result);',
  2031. 'end;',
  2032. 'var',
  2033. ' w: specialize TBird<word>;',
  2034. ' b: specialize TBird<boolean>;',
  2035. 'begin',
  2036. '']);
  2037. ParseProgram;
  2038. end;
  2039. procedure TTestResolveGenerics.TestGen_NestedProc;
  2040. begin
  2041. StartProgram(false);
  2042. Add([
  2043. '{$mode objfpc}',
  2044. 'type',
  2045. ' TObject = class end;',
  2046. ' generic TBird<T> = class',
  2047. ' function Fly(p:T): T;',
  2048. ' end;',
  2049. 'function TBird.Fly(p:T): T;',
  2050. ' function Run: T;',
  2051. ' begin',
  2052. ' Fly:=Result;',
  2053. ' end;',
  2054. 'begin',
  2055. ' Run;',
  2056. 'end;',
  2057. 'var',
  2058. ' w: specialize TBird<word>;',
  2059. ' b: specialize TBird<boolean>;',
  2060. 'begin',
  2061. '']);
  2062. ParseProgram;
  2063. end;
  2064. procedure TTestResolveGenerics.TestGenProc_Function;
  2065. begin
  2066. StartProgram(false);
  2067. Add([
  2068. 'generic function DoIt<T>(a: T): T;',
  2069. 'var i: T;',
  2070. 'begin',
  2071. ' a:=i;',
  2072. ' Result:=a;',
  2073. 'end;',
  2074. 'var w: word;',
  2075. 'begin',
  2076. ' w:=specialize DoIt<word>(3);',
  2077. '']);
  2078. ParseProgram;
  2079. end;
  2080. procedure TTestResolveGenerics.TestGenProc_FunctionDelphi;
  2081. begin
  2082. StartProgram(false);
  2083. Add([
  2084. '{$mode delphi}',
  2085. 'function DoIt<T>(a: T): T;',
  2086. 'var i: T;',
  2087. 'begin',
  2088. ' a:=i;',
  2089. ' Result:=a;',
  2090. 'end;',
  2091. 'var w: word;',
  2092. 'begin',
  2093. ' w:=DoIt<word>(3);',
  2094. '']);
  2095. ParseProgram;
  2096. end;
  2097. procedure TTestResolveGenerics.TestGenProc_OverloadDuplicate;
  2098. begin
  2099. StartProgram(false);
  2100. Add([
  2101. 'generic procedure Fly<T>(a: T);',
  2102. 'begin',
  2103. 'end;',
  2104. 'generic procedure Fly<T>(a: T);',
  2105. 'begin',
  2106. 'end;',
  2107. 'begin',
  2108. '']);
  2109. CheckResolverException('Duplicate identifier "Fly" at afile.pp(2,22)',nDuplicateIdentifier);
  2110. end;
  2111. procedure TTestResolveGenerics.TestGenProc_MissingTemplatesFail;
  2112. begin
  2113. StartProgram(false);
  2114. Add([
  2115. 'generic procedure Run;',
  2116. 'begin',
  2117. 'end;',
  2118. 'begin',
  2119. '']);
  2120. CheckParserException('Expected "<"',nParserExpectTokenError);
  2121. end;
  2122. procedure TTestResolveGenerics.TestGenProc_SpecializeNonGenericFail;
  2123. begin
  2124. StartProgram(false);
  2125. Add([
  2126. 'procedure Run;',
  2127. 'begin',
  2128. 'end;',
  2129. 'begin',
  2130. ' specialize Run<word>();',
  2131. '']);
  2132. CheckResolverException('Run expected, but Run<> found',nXExpectedButYFound);
  2133. end;
  2134. procedure TTestResolveGenerics.TestGenProc_Forward;
  2135. begin
  2136. StartProgram(false);
  2137. Add([
  2138. 'generic procedure Fly<T>(a: T); forward;',
  2139. 'procedure Run;',
  2140. 'begin',
  2141. ' specialize Fly<word>(3);',
  2142. 'end;',
  2143. 'generic procedure Fly<T>(a: T);',
  2144. 'var i: T;',
  2145. 'begin',
  2146. ' i:=a;',
  2147. 'end;',
  2148. 'begin',
  2149. ' specialize Fly<boolean>(true);',
  2150. '']);
  2151. ParseProgram;
  2152. end;
  2153. procedure TTestResolveGenerics.TestGenProc_External;
  2154. begin
  2155. StartProgram(false);
  2156. Add([
  2157. 'generic function Fly<T>(a: T): T; external name ''flap'';',
  2158. 'procedure Run;',
  2159. 'begin',
  2160. ' specialize Fly<word>(3);',
  2161. 'end;',
  2162. 'begin',
  2163. ' specialize Fly<boolean>(true);',
  2164. '']);
  2165. ParseProgram;
  2166. end;
  2167. procedure TTestResolveGenerics.TestGenProc_UnitIntf;
  2168. begin
  2169. AddModuleWithIntfImplSrc('unit2.pas',
  2170. LinesToStr([
  2171. 'generic function Fly<T>(a: T): T;',
  2172. '']),
  2173. LinesToStr([
  2174. 'generic function Fly<T>(a: T): T;',
  2175. 'var i: T;',
  2176. 'begin',
  2177. ' i:=a;',
  2178. 'end;',
  2179. '']));
  2180. StartProgram(true);
  2181. Add([
  2182. 'uses unit2;',
  2183. 'var w: word;',
  2184. 'begin',
  2185. ' w:=specialize Fly<word>(3);',
  2186. ' if specialize Fly<boolean>(false) then ;',
  2187. '']);
  2188. ParseProgram;
  2189. end;
  2190. procedure TTestResolveGenerics.TestGenProc_BackRef1Fail;
  2191. begin
  2192. StartProgram(false);
  2193. Add([
  2194. 'generic function Fly<T>(a: Fly): T;',
  2195. 'begin',
  2196. 'end;',
  2197. 'begin',
  2198. '']);
  2199. CheckResolverException('Wrong number of parameters specified for call to "function Fly<>(untyped)"',nWrongNumberOfParametersForCallTo);
  2200. end;
  2201. procedure TTestResolveGenerics.TestGenProc_BackRef2Fail;
  2202. begin
  2203. StartProgram(false);
  2204. Add([
  2205. 'generic function Fly<T>(a: Fly<word>): T;',
  2206. 'begin',
  2207. 'end;',
  2208. 'begin',
  2209. '']);
  2210. CheckResolverException('Wrong number of parameters specified for call to "function Fly<>(untyped)"',nWrongNumberOfParametersForCallTo);
  2211. end;
  2212. procedure TTestResolveGenerics.TestGenProc_BackRef3Fail;
  2213. begin
  2214. StartProgram(false);
  2215. Add([
  2216. 'generic function Fly<T>(a: Fly<T>): T;',
  2217. 'begin',
  2218. 'end;',
  2219. 'begin',
  2220. '']);
  2221. CheckResolverException('Wrong number of parameters specified for call to "function Fly<>(untyped)"',nWrongNumberOfParametersForCallTo);
  2222. end;
  2223. procedure TTestResolveGenerics.TestGenProc_CallSelf;
  2224. begin
  2225. StartProgram(false);
  2226. Add([
  2227. 'generic function Fly<T>(a: T): T;',
  2228. ' procedure Run;',
  2229. ' begin',
  2230. ' specialize Fly<T>(a);',
  2231. ' specialize Fly<word>(3);',
  2232. ' end;',
  2233. 'begin',
  2234. ' specialize Fly<T>(a);',
  2235. ' specialize Fly<boolean>(true);',
  2236. 'end;',
  2237. 'begin',
  2238. ' specialize Fly<string>(''fast'');',
  2239. '']);
  2240. ParseProgram;
  2241. end;
  2242. procedure TTestResolveGenerics.TestGenProc_CallSelfNoParams;
  2243. begin
  2244. StartProgram(false);
  2245. Add([
  2246. 'generic function Fly<T>(a: T = 0): T;',
  2247. ' procedure Run;',
  2248. ' begin',
  2249. ' specialize Fly<T>;',
  2250. ' specialize Fly<word>;',
  2251. ' end;',
  2252. 'begin',
  2253. ' specialize Fly<T>;',
  2254. ' specialize Fly<byte>;',
  2255. 'end;',
  2256. 'begin',
  2257. ' specialize Fly<shortint>;',
  2258. '']);
  2259. ParseProgram;
  2260. end;
  2261. procedure TTestResolveGenerics.TestGenProc_ForwardConstraints;
  2262. begin
  2263. StartProgram(false);
  2264. Add([
  2265. 'type',
  2266. ' TObject = class end;',
  2267. ' TBird = class end;',
  2268. 'var b: TBird;',
  2269. 'generic function Fly<T: class>(a: T): T; forward;',
  2270. 'procedure Run;',
  2271. 'begin',
  2272. ' specialize Fly<TBird>(b);',
  2273. 'end;',
  2274. 'generic function Fly<T>(a: T): T;',
  2275. 'begin',
  2276. 'end;',
  2277. 'begin',
  2278. ' specialize Fly<TBird>(b);',
  2279. '']);
  2280. ParseProgram;
  2281. end;
  2282. procedure TTestResolveGenerics.TestGenProc_ForwardConstraintsRepeatFail;
  2283. begin
  2284. StartProgram(false);
  2285. Add([
  2286. 'type',
  2287. ' TObject = class end;',
  2288. 'generic function Fly<T: class>(a: T): T; forward;',
  2289. 'generic function Fly<T: class>(a: T): T;',
  2290. 'begin',
  2291. 'end;',
  2292. 'begin',
  2293. '']);
  2294. CheckResolverException(sImplMustNotRepeatConstraints,nImplMustNotRepeatConstraints);
  2295. end;
  2296. procedure TTestResolveGenerics.TestGenProc_ForwardTempNameMismatch;
  2297. begin
  2298. StartProgram(false);
  2299. Add([
  2300. 'generic function Fly<T>(a: T): T; forward;',
  2301. 'generic function Fly<B>(a: B): B;',
  2302. 'begin',
  2303. 'end;',
  2304. 'begin',
  2305. '']);
  2306. CheckResolverException('Declaration of "Fly<B>" differs from previous declaration at afile.pp(2,23)',
  2307. nDeclOfXDiffersFromPrevAtY);
  2308. end;
  2309. procedure TTestResolveGenerics.TestGenProc_ForwardOverload;
  2310. begin
  2311. StartProgram(false);
  2312. Add([
  2313. 'generic function {#FlyA}Fly<T>(a: T; b: boolean): T; forward; overload;',
  2314. 'generic function {#FlyB}Fly<T>(a: T; w: word): T; forward; overload;',
  2315. 'procedure {#FlyC}Fly; overload;',
  2316. 'begin',
  2317. ' specialize {@FlyA}Fly<longint>(1,true);',
  2318. ' specialize {@FlyB}Fly<string>(''ABC'',3);',
  2319. 'end;',
  2320. 'generic function Fly<T>(a: T; b: boolean): T;',
  2321. 'begin',
  2322. 'end;',
  2323. 'generic function Fly<T>(a: T; w: word): T;',
  2324. 'begin',
  2325. 'end;',
  2326. 'begin',
  2327. '']);
  2328. ParseProgram;
  2329. end;
  2330. procedure TTestResolveGenerics.TestGenProc_NestedFail;
  2331. begin
  2332. StartProgram(false);
  2333. Add([
  2334. 'procedure Fly;',
  2335. ' generic procedure Run<T>(a: T);',
  2336. ' begin',
  2337. ' end;',
  2338. 'begin',
  2339. ' Run<boolean>(true);',
  2340. 'end;',
  2341. 'begin',
  2342. '']);
  2343. CheckResolverException('Type parameters not allowed on nested procedure',nTypeParamsNotAllowedOnX);
  2344. end;
  2345. procedure TTestResolveGenerics.TestGenProc_TypeParamCntOverload;
  2346. begin
  2347. StartProgram(false);
  2348. Add([
  2349. 'generic procedure {#A}Run<T>(a: T);',
  2350. 'begin',
  2351. 'end;',
  2352. 'generic procedure {#B}Run<M,N>(a: M);',
  2353. 'begin',
  2354. ' specialize {@A}Run<M>(a);',
  2355. ' specialize {@B}Run<double,char>(1.3);',
  2356. 'end;',
  2357. 'begin',
  2358. ' specialize {@A}Run<word>(3);',
  2359. ' specialize {@B}Run<word,char>(4);',
  2360. '']);
  2361. ParseProgram;
  2362. end;
  2363. procedure TTestResolveGenerics.TestGenProc_TypeParamCntOverloadNoParams;
  2364. begin
  2365. StartProgram(false);
  2366. Add([
  2367. 'generic procedure {#A}Run<T>;',
  2368. 'begin',
  2369. 'end;',
  2370. 'generic procedure {#B}Run<M,N>;',
  2371. 'begin',
  2372. ' specialize {@A}Run<M>;',
  2373. ' specialize {@A}Run<M>();',
  2374. ' specialize {@B}Run<double,char>;',
  2375. ' specialize {@B}Run<double,char>();',
  2376. 'end;',
  2377. 'begin',
  2378. ' specialize {@A}Run<word>;',
  2379. ' specialize {@A}Run<word>();',
  2380. ' specialize {@B}Run<word,char>;',
  2381. ' specialize {@B}Run<word,char>();',
  2382. '']);
  2383. ParseProgram;
  2384. end;
  2385. procedure TTestResolveGenerics.TestGenProc_TypeParamWithDefaultParamDelphiFail;
  2386. begin
  2387. // delphi 10.3 does not allow default values for args with generic types
  2388. StartProgram(false);
  2389. Add([
  2390. '{$mode delphi}',
  2391. 'procedure {#A}Run<T>(a: T = 0); overload;',
  2392. 'begin',
  2393. 'end;',
  2394. 'begin',
  2395. '']);
  2396. CheckResolverException(sParamOfThisTypeCannotHaveDefVal,nParamOfThisTypeCannotHaveDefVal);
  2397. end;
  2398. procedure TTestResolveGenerics.TestGenProc_ParamSpecWithT;
  2399. begin
  2400. StartProgram(false);
  2401. Add([
  2402. '{$mode delphi}',
  2403. 'type',
  2404. ' TObject = class end;',
  2405. ' TBird<T> = class v: T; end;',
  2406. ' TAnt = class',
  2407. ' procedure Func<T: class>(Bird: TBird<T>);',
  2408. ' end;',
  2409. 'procedure TAnt.Func<T>(Bird: TBird<T>);',
  2410. 'begin',
  2411. 'end;',
  2412. 'var',
  2413. ' Ant: TAnt;',
  2414. ' Bird: TBird<TObject>;',
  2415. ' BirdOfBird: TBird<TBird<TObject>>;',
  2416. 'begin',
  2417. ' Ant.Func<TObject>(Bird);',
  2418. ' Ant.Func<TBird<TObject>>(BirdOfBird);',
  2419. '']);
  2420. ParseProgram;
  2421. end;
  2422. procedure TTestResolveGenerics.TestGenProc_Infer_NeedExplicitFail;
  2423. begin
  2424. StartProgram(false);
  2425. Add([
  2426. '{$mode delphi}',
  2427. 'function {#A}Run<S,T>(a: S): T; overload;',
  2428. 'begin',
  2429. 'end;',
  2430. 'begin',
  2431. ' {@A}Run(1);',
  2432. '']);
  2433. CheckResolverException('Could not infer generic type argument "T" for method "Run"',
  2434. nCouldNotInferTypeArgXForMethodY);
  2435. end;
  2436. procedure TTestResolveGenerics.TestGenProc_Infer_Overload;
  2437. begin
  2438. StartProgram(false);
  2439. Add([
  2440. '{$mode delphi}',
  2441. 'procedure {#A}Run<S>(a: S; b: boolean); overload;',
  2442. 'begin',
  2443. 'end;',
  2444. 'procedure {#B}Run<T>(a: T; w: word); overload;',
  2445. 'begin',
  2446. 'end;',
  2447. 'procedure {#C}Run<U>(a: U; b: U); overload;',
  2448. 'begin',
  2449. 'end;',
  2450. 'begin',
  2451. ' {@A}Run(1,true);', // non generic take precedence
  2452. ' {@B}Run(2,word(3));', // non generic take precedence
  2453. ' {@C}Run(''foo'',''bar'');',
  2454. '']);
  2455. ParseProgram;
  2456. end;
  2457. procedure TTestResolveGenerics.TestGenProc_Infer_OverloadForward;
  2458. begin
  2459. StartProgram(false);
  2460. Add([
  2461. '{$mode delphi}',
  2462. 'procedure {#A}Run<S>(a: S; b: boolean); forward; overload;',
  2463. 'procedure {#B}Run<T>(a: T; w: word); forward; overload;',
  2464. 'procedure {#C}Run<U>(a: U; b: U); forward; overload;',
  2465. 'procedure {#A2}Run<S>(a: S; b: boolean); overload;',
  2466. 'begin',
  2467. ' {@A}Run(1,true);', // non generic take precedence
  2468. ' {@B}Run(2,word(3));', // non generic take precedence
  2469. ' {@C}Run(''foo'',''bar'');',
  2470. 'end;',
  2471. 'procedure {#B2}Run<T>(a: T; w: word); overload;',
  2472. 'begin',
  2473. 'end;',
  2474. 'procedure {#C2}Run<U>(a: U; b: U); overload;',
  2475. 'begin',
  2476. 'end;',
  2477. 'begin',
  2478. ' {@A}Run(1,true);', // non generic take precedence
  2479. ' {@B}Run(2,word(3));', // non generic take precedence
  2480. ' {@C}Run(''foo'',''bar'');',
  2481. '']);
  2482. ParseProgram;
  2483. end;
  2484. procedure TTestResolveGenerics.TestGenProc_Infer_Var_Overload;
  2485. begin
  2486. StartProgram(false);
  2487. Add([
  2488. '{$mode delphi}',
  2489. 'procedure {#A}Run<S>(var a: S; var b: boolean); overload;',
  2490. 'begin',
  2491. 'end;',
  2492. 'procedure {#B}Run<T>(var a: T; var w: word); overload;',
  2493. 'begin',
  2494. 'end;',
  2495. 'procedure {#C}Run<U>(var a: U; var b: U); overload;',
  2496. 'begin',
  2497. 'end;',
  2498. 'var',
  2499. ' w: word;',
  2500. ' b: boolean;',
  2501. ' s: string;',
  2502. 'begin',
  2503. ' {@A}Run(w,b);',
  2504. ' {@B}Run(s,w);',
  2505. ' {@C}Run(s,s);',
  2506. '']);
  2507. ParseProgram;
  2508. end;
  2509. procedure TTestResolveGenerics.TestGenProc_Infer_Widen;
  2510. begin
  2511. StartProgram(false);
  2512. Add([
  2513. '{$mode delphi}',
  2514. 'procedure {#A}Run<S>(a: S; b: S);',
  2515. 'begin',
  2516. 'end;',
  2517. 'begin',
  2518. ' {@A}Run(word(1),longint(2));',
  2519. ' {@A}Run(int64(1),longint(2));',
  2520. ' {@A}Run(boolean(false),wordbool(2));',
  2521. ' {@A}Run(''a'',''foo'');',
  2522. '']);
  2523. ParseProgram;
  2524. end;
  2525. procedure TTestResolveGenerics.TestGenProc_Infer_DefaultValue;
  2526. begin
  2527. StartProgram(false);
  2528. Add([
  2529. '{$mode objfpc}',
  2530. '{$modeswitch implicitfunctionspecialization}',
  2531. 'generic procedure {#A}Run<S>(a: S = 2; b: S = 10); overload;',
  2532. 'begin',
  2533. 'end;',
  2534. 'begin',
  2535. ' {@A}Run(1,2);',
  2536. ' {@A}Run(3);',
  2537. ' {@A}Run();',
  2538. '']);
  2539. ParseProgram;
  2540. end;
  2541. procedure TTestResolveGenerics.TestGenProc_Infer_DefaultValueMismatch;
  2542. begin
  2543. StartProgram(false);
  2544. Add([
  2545. '{$mode objfpc}',
  2546. '{$modeswitch implicitfunctionspecialization}',
  2547. 'generic procedure {#A}Run<S>(a: S; b: S = 10); overload;',
  2548. 'begin',
  2549. 'end;',
  2550. 'begin',
  2551. ' {@A}Run(false,true);',
  2552. '']);
  2553. CheckResolverException('Incompatible types: got "Longint" expected "Boolean"',
  2554. nIncompatibleTypesGotExpected);
  2555. end;
  2556. procedure TTestResolveGenerics.TestGenProc_Infer_ProcT;
  2557. begin
  2558. StartProgram(false);
  2559. Add([
  2560. '{$mode delphi}',
  2561. 'type',
  2562. ' TProc<S> = reference to procedure(a: S);',
  2563. ' TObject = class',
  2564. ' procedure {#A}Run<T: class>(a: TProc<T>);',
  2565. ' end;',
  2566. ' TBird = class end;',
  2567. 'procedure Tobject.Run<T>(a: TProc<T>);',
  2568. 'begin',
  2569. 'end;',
  2570. 'var obj: TObject;',
  2571. 'begin',
  2572. ' obj.{@A}Run<TBird>(procedure(Bird: TBird) begin end);',
  2573. //' obj.{@A}Run(procedure(Bird: TBird) begin end);', // not supported by Delphi
  2574. '']);
  2575. ParseProgram;
  2576. end;
  2577. procedure TTestResolveGenerics.TestGenProc_Infer_Mismatch;
  2578. begin
  2579. StartProgram(false);
  2580. Add([
  2581. '{$mode delphi}',
  2582. 'procedure Run<T>(a: T; b: T);',
  2583. 'begin',
  2584. 'end;',
  2585. 'begin',
  2586. ' Run(1,true);',
  2587. '']);
  2588. CheckResolverException('Inferred type "T" from different arguments mismatch for method "Run"',
  2589. nInferredTypeXFromDiffArgsMismatchFromMethodY);
  2590. end;
  2591. procedure TTestResolveGenerics.TestGenProc_Infer_ArrayOfT;
  2592. begin
  2593. StartProgram(false);
  2594. Add([
  2595. '{$mode delphi}',
  2596. 'procedure Run<T>(a: array of T);',
  2597. 'var b: T;',
  2598. 'begin',
  2599. ' b:=3;',
  2600. 'end;',
  2601. 'var Arr: array of byte;',
  2602. 'begin',
  2603. ' Run(Arr);',
  2604. '']);
  2605. ParseProgram;
  2606. end;
  2607. procedure TTestResolveGenerics.TestGenProc_Infer_PassAsArgDelphi;
  2608. begin
  2609. StartProgram(false);
  2610. Add([
  2611. '{$mode delphi}',
  2612. 'function Run<T>(a: T): T;',
  2613. 'var b: T;',
  2614. 'begin',
  2615. ' Run(Run<word>(3));',
  2616. ' Run(Run(4));',
  2617. 'end;',
  2618. 'begin',
  2619. ' Run(Run<word>(5));',
  2620. ' Run(Run(6));',
  2621. '']);
  2622. ParseProgram;
  2623. end;
  2624. procedure TTestResolveGenerics.TestGenProc_Infer_PassAsArgObjFPC;
  2625. begin
  2626. StartProgram(false);
  2627. Add([
  2628. '{$mode objfpc}',
  2629. '{$ModeSwitch implicitfunctionspecialization}',
  2630. 'generic function Run<T>(a: T): T;',
  2631. 'var b: T;',
  2632. 'begin',
  2633. ' Run(specialize Run<word>(3));',
  2634. ' Run(Run(4));',
  2635. 'end;',
  2636. 'begin',
  2637. ' Run(specialize Run<word>(5));',
  2638. ' Run(Run(6));',
  2639. '']);
  2640. ParseProgram;
  2641. end;
  2642. procedure TTestResolveGenerics.TestGenMethod_VirtualFail;
  2643. begin
  2644. StartProgram(false);
  2645. Add([
  2646. 'type',
  2647. ' TObject = class',
  2648. ' generic procedure Run<T>(a: T); virtual; abstract;',
  2649. ' end;',
  2650. 'begin',
  2651. '']);
  2652. CheckResolverException('virtual, dynamic or message methods cannot have type parameters',
  2653. nXMethodsCannotHaveTypeParams);
  2654. end;
  2655. procedure TTestResolveGenerics.TestGenMethod_PublishedFail;
  2656. begin
  2657. StartProgram(false);
  2658. Add([
  2659. 'type',
  2660. ' TObject = class',
  2661. ' published',
  2662. ' generic procedure Run<T>(a: T);',
  2663. ' end;',
  2664. 'generic procedure TObject.Run<T>(a: T);',
  2665. 'begin',
  2666. 'end;',
  2667. 'begin',
  2668. '']);
  2669. CheckResolverException('published methods cannot have type parameters',
  2670. nXMethodsCannotHaveTypeParams);
  2671. end;
  2672. procedure TTestResolveGenerics.TestGenMethod_ClassInterfaceMethodFail;
  2673. begin
  2674. StartProgram(false);
  2675. Add([
  2676. 'type',
  2677. ' IUnknown = interface',
  2678. ' generic procedure Run<T>(a: T); virtual; abstract;',
  2679. ' end;',
  2680. 'begin',
  2681. '']);
  2682. CheckParserException('generic is not allowed in interface',nParserXNotAllowedInY);
  2683. end;
  2684. procedure TTestResolveGenerics.TestGenMethod_ClassConstructorFail;
  2685. begin
  2686. StartProgram(false);
  2687. Add([
  2688. 'type',
  2689. ' TObject = class',
  2690. ' generic class constructor Run<T>(a: T);',
  2691. ' end;',
  2692. 'generic class constructor TObject.Run<T>(a: T);',
  2693. 'begin end;',
  2694. 'begin',
  2695. '']);
  2696. CheckParserException('Expected "Procedure" or "Function" at token "constructor" in file afile.pp at line 4 column 19',
  2697. nParserExpectToken2Error);
  2698. end;
  2699. procedure TTestResolveGenerics.TestGenMethod_TemplNameDifferFail;
  2700. begin
  2701. StartProgram(false);
  2702. Add([
  2703. 'type',
  2704. ' TObject = class',
  2705. ' generic procedure Run<T>(a: T);',
  2706. ' end;',
  2707. 'generic procedure TObject.Run<S>(a: S);',
  2708. 'begin',
  2709. 'end;',
  2710. 'begin',
  2711. '']);
  2712. CheckResolverException('Declaration of "TObject.Run<S>" differs from previous declaration at afile.pp(4,28)',
  2713. nDeclOfXDiffersFromPrevAtY);
  2714. end;
  2715. procedure TTestResolveGenerics.TestGenMethod_ImplConstraintFail;
  2716. begin
  2717. StartProgram(false);
  2718. Add([
  2719. 'type',
  2720. ' TObject = class',
  2721. ' generic procedure Run<T>(a: T);',
  2722. ' end;',
  2723. 'generic procedure TObject.Run<T: class>(a: T);',
  2724. 'begin',
  2725. 'end;',
  2726. 'begin',
  2727. '']);
  2728. CheckResolverException(sImplMustNotRepeatConstraints,nImplMustNotRepeatConstraints);
  2729. end;
  2730. procedure TTestResolveGenerics.TestGenMethod_NestedSelf;
  2731. begin
  2732. StartProgram(false);
  2733. Add([
  2734. 'type',
  2735. ' TObject = class',
  2736. ' w: word;',
  2737. ' generic function Fly<T>(a: T): T;',
  2738. ' end;',
  2739. 'generic function TObject.Fly<T>(a: T): T;',
  2740. ' function Sub: T;',
  2741. ' begin',
  2742. ' Result:=w+a;',
  2743. ' Result:=Self.w+a;',
  2744. //' specialize Fly<T> :=', not supported by FPC/Delphi
  2745. ' end;',
  2746. 'begin',
  2747. ' Result:=Sub;',
  2748. ' Result:=Self.w+Sub+a;',
  2749. 'end;',
  2750. 'var Obj: TObject;',
  2751. 'begin',
  2752. ' if Obj.specialize Fly<smallint>(3)=4 then ;',
  2753. '']);
  2754. ParseProgram;
  2755. end;
  2756. procedure TTestResolveGenerics.TestGenMethod_OverloadTypeParamCntObjFPC;
  2757. begin
  2758. StartProgram(false);
  2759. Add([
  2760. 'type',
  2761. ' TObject = class',
  2762. ' generic procedure {#A}Run<T>(a: T);',
  2763. ' generic procedure {#B}Run<M,N>(a: M);',
  2764. ' end;',
  2765. 'generic procedure TObject.Run<T>(a: T);',
  2766. 'begin',
  2767. 'end;',
  2768. 'generic procedure TObject.Run<M,N>(a: M);',
  2769. 'begin',
  2770. ' specialize {@A}Run<M>(a);',
  2771. ' specialize {@B}Run<double,char>(1.3);',
  2772. 'end;',
  2773. 'var obj: TObject;',
  2774. 'begin',
  2775. ' obj.specialize {@A}Run<word>(3);',
  2776. ' obj.specialize {@B}Run<word,char>(4);',
  2777. '']);
  2778. ParseProgram;
  2779. end;
  2780. procedure TTestResolveGenerics.TestGenMethod_OverloadTypeParamCntDelphi;
  2781. begin
  2782. StartProgram(false);
  2783. Add([
  2784. '{$mode delphi}',
  2785. 'type',
  2786. ' TObject = class',
  2787. ' procedure {#A}Run<T>(a: T); overload;',
  2788. ' procedure {#B}Run<M,N>(a: M); overload;',
  2789. ' end;',
  2790. 'procedure TObject.Run<T>(a: T);',
  2791. 'begin',
  2792. 'end;',
  2793. 'procedure TObject.Run<M,N>(a: M);',
  2794. 'begin',
  2795. ' {@A}Run<M>(a);',
  2796. ' {@B}Run<double,char>(1.3);',
  2797. 'end;',
  2798. 'var obj: TObject;',
  2799. 'begin',
  2800. ' obj.{@A}Run<word>(3);',
  2801. ' obj.{@B}Run<word,char>(4);',
  2802. '']);
  2803. ParseProgram;
  2804. end;
  2805. procedure TTestResolveGenerics.TestGenMethod_OverloadArgs;
  2806. begin
  2807. StartProgram(false);
  2808. Add([
  2809. 'type',
  2810. ' TObject = class',
  2811. ' generic function {#A}Run<T>(a: boolean): T;',
  2812. ' generic function {#B}Run<M>(a: word): M;',
  2813. ' end;',
  2814. 'generic function TObject.Run<T>(a: boolean): T;',
  2815. 'begin',
  2816. 'end;',
  2817. 'generic function TObject.Run<M>(a: word): M;',
  2818. 'begin',
  2819. ' Result:=specialize Run<M>(a);',
  2820. ' if specialize {@A}Run<string>(true)=''foo'' then ;',
  2821. ' if specialize {@B}Run<byte>(3)=4 then ;',
  2822. 'end;',
  2823. 'var obj: TObject;',
  2824. 'begin',
  2825. ' if obj.specialize {@A}Run<string>(true)=''bar'' then ;',
  2826. ' if obj.specialize {@B}Run<byte>(5)=6 then ;',
  2827. '']);
  2828. ParseProgram;
  2829. end;
  2830. procedure TTestResolveGenerics.TestGenMethod_TypeCastParam;
  2831. begin
  2832. StartUnit(false);
  2833. Add([
  2834. '{$mode delphi}',
  2835. 'interface',
  2836. 'type',
  2837. ' TObject = class end;',
  2838. ' TArray<T> = array of T;',
  2839. ' TBird = class',
  2840. ' F: TArray<TObject>;',
  2841. ' procedure Run<S>(a: TArray<S>);',
  2842. ' end;',
  2843. 'implementation',
  2844. 'procedure TBird.Run<S>(a: TArray<S>);',
  2845. 'begin',
  2846. ' a:=TArray<S>(a);',
  2847. //' F:=TArray<TObject>(a);',
  2848. 'end;',
  2849. '']);
  2850. ParseUnit;
  2851. end;
  2852. initialization
  2853. RegisterTests([TTestResolveGenerics]);
  2854. end.