tcresolvegenerics.pas 65 KB

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