types.nim 60 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745
  1. #
  2. #
  3. # The Nim Compiler
  4. # (c) Copyright 2013 Andreas Rumpf
  5. #
  6. # See the file "copying.txt", included in this
  7. # distribution, for details about the copyright.
  8. #
  9. # this module contains routines for accessing and iterating over types
  10. import
  11. intsets, ast, astalgo, trees, msgs, strutils, platform, renderer, options,
  12. lineinfos, int128, modulegraphs, astmsgs
  13. when defined(nimPreviewSlimSystem):
  14. import std/[assertions, formatfloat]
  15. type
  16. TPreferedDesc* = enum
  17. preferName, # default
  18. preferDesc, # probably should become what preferResolved is
  19. preferExported,
  20. preferModuleInfo, # fully qualified
  21. preferGenericArg,
  22. preferTypeName,
  23. preferResolved, # fully resolved symbols
  24. preferMixed,
  25. # most useful, shows: symbol + resolved symbols if it differs, e.g.:
  26. # tuple[a: MyInt{int}, b: float]
  27. TTypeRelation* = enum # order is important!
  28. isNone, isConvertible,
  29. isIntConv,
  30. isSubtype,
  31. isSubrange, # subrange of the wanted type; no type conversion
  32. # but apart from that counts as ``isSubtype``
  33. isBothMetaConvertible # generic proc parameter was matched against
  34. # generic type, e.g., map(mySeq, x=>x+1),
  35. # maybe recoverable by rerun if the parameter is
  36. # the proc's return value
  37. isInferred, # generic proc was matched against a concrete type
  38. isInferredConvertible, # same as above, but requiring proc CC conversion
  39. isGeneric,
  40. isFromIntLit, # conversion *from* int literal; proven safe
  41. isEqual
  42. ProcConvMismatch* = enum
  43. pcmNoSideEffect
  44. pcmNotGcSafe
  45. pcmLockDifference
  46. pcmNotIterator
  47. pcmDifferentCallConv
  48. proc typeToString*(typ: PType; prefer: TPreferedDesc = preferName): string
  49. proc addTypeDeclVerboseMaybe*(result: var string, conf: ConfigRef; typ: PType) =
  50. if optDeclaredLocs in conf.globalOptions:
  51. result.add typeToString(typ, preferMixed)
  52. result.addDeclaredLoc(conf, typ)
  53. else:
  54. result.add typeToString(typ)
  55. template `$`*(typ: PType): string = typeToString(typ)
  56. proc base*(t: PType): PType =
  57. result = t[0]
  58. # ------------------- type iterator: ----------------------------------------
  59. type
  60. TTypeIter* = proc (t: PType, closure: RootRef): bool {.nimcall.} # true if iteration should stop
  61. TTypeMutator* = proc (t: PType, closure: RootRef): PType {.nimcall.} # copy t and mutate it
  62. TTypePredicate* = proc (t: PType): bool {.nimcall.}
  63. proc iterOverType*(t: PType, iter: TTypeIter, closure: RootRef): bool
  64. # Returns result of `iter`.
  65. proc mutateType*(t: PType, iter: TTypeMutator, closure: RootRef): PType
  66. # Returns result of `iter`.
  67. type
  68. TParamsEquality* = enum # they are equal, but their
  69. # identifiers or their return
  70. # type differ (i.e. they cannot be
  71. # overloaded)
  72. # this used to provide better error messages
  73. paramsNotEqual, # parameters are not equal
  74. paramsEqual, # parameters are equal
  75. paramsIncompatible
  76. proc equalParams*(a, b: PNode): TParamsEquality
  77. # returns whether the parameter lists of the procs a, b are exactly the same
  78. const
  79. # TODO: Remove tyTypeDesc from each abstractX and (where necessary)
  80. # replace with typedescX
  81. abstractPtrs* = {tyVar, tyPtr, tyRef, tyGenericInst, tyDistinct, tyOrdinal,
  82. tyTypeDesc, tyAlias, tyInferred, tySink, tyLent, tyOwned}
  83. abstractVar* = {tyVar, tyGenericInst, tyDistinct, tyOrdinal, tyTypeDesc,
  84. tyAlias, tyInferred, tySink, tyLent, tyOwned}
  85. abstractRange* = {tyGenericInst, tyRange, tyDistinct, tyOrdinal, tyTypeDesc,
  86. tyAlias, tyInferred, tySink, tyOwned}
  87. abstractInstOwned* = abstractInst + {tyOwned}
  88. skipPtrs* = {tyVar, tyPtr, tyRef, tyGenericInst, tyTypeDesc, tyAlias,
  89. tyInferred, tySink, tyLent, tyOwned}
  90. # typedescX is used if we're sure tyTypeDesc should be included (or skipped)
  91. typedescPtrs* = abstractPtrs + {tyTypeDesc}
  92. typedescInst* = abstractInst + {tyTypeDesc, tyOwned, tyUserTypeClass}
  93. proc invalidGenericInst*(f: PType): bool =
  94. result = f.kind == tyGenericInst and lastSon(f) == nil
  95. proc isPureObject*(typ: PType): bool =
  96. var t = typ
  97. while t.kind == tyObject and t[0] != nil:
  98. t = t[0].skipTypes(skipPtrs)
  99. result = t.sym != nil and sfPure in t.sym.flags
  100. proc isUnsigned*(t: PType): bool =
  101. t.skipTypes(abstractInst).kind in {tyChar, tyUInt..tyUInt64}
  102. proc getOrdValue*(n: PNode; onError = high(Int128)): Int128 =
  103. var k = n.kind
  104. if n.typ != nil and n.typ.skipTypes(abstractInst).kind in {tyChar, tyUInt..tyUInt64}:
  105. k = nkUIntLit
  106. case k
  107. of nkCharLit, nkUIntLit..nkUInt64Lit:
  108. # XXX: enable this assert
  109. #assert n.typ == nil or isUnsigned(n.typ), $n.typ
  110. toInt128(cast[uint64](n.intVal))
  111. of nkIntLit..nkInt64Lit:
  112. # XXX: enable this assert
  113. #assert n.typ == nil or not isUnsigned(n.typ), $n.typ.kind
  114. toInt128(n.intVal)
  115. of nkNilLit:
  116. int128.Zero
  117. of nkHiddenStdConv: getOrdValue(n[1], onError)
  118. else:
  119. # XXX: The idea behind the introduction of int128 was to finally
  120. # have all calculations numerically far away from any
  121. # overflows. This command just introduces such overflows and
  122. # should therefore really be revisited.
  123. onError
  124. proc getFloatValue*(n: PNode): BiggestFloat =
  125. case n.kind
  126. of nkFloatLiterals: n.floatVal
  127. of nkHiddenStdConv: getFloatValue(n[1])
  128. else: NaN
  129. proc isIntLit*(t: PType): bool {.inline.} =
  130. result = t.kind == tyInt and t.n != nil and t.n.kind == nkIntLit
  131. proc isFloatLit*(t: PType): bool {.inline.} =
  132. result = t.kind == tyFloat and t.n != nil and t.n.kind == nkFloatLit
  133. proc addTypeHeader*(result: var string, conf: ConfigRef; typ: PType; prefer: TPreferedDesc = preferMixed; getDeclarationPath = true) =
  134. result.add typeToString(typ, prefer)
  135. if getDeclarationPath: result.addDeclaredLoc(conf, typ.sym)
  136. proc getProcHeader*(conf: ConfigRef; sym: PSym; prefer: TPreferedDesc = preferName; getDeclarationPath = true): string =
  137. assert sym != nil
  138. # consider using `skipGenericOwner` to avoid fun2.fun2 when fun2 is generic
  139. result = sym.owner.name.s & '.' & sym.name.s
  140. if sym.kind in routineKinds:
  141. result.add '('
  142. var n = sym.typ.n
  143. for i in 1..<n.len:
  144. let p = n[i]
  145. if p.kind == nkSym:
  146. result.add(p.sym.name.s)
  147. result.add(": ")
  148. result.add(typeToString(p.sym.typ, prefer))
  149. if i != n.len-1: result.add(", ")
  150. else:
  151. result.add renderTree(p)
  152. result.add(')')
  153. if n[0].typ != nil:
  154. result.add(": " & typeToString(n[0].typ, prefer))
  155. if getDeclarationPath: result.addDeclaredLoc(conf, sym)
  156. proc elemType*(t: PType): PType =
  157. assert(t != nil)
  158. case t.kind
  159. of tyGenericInst, tyDistinct, tyAlias, tySink: result = elemType(lastSon(t))
  160. of tyArray: result = t[1]
  161. of tyError: result = t
  162. else: result = t.lastSon
  163. assert(result != nil)
  164. proc enumHasHoles*(t: PType): bool =
  165. var b = t.skipTypes({tyRange, tyGenericInst, tyAlias, tySink})
  166. result = b.kind == tyEnum and tfEnumHasHoles in b.flags
  167. proc isOrdinalType*(t: PType, allowEnumWithHoles: bool = false): bool =
  168. assert(t != nil)
  169. const
  170. baseKinds = {tyChar, tyInt..tyInt64, tyUInt..tyUInt64, tyBool, tyEnum}
  171. parentKinds = {tyRange, tyOrdinal, tyGenericInst, tyAlias, tySink, tyDistinct}
  172. result = (t.kind in baseKinds and (not t.enumHasHoles or allowEnumWithHoles)) or
  173. (t.kind in parentKinds and isOrdinalType(t.lastSon, allowEnumWithHoles))
  174. proc iterOverTypeAux(marker: var IntSet, t: PType, iter: TTypeIter,
  175. closure: RootRef): bool
  176. proc iterOverNode(marker: var IntSet, n: PNode, iter: TTypeIter,
  177. closure: RootRef): bool =
  178. if n != nil:
  179. case n.kind
  180. of nkNone..nkNilLit:
  181. # a leaf
  182. result = iterOverTypeAux(marker, n.typ, iter, closure)
  183. else:
  184. for i in 0..<n.len:
  185. result = iterOverNode(marker, n[i], iter, closure)
  186. if result: return
  187. proc iterOverTypeAux(marker: var IntSet, t: PType, iter: TTypeIter,
  188. closure: RootRef): bool =
  189. result = false
  190. if t == nil: return
  191. result = iter(t, closure)
  192. if result: return
  193. if not containsOrIncl(marker, t.id):
  194. case t.kind
  195. of tyGenericInst, tyGenericBody, tyAlias, tySink, tyInferred:
  196. result = iterOverTypeAux(marker, lastSon(t), iter, closure)
  197. else:
  198. for i in 0..<t.len:
  199. result = iterOverTypeAux(marker, t[i], iter, closure)
  200. if result: return
  201. if t.n != nil and t.kind != tyProc: result = iterOverNode(marker, t.n, iter, closure)
  202. proc iterOverType(t: PType, iter: TTypeIter, closure: RootRef): bool =
  203. var marker = initIntSet()
  204. result = iterOverTypeAux(marker, t, iter, closure)
  205. proc searchTypeForAux(t: PType, predicate: TTypePredicate,
  206. marker: var IntSet): bool
  207. proc searchTypeNodeForAux(n: PNode, p: TTypePredicate,
  208. marker: var IntSet): bool =
  209. result = false
  210. case n.kind
  211. of nkRecList:
  212. for i in 0..<n.len:
  213. result = searchTypeNodeForAux(n[i], p, marker)
  214. if result: return
  215. of nkRecCase:
  216. assert(n[0].kind == nkSym)
  217. result = searchTypeNodeForAux(n[0], p, marker)
  218. if result: return
  219. for i in 1..<n.len:
  220. case n[i].kind
  221. of nkOfBranch, nkElse:
  222. result = searchTypeNodeForAux(lastSon(n[i]), p, marker)
  223. if result: return
  224. else: discard
  225. of nkSym:
  226. result = searchTypeForAux(n.sym.typ, p, marker)
  227. else: discard
  228. proc searchTypeForAux(t: PType, predicate: TTypePredicate,
  229. marker: var IntSet): bool =
  230. # iterates over VALUE types!
  231. result = false
  232. if t == nil: return
  233. if containsOrIncl(marker, t.id): return
  234. result = predicate(t)
  235. if result: return
  236. case t.kind
  237. of tyObject:
  238. if t[0] != nil:
  239. result = searchTypeForAux(t[0].skipTypes(skipPtrs), predicate, marker)
  240. if not result: result = searchTypeNodeForAux(t.n, predicate, marker)
  241. of tyGenericInst, tyDistinct, tyAlias, tySink:
  242. result = searchTypeForAux(lastSon(t), predicate, marker)
  243. of tyArray, tySet, tyTuple:
  244. for i in 0..<t.len:
  245. result = searchTypeForAux(t[i], predicate, marker)
  246. if result: return
  247. else:
  248. discard
  249. proc searchTypeFor*(t: PType, predicate: TTypePredicate): bool =
  250. var marker = initIntSet()
  251. result = searchTypeForAux(t, predicate, marker)
  252. proc isObjectPredicate(t: PType): bool =
  253. result = t.kind == tyObject
  254. proc containsObject*(t: PType): bool =
  255. result = searchTypeFor(t, isObjectPredicate)
  256. proc isObjectWithTypeFieldPredicate(t: PType): bool =
  257. result = t.kind == tyObject and t[0] == nil and
  258. not (t.sym != nil and {sfPure, sfInfixCall} * t.sym.flags != {}) and
  259. tfFinal notin t.flags
  260. type
  261. TTypeFieldResult* = enum
  262. frNone, # type has no object type field
  263. frHeader, # type has an object type field only in the header
  264. frEmbedded # type has an object type field somewhere embedded
  265. proc analyseObjectWithTypeFieldAux(t: PType,
  266. marker: var IntSet): TTypeFieldResult =
  267. var res: TTypeFieldResult
  268. result = frNone
  269. if t == nil: return
  270. case t.kind
  271. of tyObject:
  272. if t.n != nil:
  273. if searchTypeNodeForAux(t.n, isObjectWithTypeFieldPredicate, marker):
  274. return frEmbedded
  275. for i in 0..<t.len:
  276. var x = t[i]
  277. if x != nil: x = x.skipTypes(skipPtrs)
  278. res = analyseObjectWithTypeFieldAux(x, marker)
  279. if res == frEmbedded:
  280. return frEmbedded
  281. if res == frHeader: result = frHeader
  282. if result == frNone:
  283. if isObjectWithTypeFieldPredicate(t): result = frHeader
  284. of tyGenericInst, tyDistinct, tyAlias, tySink:
  285. result = analyseObjectWithTypeFieldAux(lastSon(t), marker)
  286. of tyArray, tyTuple:
  287. for i in 0..<t.len:
  288. res = analyseObjectWithTypeFieldAux(t[i], marker)
  289. if res != frNone:
  290. return frEmbedded
  291. else:
  292. discard
  293. proc analyseObjectWithTypeField*(t: PType): TTypeFieldResult =
  294. # this does a complex analysis whether a call to ``objectInit`` needs to be
  295. # made or initializing of the type field suffices or if there is no type field
  296. # at all in this type.
  297. var marker = initIntSet()
  298. result = analyseObjectWithTypeFieldAux(t, marker)
  299. proc isGCRef(t: PType): bool =
  300. result = t.kind in GcTypeKinds or
  301. (t.kind == tyProc and t.callConv == ccClosure)
  302. if result and t.kind in {tyString, tySequence} and tfHasAsgn in t.flags:
  303. result = false
  304. proc containsGarbageCollectedRef*(typ: PType): bool =
  305. # returns true if typ contains a reference, sequence or string (all the
  306. # things that are garbage-collected)
  307. result = searchTypeFor(typ, isGCRef)
  308. proc isManagedMemory(t: PType): bool =
  309. result = t.kind in GcTypeKinds or
  310. (t.kind == tyProc and t.callConv == ccClosure)
  311. proc containsManagedMemory*(typ: PType): bool =
  312. result = searchTypeFor(typ, isManagedMemory)
  313. proc isTyRef(t: PType): bool =
  314. result = t.kind == tyRef or (t.kind == tyProc and t.callConv == ccClosure)
  315. proc containsTyRef*(typ: PType): bool =
  316. # returns true if typ contains a 'ref'
  317. result = searchTypeFor(typ, isTyRef)
  318. proc isHiddenPointer(t: PType): bool =
  319. result = t.kind in {tyString, tySequence, tyOpenArray, tyVarargs}
  320. proc containsHiddenPointer*(typ: PType): bool =
  321. # returns true if typ contains a string, table or sequence (all the things
  322. # that need to be copied deeply)
  323. result = searchTypeFor(typ, isHiddenPointer)
  324. proc canFormAcycleAux(marker: var IntSet, typ: PType, startId: int): bool
  325. proc canFormAcycleNode(marker: var IntSet, n: PNode, startId: int): bool =
  326. result = false
  327. if n != nil:
  328. result = canFormAcycleAux(marker, n.typ, startId)
  329. if not result:
  330. case n.kind
  331. of nkNone..nkNilLit:
  332. discard
  333. else:
  334. for i in 0..<n.len:
  335. result = canFormAcycleNode(marker, n[i], startId)
  336. if result: return
  337. proc canFormAcycleAux(marker: var IntSet, typ: PType, startId: int): bool =
  338. result = false
  339. if typ == nil: return
  340. if tfAcyclic in typ.flags: return
  341. var t = skipTypes(typ, abstractInst+{tyOwned}-{tyTypeDesc})
  342. if tfAcyclic in t.flags: return
  343. case t.kind
  344. of tyTuple, tyObject, tyRef, tySequence, tyArray, tyOpenArray, tyVarargs:
  345. if t.id == startId:
  346. result = true
  347. elif not containsOrIncl(marker, t.id):
  348. for i in 0..<t.len:
  349. result = canFormAcycleAux(marker, t[i], startId)
  350. if result: return
  351. if t.n != nil: result = canFormAcycleNode(marker, t.n, startId)
  352. # Inheritance can introduce cyclic types, however this is not relevant
  353. # as the type that is passed to 'new' is statically known!
  354. # er but we use it also for the write barrier ...
  355. if t.kind == tyObject and tfFinal notin t.flags:
  356. # damn inheritance may introduce cycles:
  357. result = true
  358. of tyProc: result = typ.callConv == ccClosure
  359. else: discard
  360. proc isFinal*(t: PType): bool =
  361. let t = t.skipTypes(abstractInst)
  362. result = t.kind != tyObject or tfFinal in t.flags or isPureObject(t)
  363. proc canFormAcycle*(typ: PType): bool =
  364. var marker = initIntSet()
  365. let t = skipTypes(typ, abstractInst+{tyOwned}-{tyTypeDesc})
  366. result = canFormAcycleAux(marker, t, t.id)
  367. proc mutateTypeAux(marker: var IntSet, t: PType, iter: TTypeMutator,
  368. closure: RootRef): PType
  369. proc mutateNode(marker: var IntSet, n: PNode, iter: TTypeMutator,
  370. closure: RootRef): PNode =
  371. result = nil
  372. if n != nil:
  373. result = copyNode(n)
  374. result.typ = mutateTypeAux(marker, n.typ, iter, closure)
  375. case n.kind
  376. of nkNone..nkNilLit:
  377. # a leaf
  378. discard
  379. else:
  380. for i in 0..<n.len:
  381. result.add mutateNode(marker, n[i], iter, closure)
  382. proc mutateTypeAux(marker: var IntSet, t: PType, iter: TTypeMutator,
  383. closure: RootRef): PType =
  384. result = nil
  385. if t == nil: return
  386. result = iter(t, closure)
  387. if not containsOrIncl(marker, t.id):
  388. for i in 0..<t.len:
  389. result[i] = mutateTypeAux(marker, result[i], iter, closure)
  390. if t.n != nil: result.n = mutateNode(marker, t.n, iter, closure)
  391. assert(result != nil)
  392. proc mutateType(t: PType, iter: TTypeMutator, closure: RootRef): PType =
  393. var marker = initIntSet()
  394. result = mutateTypeAux(marker, t, iter, closure)
  395. proc valueToString(a: PNode): string =
  396. case a.kind
  397. of nkCharLit..nkUInt64Lit: result = $a.intVal
  398. of nkFloatLit..nkFloat128Lit: result = $a.floatVal
  399. of nkStrLit..nkTripleStrLit: result = a.strVal
  400. else: result = "<invalid value>"
  401. proc rangeToStr(n: PNode): string =
  402. assert(n.kind == nkRange)
  403. result = valueToString(n[0]) & ".." & valueToString(n[1])
  404. const
  405. typeToStr: array[TTypeKind, string] = ["None", "bool", "char", "empty",
  406. "Alias", "typeof(nil)", "untyped", "typed", "typeDesc",
  407. # xxx typeDesc=>typedesc: typedesc is declared as such, and is 10x more common.
  408. "GenericInvocation", "GenericBody", "GenericInst", "GenericParam",
  409. "distinct $1", "enum", "ordinal[$1]", "array[$1, $2]", "object", "tuple",
  410. "set[$1]", "range[$1]", "ptr ", "ref ", "var ", "seq[$1]", "proc",
  411. "pointer", "OpenArray[$1]", "string", "cstring", "Forward",
  412. "int", "int8", "int16", "int32", "int64",
  413. "float", "float32", "float64", "float128",
  414. "uint", "uint8", "uint16", "uint32", "uint64",
  415. "owned", "sink",
  416. "lent ", "varargs[$1]", "UncheckedArray[$1]", "Error Type",
  417. "BuiltInTypeClass", "UserTypeClass",
  418. "UserTypeClassInst", "CompositeTypeClass", "inferred",
  419. "and", "or", "not", "any", "static", "TypeFromExpr", "concept", # xxx bugfix
  420. "void", "iterable"]
  421. const preferToResolveSymbols = {preferName, preferTypeName, preferModuleInfo,
  422. preferGenericArg, preferResolved, preferMixed}
  423. template bindConcreteTypeToUserTypeClass*(tc, concrete: PType) =
  424. tc.add concrete
  425. tc.flags.incl tfResolved
  426. # TODO: It would be a good idea to kill the special state of a resolved
  427. # concept by switching to tyAlias within the instantiated procs.
  428. # Currently, tyAlias is always skipped with lastSon, which means that
  429. # we can store information about the matched concept in another position.
  430. # Then builtInFieldAccess can be modified to properly read the derived
  431. # consts and types stored within the concept.
  432. template isResolvedUserTypeClass*(t: PType): bool =
  433. tfResolved in t.flags
  434. proc addTypeFlags(name: var string, typ: PType) {.inline.} =
  435. if tfNotNil in typ.flags: name.add(" not nil")
  436. proc typeToString(typ: PType, prefer: TPreferedDesc = preferName): string =
  437. let preferToplevel = prefer
  438. proc getPrefer(prefer: TPreferedDesc): TPreferedDesc =
  439. if preferToplevel in {preferResolved, preferMixed}:
  440. preferToplevel # sticky option
  441. else:
  442. prefer
  443. proc typeToString(typ: PType, prefer: TPreferedDesc = preferName): string =
  444. result = ""
  445. let prefer = getPrefer(prefer)
  446. let t = typ
  447. if t == nil: return
  448. if prefer in preferToResolveSymbols and t.sym != nil and
  449. sfAnon notin t.sym.flags and t.kind != tySequence:
  450. if t.kind == tyInt and isIntLit(t):
  451. result = t.sym.name.s & " literal(" & $t.n.intVal & ")"
  452. elif t.kind == tyAlias and t[0].kind != tyAlias:
  453. result = typeToString(t[0])
  454. elif prefer in {preferResolved, preferMixed}:
  455. case t.kind
  456. of IntegralTypes + {tyFloat..tyFloat128} + {tyString, tyCstring}:
  457. result = typeToStr[t.kind]
  458. of tyGenericBody:
  459. result = typeToString(t.lastSon)
  460. of tyCompositeTypeClass:
  461. # avoids showing `A[any]` in `proc fun(a: A)` with `A = object[T]`
  462. result = typeToString(t.lastSon.lastSon)
  463. else:
  464. result = t.sym.name.s
  465. if prefer == preferMixed and result != t.sym.name.s:
  466. result = t.sym.name.s & "{" & result & "}"
  467. elif prefer in {preferName, preferTypeName} or t.sym.owner.isNil:
  468. # note: should probably be: {preferName, preferTypeName, preferGenericArg}
  469. result = t.sym.name.s
  470. if t.kind == tyGenericParam and t.len > 0:
  471. result.add ": "
  472. var first = true
  473. for son in t.sons:
  474. if not first: result.add " or "
  475. result.add son.typeToString
  476. first = false
  477. else:
  478. result = t.sym.owner.name.s & '.' & t.sym.name.s
  479. result.addTypeFlags(t)
  480. return
  481. case t.kind
  482. of tyInt:
  483. if not isIntLit(t) or prefer == preferExported:
  484. result = typeToStr[t.kind]
  485. else:
  486. if prefer == preferGenericArg:
  487. result = $t.n.intVal
  488. else:
  489. result = "int literal(" & $t.n.intVal & ")"
  490. of tyGenericInst, tyGenericInvocation:
  491. result = typeToString(t[0]) & '['
  492. for i in 1..<t.len-ord(t.kind != tyGenericInvocation):
  493. if i > 1: result.add(", ")
  494. result.add(typeToString(t[i], preferGenericArg))
  495. result.add(']')
  496. of tyGenericBody:
  497. result = typeToString(t.lastSon) & '['
  498. for i in 0..<t.len-1:
  499. if i > 0: result.add(", ")
  500. result.add(typeToString(t[i], preferTypeName))
  501. result.add(']')
  502. of tyTypeDesc:
  503. if t[0].kind == tyNone: result = "typedesc"
  504. else: result = "typedesc[" & typeToString(t[0]) & "]"
  505. of tyStatic:
  506. if prefer == preferGenericArg and t.n != nil:
  507. result = t.n.renderTree
  508. else:
  509. result = "static[" & (if t.len > 0: typeToString(t[0]) else: "") & "]"
  510. if t.n != nil: result.add "(" & renderTree(t.n) & ")"
  511. of tyUserTypeClass:
  512. if t.sym != nil and t.sym.owner != nil:
  513. if t.isResolvedUserTypeClass: return typeToString(t.lastSon)
  514. return t.sym.owner.name.s
  515. else:
  516. result = "<invalid tyUserTypeClass>"
  517. of tyBuiltInTypeClass:
  518. result = case t.base.kind
  519. of tyVar: "var"
  520. of tyRef: "ref"
  521. of tyPtr: "ptr"
  522. of tySequence: "seq"
  523. of tyArray: "array"
  524. of tySet: "set"
  525. of tyRange: "range"
  526. of tyDistinct: "distinct"
  527. of tyProc: "proc"
  528. of tyObject: "object"
  529. of tyTuple: "tuple"
  530. of tyOpenArray: "openArray"
  531. else: typeToStr[t.base.kind]
  532. of tyInferred:
  533. let concrete = t.previouslyInferred
  534. if concrete != nil: result = typeToString(concrete)
  535. else: result = "inferred[" & typeToString(t.base) & "]"
  536. of tyUserTypeClassInst:
  537. let body = t.base
  538. result = body.sym.name.s & "["
  539. for i in 1..<t.len - 1:
  540. if i > 1: result.add(", ")
  541. result.add(typeToString(t[i]))
  542. result.add "]"
  543. of tyAnd:
  544. for i, son in t.sons:
  545. result.add(typeToString(son))
  546. if i < t.sons.high:
  547. result.add(" and ")
  548. of tyOr:
  549. for i, son in t.sons:
  550. result.add(typeToString(son))
  551. if i < t.sons.high:
  552. result.add(" or ")
  553. of tyNot:
  554. result = "not " & typeToString(t[0])
  555. of tyUntyped:
  556. #internalAssert t.len == 0
  557. result = "untyped"
  558. of tyFromExpr:
  559. if t.n == nil:
  560. result = "unknown"
  561. else:
  562. result = "typeof(" & renderTree(t.n) & ")"
  563. of tyArray:
  564. result = "array"
  565. if t.len > 0:
  566. if t[0].kind == tyRange:
  567. result &= "[" & rangeToStr(t[0].n) & ", " &
  568. typeToString(t[1]) & ']'
  569. else:
  570. result &= "[" & typeToString(t[0]) & ", " &
  571. typeToString(t[1]) & ']'
  572. of tyUncheckedArray:
  573. result = "UncheckedArray"
  574. if t.len > 0:
  575. result &= "[" & typeToString(t[0]) & ']'
  576. of tySequence:
  577. if t.sym != nil and prefer != preferResolved:
  578. result = t.sym.name.s
  579. else:
  580. result = "seq"
  581. if t.len > 0:
  582. result &= "[" & typeToString(t[0]) & ']'
  583. of tyOrdinal:
  584. result = "ordinal"
  585. if t.len > 0:
  586. result &= "[" & typeToString(t[0]) & ']'
  587. of tySet:
  588. result = "set"
  589. if t.len > 0:
  590. result &= "[" & typeToString(t[0]) & ']'
  591. of tyOpenArray:
  592. result = "openArray"
  593. if t.len > 0:
  594. result &= "[" & typeToString(t[0]) & ']'
  595. of tyDistinct:
  596. result = "distinct " & typeToString(t[0],
  597. if prefer == preferModuleInfo: preferModuleInfo else: preferTypeName)
  598. of tyIterable:
  599. # xxx factor this pattern
  600. result = "iterable"
  601. if t.len > 0:
  602. result &= "[" & typeToString(t[0]) & ']'
  603. of tyTuple:
  604. # we iterate over t.sons here, because t.n may be nil
  605. if t.n != nil:
  606. result = "tuple["
  607. assert(t.n.len == t.len)
  608. for i in 0..<t.n.len:
  609. assert(t.n[i].kind == nkSym)
  610. result.add(t.n[i].sym.name.s & ": " & typeToString(t[i]))
  611. if i < t.n.len - 1: result.add(", ")
  612. result.add(']')
  613. elif t.len == 0:
  614. result = "tuple[]"
  615. else:
  616. result = "("
  617. for i in 0..<t.len:
  618. result.add(typeToString(t[i]))
  619. if i < t.len - 1: result.add(", ")
  620. elif t.len == 1: result.add(",")
  621. result.add(')')
  622. of tyPtr, tyRef, tyVar, tyLent:
  623. result = if isOutParam(t): "out " else: typeToStr[t.kind]
  624. if t.len >= 2:
  625. setLen(result, result.len-1)
  626. result.add '['
  627. for i in 0..<t.len:
  628. result.add(typeToString(t[i]))
  629. if i < t.len - 1: result.add(", ")
  630. result.add ']'
  631. else:
  632. result.add typeToString(t[0])
  633. of tyRange:
  634. result = "range "
  635. if t.n != nil and t.n.kind == nkRange:
  636. result.add rangeToStr(t.n)
  637. if prefer != preferExported:
  638. result.add("(" & typeToString(t[0]) & ")")
  639. of tyProc:
  640. result = if tfIterator in t.flags: "iterator "
  641. elif t.owner != nil:
  642. case t.owner.kind
  643. of skTemplate: "template "
  644. of skMacro: "macro "
  645. of skConverter: "converter "
  646. else: "proc "
  647. else:
  648. "proc "
  649. if tfUnresolved in t.flags: result.add "[*missing parameters*]"
  650. result.add "("
  651. for i in 1..<t.len:
  652. if t.n != nil and i < t.n.len and t.n[i].kind == nkSym:
  653. result.add(t.n[i].sym.name.s)
  654. result.add(": ")
  655. result.add(typeToString(t[i]))
  656. if i < t.len - 1: result.add(", ")
  657. result.add(')')
  658. if t.len > 0 and t[0] != nil: result.add(": " & typeToString(t[0]))
  659. var prag = if t.callConv == ccNimCall and tfExplicitCallConv notin t.flags: "" else: $t.callConv
  660. if tfNoSideEffect in t.flags:
  661. addSep(prag)
  662. prag.add("noSideEffect")
  663. if tfThread in t.flags:
  664. addSep(prag)
  665. prag.add("gcsafe")
  666. if t.lockLevel.ord != UnspecifiedLockLevel.ord:
  667. addSep(prag)
  668. prag.add("locks: " & $t.lockLevel)
  669. if prag.len != 0: result.add("{." & prag & ".}")
  670. of tyVarargs:
  671. result = typeToStr[t.kind] % typeToString(t[0])
  672. of tySink:
  673. result = "sink " & typeToString(t[0])
  674. of tyOwned:
  675. result = "owned " & typeToString(t[0])
  676. else:
  677. result = typeToStr[t.kind]
  678. result.addTypeFlags(t)
  679. result = typeToString(typ, prefer)
  680. proc firstOrd*(conf: ConfigRef; t: PType): Int128 =
  681. case t.kind
  682. of tyBool, tyChar, tySequence, tyOpenArray, tyString, tyVarargs, tyProxy:
  683. result = Zero
  684. of tySet, tyVar: result = firstOrd(conf, t[0])
  685. of tyArray: result = firstOrd(conf, t[0])
  686. of tyRange:
  687. assert(t.n != nil) # range directly given:
  688. assert(t.n.kind == nkRange)
  689. result = getOrdValue(t.n[0])
  690. of tyInt:
  691. if conf != nil and conf.target.intSize == 4:
  692. result = toInt128(-2147483648)
  693. else:
  694. result = toInt128(0x8000000000000000'i64)
  695. of tyInt8: result = toInt128(-128)
  696. of tyInt16: result = toInt128(-32768)
  697. of tyInt32: result = toInt128(-2147483648)
  698. of tyInt64: result = toInt128(0x8000000000000000'i64)
  699. of tyUInt..tyUInt64: result = Zero
  700. of tyEnum:
  701. # if basetype <> nil then return firstOrd of basetype
  702. if t.len > 0 and t[0] != nil:
  703. result = firstOrd(conf, t[0])
  704. else:
  705. if t.n.len > 0:
  706. assert(t.n[0].kind == nkSym)
  707. result = toInt128(t.n[0].sym.position)
  708. of tyGenericInst, tyDistinct, tyTypeDesc, tyAlias, tySink,
  709. tyStatic, tyInferred, tyUserTypeClasses, tyLent:
  710. result = firstOrd(conf, lastSon(t))
  711. of tyOrdinal:
  712. if t.len > 0: result = firstOrd(conf, lastSon(t))
  713. else: internalError(conf, "invalid kind for firstOrd(" & $t.kind & ')')
  714. of tyUncheckedArray, tyCstring:
  715. result = Zero
  716. else:
  717. internalError(conf, "invalid kind for firstOrd(" & $t.kind & ')')
  718. result = Zero
  719. proc firstFloat*(t: PType): BiggestFloat =
  720. case t.kind
  721. of tyFloat..tyFloat128: -Inf
  722. of tyRange:
  723. assert(t.n != nil) # range directly given:
  724. assert(t.n.kind == nkRange)
  725. getFloatValue(t.n[0])
  726. of tyVar: firstFloat(t[0])
  727. of tyGenericInst, tyDistinct, tyTypeDesc, tyAlias, tySink,
  728. tyStatic, tyInferred, tyUserTypeClasses:
  729. firstFloat(lastSon(t))
  730. else:
  731. internalError(newPartialConfigRef(), "invalid kind for firstFloat(" & $t.kind & ')')
  732. NaN
  733. proc lastOrd*(conf: ConfigRef; t: PType): Int128 =
  734. case t.kind
  735. of tyBool: result = toInt128(1'u)
  736. of tyChar: result = toInt128(255'u)
  737. of tySet, tyVar: result = lastOrd(conf, t[0])
  738. of tyArray: result = lastOrd(conf, t[0])
  739. of tyRange:
  740. assert(t.n != nil) # range directly given:
  741. assert(t.n.kind == nkRange)
  742. result = getOrdValue(t.n[1])
  743. of tyInt:
  744. if conf != nil and conf.target.intSize == 4: result = toInt128(0x7FFFFFFF)
  745. else: result = toInt128(0x7FFFFFFFFFFFFFFF'u64)
  746. of tyInt8: result = toInt128(0x0000007F)
  747. of tyInt16: result = toInt128(0x00007FFF)
  748. of tyInt32: result = toInt128(0x7FFFFFFF)
  749. of tyInt64: result = toInt128(0x7FFFFFFFFFFFFFFF'u64)
  750. of tyUInt:
  751. if conf != nil and conf.target.intSize == 4:
  752. result = toInt128(0xFFFFFFFF)
  753. else:
  754. result = toInt128(0xFFFFFFFFFFFFFFFF'u64)
  755. of tyUInt8: result = toInt128(0xFF)
  756. of tyUInt16: result = toInt128(0xFFFF)
  757. of tyUInt32: result = toInt128(0xFFFFFFFF)
  758. of tyUInt64:
  759. result = toInt128(0xFFFFFFFFFFFFFFFF'u64)
  760. of tyEnum:
  761. if t.n.len > 0:
  762. assert(t.n[^1].kind == nkSym)
  763. result = toInt128(t.n[^1].sym.position)
  764. of tyGenericInst, tyDistinct, tyTypeDesc, tyAlias, tySink,
  765. tyStatic, tyInferred, tyUserTypeClasses, tyLent:
  766. result = lastOrd(conf, lastSon(t))
  767. of tyProxy: result = Zero
  768. of tyOrdinal:
  769. if t.len > 0: result = lastOrd(conf, lastSon(t))
  770. else: internalError(conf, "invalid kind for lastOrd(" & $t.kind & ')')
  771. of tyUncheckedArray:
  772. result = Zero
  773. else:
  774. internalError(conf, "invalid kind for lastOrd(" & $t.kind & ')')
  775. result = Zero
  776. proc lastFloat*(t: PType): BiggestFloat =
  777. case t.kind
  778. of tyFloat..tyFloat128: Inf
  779. of tyVar: lastFloat(t[0])
  780. of tyRange:
  781. assert(t.n != nil) # range directly given:
  782. assert(t.n.kind == nkRange)
  783. getFloatValue(t.n[1])
  784. of tyGenericInst, tyDistinct, tyTypeDesc, tyAlias, tySink,
  785. tyStatic, tyInferred, tyUserTypeClasses:
  786. lastFloat(lastSon(t))
  787. else:
  788. internalError(newPartialConfigRef(), "invalid kind for lastFloat(" & $t.kind & ')')
  789. NaN
  790. proc floatRangeCheck*(x: BiggestFloat, t: PType): bool =
  791. case t.kind
  792. # This needs to be special cased since NaN is never
  793. # part of firstFloat(t)..lastFloat(t)
  794. of tyFloat..tyFloat128:
  795. true
  796. of tyRange:
  797. x in firstFloat(t)..lastFloat(t)
  798. of tyVar:
  799. floatRangeCheck(x, t[0])
  800. of tyGenericInst, tyDistinct, tyTypeDesc, tyAlias, tySink,
  801. tyStatic, tyInferred, tyUserTypeClasses:
  802. floatRangeCheck(x, lastSon(t))
  803. else:
  804. internalError(newPartialConfigRef(), "invalid kind for floatRangeCheck:" & $t.kind)
  805. false
  806. proc lengthOrd*(conf: ConfigRef; t: PType): Int128 =
  807. if t.skipTypes(tyUserTypeClasses).kind == tyDistinct:
  808. result = lengthOrd(conf, t[0])
  809. else:
  810. let last = lastOrd(conf, t)
  811. let first = firstOrd(conf, t)
  812. result = last - first + One
  813. # -------------- type equality -----------------------------------------------
  814. type
  815. TDistinctCompare* = enum ## how distinct types are to be compared
  816. dcEq, ## a and b should be the same type
  817. dcEqIgnoreDistinct, ## compare symmetrically: (distinct a) == b, a == b
  818. ## or a == (distinct b)
  819. dcEqOrDistinctOf ## a equals b or a is distinct of b
  820. TTypeCmpFlag* = enum
  821. IgnoreTupleFields ## NOTE: Only set this flag for backends!
  822. IgnoreCC
  823. ExactTypeDescValues
  824. ExactGenericParams
  825. ExactConstraints
  826. ExactGcSafety
  827. AllowCommonBase
  828. PickyCAliases # be picky about the distinction between 'cint' and 'int32'
  829. TTypeCmpFlags* = set[TTypeCmpFlag]
  830. TSameTypeClosure = object
  831. cmp: TDistinctCompare
  832. recCheck: int
  833. flags: TTypeCmpFlags
  834. s: seq[tuple[a,b: int]] # seq for a set as it's hopefully faster
  835. # (few elements expected)
  836. proc initSameTypeClosure: TSameTypeClosure =
  837. # we do the initialization lazily for performance (avoids memory allocations)
  838. discard
  839. proc containsOrIncl(c: var TSameTypeClosure, a, b: PType): bool =
  840. result = c.s.len > 0 and c.s.contains((a.id, b.id))
  841. if not result:
  842. c.s.add((a.id, b.id))
  843. proc sameTypeAux(x, y: PType, c: var TSameTypeClosure): bool
  844. proc sameTypeOrNilAux(a, b: PType, c: var TSameTypeClosure): bool =
  845. if a == b:
  846. result = true
  847. else:
  848. if a == nil or b == nil: result = false
  849. else: result = sameTypeAux(a, b, c)
  850. proc sameType*(a, b: PType, flags: TTypeCmpFlags = {}): bool =
  851. var c = initSameTypeClosure()
  852. c.flags = flags
  853. result = sameTypeAux(a, b, c)
  854. proc sameTypeOrNil*(a, b: PType, flags: TTypeCmpFlags = {}): bool =
  855. if a == b:
  856. result = true
  857. else:
  858. if a == nil or b == nil: result = false
  859. else: result = sameType(a, b, flags)
  860. proc equalParam(a, b: PSym): TParamsEquality =
  861. if sameTypeOrNil(a.typ, b.typ, {ExactTypeDescValues}) and
  862. exprStructuralEquivalent(a.constraint, b.constraint):
  863. if a.ast == b.ast:
  864. result = paramsEqual
  865. elif a.ast != nil and b.ast != nil:
  866. if exprStructuralEquivalent(a.ast, b.ast): result = paramsEqual
  867. else: result = paramsIncompatible
  868. elif a.ast != nil:
  869. result = paramsEqual
  870. elif b.ast != nil:
  871. result = paramsIncompatible
  872. else:
  873. result = paramsNotEqual
  874. proc sameConstraints(a, b: PNode): bool =
  875. if isNil(a) and isNil(b): return true
  876. if a.len != b.len: return false
  877. for i in 1..<a.len:
  878. if not exprStructuralEquivalent(a[i].sym.constraint,
  879. b[i].sym.constraint):
  880. return false
  881. return true
  882. proc equalParams(a, b: PNode): TParamsEquality =
  883. result = paramsEqual
  884. if a.len != b.len:
  885. result = paramsNotEqual
  886. else:
  887. for i in 1..<a.len:
  888. var m = a[i].sym
  889. var n = b[i].sym
  890. assert((m.kind == skParam) and (n.kind == skParam))
  891. case equalParam(m, n)
  892. of paramsNotEqual:
  893. return paramsNotEqual
  894. of paramsEqual:
  895. discard
  896. of paramsIncompatible:
  897. result = paramsIncompatible
  898. if m.name.id != n.name.id:
  899. # BUGFIX
  900. return paramsNotEqual # paramsIncompatible;
  901. # continue traversal! If not equal, we can return immediately; else
  902. # it stays incompatible
  903. if not sameTypeOrNil(a.typ, b.typ, {ExactTypeDescValues}):
  904. if (a.typ == nil) or (b.typ == nil):
  905. result = paramsNotEqual # one proc has a result, the other not is OK
  906. else:
  907. result = paramsIncompatible # overloading by different
  908. # result types does not work
  909. proc sameTuple(a, b: PType, c: var TSameTypeClosure): bool =
  910. # two tuples are equivalent iff the names, types and positions are the same;
  911. # however, both types may not have any field names (t.n may be nil) which
  912. # complicates the matter a bit.
  913. if a.len == b.len:
  914. result = true
  915. for i in 0..<a.len:
  916. var x = a[i]
  917. var y = b[i]
  918. if IgnoreTupleFields in c.flags:
  919. x = skipTypes(x, {tyRange, tyGenericInst, tyAlias})
  920. y = skipTypes(y, {tyRange, tyGenericInst, tyAlias})
  921. result = sameTypeAux(x, y, c)
  922. if not result: return
  923. if a.n != nil and b.n != nil and IgnoreTupleFields notin c.flags:
  924. for i in 0..<a.n.len:
  925. # check field names:
  926. if a.n[i].kind == nkSym and b.n[i].kind == nkSym:
  927. var x = a.n[i].sym
  928. var y = b.n[i].sym
  929. result = x.name.id == y.name.id
  930. if not result: break
  931. else:
  932. return false
  933. elif a.n != b.n and (a.n == nil or b.n == nil) and IgnoreTupleFields notin c.flags:
  934. result = false
  935. template ifFastObjectTypeCheckFailed(a, b: PType, body: untyped) =
  936. if tfFromGeneric notin a.flags + b.flags:
  937. # fast case: id comparison suffices:
  938. result = a.id == b.id
  939. else:
  940. # expensive structural equality test; however due to the way generic and
  941. # objects work, if one of the types does **not** contain tfFromGeneric,
  942. # they cannot be equal. The check ``a.sym.id == b.sym.id`` checks
  943. # for the same origin and is essential because we don't want "pure"
  944. # structural type equivalence:
  945. #
  946. # type
  947. # TA[T] = object
  948. # TB[T] = object
  949. # --> TA[int] != TB[int]
  950. if tfFromGeneric in a.flags * b.flags and a.sym.id == b.sym.id:
  951. # ok, we need the expensive structural check
  952. body
  953. proc sameObjectTypes*(a, b: PType): bool =
  954. # specialized for efficiency (sigmatch uses it)
  955. ifFastObjectTypeCheckFailed(a, b):
  956. var c = initSameTypeClosure()
  957. result = sameTypeAux(a, b, c)
  958. proc sameDistinctTypes*(a, b: PType): bool {.inline.} =
  959. result = sameObjectTypes(a, b)
  960. proc sameEnumTypes*(a, b: PType): bool {.inline.} =
  961. result = a.id == b.id
  962. proc sameObjectTree(a, b: PNode, c: var TSameTypeClosure): bool =
  963. if a == b:
  964. result = true
  965. elif a != nil and b != nil and a.kind == b.kind:
  966. var x = a.typ
  967. var y = b.typ
  968. if IgnoreTupleFields in c.flags:
  969. if x != nil: x = skipTypes(x, {tyRange, tyGenericInst, tyAlias})
  970. if y != nil: y = skipTypes(y, {tyRange, tyGenericInst, tyAlias})
  971. if sameTypeOrNilAux(x, y, c):
  972. case a.kind
  973. of nkSym:
  974. # same symbol as string is enough:
  975. result = a.sym.name.id == b.sym.name.id
  976. of nkIdent: result = a.ident.id == b.ident.id
  977. of nkCharLit..nkInt64Lit: result = a.intVal == b.intVal
  978. of nkFloatLit..nkFloat64Lit: result = a.floatVal == b.floatVal
  979. of nkStrLit..nkTripleStrLit: result = a.strVal == b.strVal
  980. of nkEmpty, nkNilLit, nkType: result = true
  981. else:
  982. if a.len == b.len:
  983. for i in 0..<a.len:
  984. if not sameObjectTree(a[i], b[i], c): return
  985. result = true
  986. proc sameObjectStructures(a, b: PType, c: var TSameTypeClosure): bool =
  987. # check base types:
  988. if a.len != b.len: return
  989. for i in 0..<a.len:
  990. if not sameTypeOrNilAux(a[i], b[i], c): return
  991. if not sameObjectTree(a.n, b.n, c): return
  992. result = true
  993. proc sameChildrenAux(a, b: PType, c: var TSameTypeClosure): bool =
  994. if a.len != b.len: return false
  995. result = true
  996. for i in 0..<a.len:
  997. result = sameTypeOrNilAux(a[i], b[i], c)
  998. if not result: return
  999. proc isGenericAlias*(t: PType): bool =
  1000. return t.kind == tyGenericInst and t.lastSon.kind == tyGenericInst
  1001. proc skipGenericAlias*(t: PType): PType =
  1002. return if t.isGenericAlias: t.lastSon else: t
  1003. proc sameFlags*(a, b: PType): bool {.inline.} =
  1004. result = eqTypeFlags*a.flags == eqTypeFlags*b.flags
  1005. proc sameTypeAux(x, y: PType, c: var TSameTypeClosure): bool =
  1006. template cycleCheck() =
  1007. # believe it or not, the direct check for ``containsOrIncl(c, a, b)``
  1008. # increases bootstrapping time from 2.4s to 3.3s on my laptop! So we cheat
  1009. # again: Since the recursion check is only to not get caught in an endless
  1010. # recursion, we use a counter and only if it's value is over some
  1011. # threshold we perform the expensive exact cycle check:
  1012. if c.recCheck < 3:
  1013. inc c.recCheck
  1014. else:
  1015. if containsOrIncl(c, a, b): return true
  1016. if x == y: return true
  1017. var a = skipTypes(x, {tyGenericInst, tyAlias})
  1018. while a.kind == tyUserTypeClass and tfResolved in a.flags:
  1019. a = skipTypes(a[^1], {tyGenericInst, tyAlias})
  1020. var b = skipTypes(y, {tyGenericInst, tyAlias})
  1021. while b.kind == tyUserTypeClass and tfResolved in b.flags:
  1022. b = skipTypes(b[^1], {tyGenericInst, tyAlias})
  1023. assert(a != nil)
  1024. assert(b != nil)
  1025. if a.kind != b.kind:
  1026. case c.cmp
  1027. of dcEq: return false
  1028. of dcEqIgnoreDistinct:
  1029. a = a.skipTypes({tyDistinct, tyGenericInst})
  1030. b = b.skipTypes({tyDistinct, tyGenericInst})
  1031. if a.kind != b.kind: return false
  1032. of dcEqOrDistinctOf:
  1033. a = a.skipTypes({tyDistinct, tyGenericInst})
  1034. if a.kind != b.kind: return false
  1035. #[
  1036. The following code should not run in the case either side is an generic alias,
  1037. but it's not presently possible to distinguish the genericinsts from aliases of
  1038. objects ie `type A[T] = SomeObject`
  1039. ]#
  1040. # this is required by tunique_type but makes no sense really:
  1041. if tyDistinct notin {x.kind, y.kind} and x.kind == tyGenericInst and IgnoreTupleFields notin c.flags:
  1042. let
  1043. lhs = x.skipGenericAlias
  1044. rhs = y.skipGenericAlias
  1045. if rhs.kind != tyGenericInst or lhs.base != rhs.base:
  1046. return false
  1047. for i in 1..<lhs.len - 1:
  1048. let ff = rhs[i]
  1049. let aa = lhs[i]
  1050. if not sameTypeAux(ff, aa, c): return false
  1051. return true
  1052. case a.kind
  1053. of tyEmpty, tyChar, tyBool, tyNil, tyPointer, tyString, tyCstring,
  1054. tyInt..tyUInt64, tyTyped, tyUntyped, tyVoid:
  1055. result = sameFlags(a, b)
  1056. if result and PickyCAliases in c.flags:
  1057. # additional requirement for the caching of generics for importc'ed types:
  1058. # the symbols must be identical too:
  1059. let symFlagsA = if a.sym != nil: a.sym.flags else: {}
  1060. let symFlagsB = if b.sym != nil: b.sym.flags else: {}
  1061. if (symFlagsA+symFlagsB) * {sfImportc, sfExportc} != {}:
  1062. result = symFlagsA == symFlagsB
  1063. of tyStatic, tyFromExpr:
  1064. result = exprStructuralEquivalent(a.n, b.n) and sameFlags(a, b)
  1065. if result and a.len == b.len and a.len == 1:
  1066. cycleCheck()
  1067. result = sameTypeAux(a[0], b[0], c)
  1068. of tyObject:
  1069. ifFastObjectTypeCheckFailed(a, b):
  1070. cycleCheck()
  1071. result = sameObjectStructures(a, b, c) and sameFlags(a, b)
  1072. of tyDistinct:
  1073. cycleCheck()
  1074. if c.cmp == dcEq:
  1075. if sameFlags(a, b):
  1076. ifFastObjectTypeCheckFailed(a, b):
  1077. result = sameTypeAux(a[0], b[0], c)
  1078. else:
  1079. result = sameTypeAux(a[0], b[0], c) and sameFlags(a, b)
  1080. of tyEnum, tyForward:
  1081. # XXX generic enums do not make much sense, but require structural checking
  1082. result = a.id == b.id and sameFlags(a, b)
  1083. of tyError:
  1084. result = b.kind == tyError
  1085. of tyTuple:
  1086. cycleCheck()
  1087. result = sameTuple(a, b, c) and sameFlags(a, b)
  1088. of tyTypeDesc:
  1089. if c.cmp == dcEqIgnoreDistinct: result = false
  1090. elif ExactTypeDescValues in c.flags:
  1091. cycleCheck()
  1092. result = sameChildrenAux(x, y, c) and sameFlags(a, b)
  1093. else:
  1094. result = sameFlags(a, b)
  1095. of tyGenericParam:
  1096. result = sameChildrenAux(a, b, c) and sameFlags(a, b)
  1097. if result and {ExactGenericParams, ExactTypeDescValues} * c.flags != {}:
  1098. result = a.sym.position == b.sym.position
  1099. of tyBuiltInTypeClass:
  1100. assert a.len == 1
  1101. assert a[0].len == 0
  1102. assert b.len == 1
  1103. assert b[0].len == 0
  1104. result = a[0].kind == b[0].kind
  1105. of tyGenericInvocation, tyGenericBody, tySequence, tyOpenArray, tySet, tyRef,
  1106. tyPtr, tyVar, tyLent, tySink, tyUncheckedArray, tyArray, tyProc, tyVarargs,
  1107. tyOrdinal, tyCompositeTypeClass, tyUserTypeClass, tyUserTypeClassInst,
  1108. tyAnd, tyOr, tyNot, tyAnything, tyOwned:
  1109. cycleCheck()
  1110. if a.kind == tyUserTypeClass and a.n != nil: return a.n == b.n
  1111. result = sameChildrenAux(a, b, c)
  1112. if result:
  1113. if IgnoreTupleFields in c.flags:
  1114. result = a.flags * {tfVarIsPtr, tfIsOutParam} == b.flags * {tfVarIsPtr, tfIsOutParam}
  1115. else:
  1116. result = sameFlags(a, b)
  1117. if result and ExactGcSafety in c.flags:
  1118. result = a.flags * {tfThread} == b.flags * {tfThread}
  1119. if result and a.kind == tyProc:
  1120. result = ((IgnoreCC in c.flags) or a.callConv == b.callConv) and
  1121. ((ExactConstraints notin c.flags) or sameConstraints(a.n, b.n))
  1122. of tyRange:
  1123. cycleCheck()
  1124. result = sameTypeOrNilAux(a[0], b[0], c) and
  1125. sameValue(a.n[0], b.n[0]) and
  1126. sameValue(a.n[1], b.n[1])
  1127. of tyGenericInst, tyAlias, tyInferred, tyIterable:
  1128. cycleCheck()
  1129. result = sameTypeAux(a.lastSon, b.lastSon, c)
  1130. of tyNone: result = false
  1131. of tyConcept:
  1132. result = exprStructuralEquivalent(a.n, b.n)
  1133. proc sameBackendType*(x, y: PType): bool =
  1134. var c = initSameTypeClosure()
  1135. c.flags.incl IgnoreTupleFields
  1136. c.cmp = dcEqIgnoreDistinct
  1137. result = sameTypeAux(x, y, c)
  1138. proc compareTypes*(x, y: PType,
  1139. cmp: TDistinctCompare = dcEq,
  1140. flags: TTypeCmpFlags = {}): bool =
  1141. ## compares two type for equality (modulo type distinction)
  1142. var c = initSameTypeClosure()
  1143. c.cmp = cmp
  1144. c.flags = flags
  1145. if x == y: result = true
  1146. elif x.isNil or y.isNil: result = false
  1147. else: result = sameTypeAux(x, y, c)
  1148. proc inheritanceDiff*(a, b: PType): int =
  1149. # | returns: 0 iff `a` == `b`
  1150. # | returns: -x iff `a` is the x'th direct superclass of `b`
  1151. # | returns: +x iff `a` is the x'th direct subclass of `b`
  1152. # | returns: `maxint` iff `a` and `b` are not compatible at all
  1153. if a == b or a.kind == tyError or b.kind == tyError: return 0
  1154. assert a.kind in {tyObject} + skipPtrs
  1155. assert b.kind in {tyObject} + skipPtrs
  1156. var x = a
  1157. result = 0
  1158. while x != nil:
  1159. x = skipTypes(x, skipPtrs)
  1160. if sameObjectTypes(x, b): return
  1161. x = x[0]
  1162. dec(result)
  1163. var y = b
  1164. result = 0
  1165. while y != nil:
  1166. y = skipTypes(y, skipPtrs)
  1167. if sameObjectTypes(y, a): return
  1168. y = y[0]
  1169. inc(result)
  1170. result = high(int)
  1171. proc commonSuperclass*(a, b: PType): PType =
  1172. # quick check: are they the same?
  1173. if sameObjectTypes(a, b): return a
  1174. # simple algorithm: we store all ancestors of 'a' in a ID-set and walk 'b'
  1175. # up until the ID is found:
  1176. assert a.kind == tyObject
  1177. assert b.kind == tyObject
  1178. var x = a
  1179. var ancestors = initIntSet()
  1180. while x != nil:
  1181. x = skipTypes(x, skipPtrs)
  1182. ancestors.incl(x.id)
  1183. x = x[0]
  1184. var y = b
  1185. while y != nil:
  1186. var t = y # bug #7818, save type before skip
  1187. y = skipTypes(y, skipPtrs)
  1188. if ancestors.contains(y.id):
  1189. # bug #7818, defer the previous skipTypes
  1190. if t.kind != tyGenericInst: t = y
  1191. return t
  1192. y = y[0]
  1193. proc matchType*(a: PType, pattern: openArray[tuple[k:TTypeKind, i:int]],
  1194. last: TTypeKind): bool =
  1195. var a = a
  1196. for k, i in pattern.items:
  1197. if a.kind != k: return false
  1198. if i >= a.len or a[i] == nil: return false
  1199. a = a[i]
  1200. result = a.kind == last
  1201. include sizealignoffsetimpl
  1202. proc computeSize*(conf: ConfigRef; typ: PType): BiggestInt =
  1203. computeSizeAlign(conf, typ)
  1204. result = typ.size
  1205. proc getReturnType*(s: PSym): PType =
  1206. # Obtains the return type of a iterator/proc/macro/template
  1207. assert s.kind in skProcKinds
  1208. result = s.typ[0]
  1209. proc getAlign*(conf: ConfigRef; typ: PType): BiggestInt =
  1210. computeSizeAlign(conf, typ)
  1211. result = typ.align
  1212. proc getSize*(conf: ConfigRef; typ: PType): BiggestInt =
  1213. computeSizeAlign(conf, typ)
  1214. result = typ.size
  1215. proc containsGenericTypeIter(t: PType, closure: RootRef): bool =
  1216. case t.kind
  1217. of tyStatic:
  1218. return t.n == nil
  1219. of tyTypeDesc:
  1220. if t.base.kind == tyNone: return true
  1221. if containsGenericTypeIter(t.base, closure): return true
  1222. return false
  1223. of GenericTypes + tyTypeClasses + {tyFromExpr}:
  1224. return true
  1225. else:
  1226. return false
  1227. proc containsGenericType*(t: PType): bool =
  1228. result = iterOverType(t, containsGenericTypeIter, nil)
  1229. proc baseOfDistinct*(t: PType; g: ModuleGraph; idgen: IdGenerator): PType =
  1230. if t.kind == tyDistinct:
  1231. result = t[0]
  1232. else:
  1233. result = copyType(t, nextTypeId idgen, t.owner)
  1234. copyTypeProps(g, idgen.module, result, t)
  1235. var parent: PType = nil
  1236. var it = result
  1237. while it.kind in {tyPtr, tyRef, tyOwned}:
  1238. parent = it
  1239. it = it.lastSon
  1240. if it.kind == tyDistinct and parent != nil:
  1241. parent[0] = it[0]
  1242. proc safeInheritanceDiff*(a, b: PType): int =
  1243. # same as inheritanceDiff but checks for tyError:
  1244. if a.kind == tyError or b.kind == tyError:
  1245. result = -1
  1246. else:
  1247. result = inheritanceDiff(a.skipTypes(skipPtrs), b.skipTypes(skipPtrs))
  1248. proc compatibleEffectsAux(se, re: PNode): bool =
  1249. if re.isNil: return false
  1250. for r in items(re):
  1251. block search:
  1252. for s in items(se):
  1253. if safeInheritanceDiff(r.typ, s.typ) <= 0:
  1254. break search
  1255. return false
  1256. result = true
  1257. proc hasIncompatibleEffect(se, re: PNode): bool =
  1258. if re.isNil: return false
  1259. for r in items(re):
  1260. for s in items(se):
  1261. if safeInheritanceDiff(r.typ, s.typ) != high(int):
  1262. return true
  1263. type
  1264. EffectsCompat* = enum
  1265. efCompat
  1266. efRaisesDiffer
  1267. efRaisesUnknown
  1268. efTagsDiffer
  1269. efTagsUnknown
  1270. efLockLevelsDiffer
  1271. efEffectsDelayed
  1272. efTagsIllegal
  1273. proc compatibleEffects*(formal, actual: PType): EffectsCompat =
  1274. # for proc type compatibility checking:
  1275. assert formal.kind == tyProc and actual.kind == tyProc
  1276. #if tfEffectSystemWorkaround in actual.flags:
  1277. # return efCompat
  1278. if formal.n[0].kind != nkEffectList or
  1279. actual.n[0].kind != nkEffectList:
  1280. return efTagsUnknown
  1281. var spec = formal.n[0]
  1282. if spec.len != 0:
  1283. var real = actual.n[0]
  1284. let se = spec[exceptionEffects]
  1285. # if 'se.kind == nkArgList' it is no formal type really, but a
  1286. # computed effect and as such no spec:
  1287. # 'r.msgHandler = if isNil(msgHandler): defaultMsgHandler else: msgHandler'
  1288. if not isNil(se) and se.kind != nkArgList:
  1289. # spec requires some exception or tag, but we don't know anything:
  1290. if real.len == 0: return efRaisesUnknown
  1291. let res = compatibleEffectsAux(se, real[exceptionEffects])
  1292. if not res: return efRaisesDiffer
  1293. let st = spec[tagEffects]
  1294. if not isNil(st) and st.kind != nkArgList:
  1295. # spec requires some exception or tag, but we don't know anything:
  1296. if real.len == 0: return efTagsUnknown
  1297. let res = compatibleEffectsAux(st, real[tagEffects])
  1298. if not res:
  1299. #if tfEffectSystemWorkaround notin actual.flags:
  1300. return efTagsDiffer
  1301. let sn = spec[forbiddenEffects]
  1302. if not isNil(sn) and sn.kind != nkArgList:
  1303. if 0 == real.len:
  1304. return efTagsUnknown
  1305. elif hasIncompatibleEffect(sn, real[tagEffects]):
  1306. return efTagsIllegal
  1307. if formal.lockLevel.ord < 0 or
  1308. actual.lockLevel.ord <= formal.lockLevel.ord:
  1309. for i in 1 ..< min(formal.n.len, actual.n.len):
  1310. if formal.n[i].sym.flags * {sfEffectsDelayed} != actual.n[i].sym.flags * {sfEffectsDelayed}:
  1311. result = efEffectsDelayed
  1312. break
  1313. result = efCompat
  1314. else:
  1315. result = efLockLevelsDiffer
  1316. proc isCompileTimeOnly*(t: PType): bool {.inline.} =
  1317. result = t.kind in {tyTypeDesc, tyStatic}
  1318. proc containsCompileTimeOnly*(t: PType): bool =
  1319. if isCompileTimeOnly(t): return true
  1320. for i in 0..<t.len:
  1321. if t[i] != nil and isCompileTimeOnly(t[i]):
  1322. return true
  1323. return false
  1324. proc safeSkipTypes*(t: PType, kinds: TTypeKinds): PType =
  1325. ## same as 'skipTypes' but with a simple cycle detector.
  1326. result = t
  1327. var seen = initIntSet()
  1328. while result.kind in kinds and not containsOrIncl(seen, result.id):
  1329. result = lastSon(result)
  1330. type
  1331. OrdinalType* = enum
  1332. NoneLike, IntLike, FloatLike
  1333. proc classify*(t: PType): OrdinalType =
  1334. ## for convenient type checking:
  1335. if t == nil:
  1336. result = NoneLike
  1337. else:
  1338. case skipTypes(t, abstractVarRange).kind
  1339. of tyFloat..tyFloat128: result = FloatLike
  1340. of tyInt..tyInt64, tyUInt..tyUInt64, tyBool, tyChar, tyEnum:
  1341. result = IntLike
  1342. else: result = NoneLike
  1343. proc skipConv*(n: PNode): PNode =
  1344. result = n
  1345. case n.kind
  1346. of nkObjUpConv, nkObjDownConv, nkChckRange, nkChckRangeF, nkChckRange64:
  1347. # only skip the conversion if it doesn't lose too important information
  1348. # (see bug #1334)
  1349. if n[0].typ.classify == n.typ.classify:
  1350. result = n[0]
  1351. of nkHiddenStdConv, nkHiddenSubConv, nkConv:
  1352. if n[1].typ.classify == n.typ.classify:
  1353. result = n[1]
  1354. else: discard
  1355. proc skipHidden*(n: PNode): PNode =
  1356. result = n
  1357. while true:
  1358. case result.kind
  1359. of nkHiddenStdConv, nkHiddenSubConv:
  1360. if result[1].typ.classify == result.typ.classify:
  1361. result = result[1]
  1362. else: break
  1363. of nkHiddenDeref, nkHiddenAddr:
  1364. result = result[0]
  1365. else: break
  1366. proc skipConvTakeType*(n: PNode): PNode =
  1367. result = n.skipConv
  1368. result.typ = n.typ
  1369. proc isEmptyContainer*(t: PType): bool =
  1370. case t.kind
  1371. of tyUntyped, tyNil: result = true
  1372. of tyArray: result = t[1].kind == tyEmpty
  1373. of tySet, tySequence, tyOpenArray, tyVarargs:
  1374. result = t[0].kind == tyEmpty
  1375. of tyGenericInst, tyAlias, tySink: result = isEmptyContainer(t.lastSon)
  1376. else: result = false
  1377. proc takeType*(formal, arg: PType; g: ModuleGraph; idgen: IdGenerator): PType =
  1378. # param: openArray[string] = []
  1379. # [] is an array constructor of length 0 of type string!
  1380. if arg.kind == tyNil:
  1381. # and not (formal.kind == tyProc and formal.callConv == ccClosure):
  1382. result = formal
  1383. elif formal.kind in {tyOpenArray, tyVarargs, tySequence} and
  1384. arg.isEmptyContainer:
  1385. let a = copyType(arg.skipTypes({tyGenericInst, tyAlias}), nextTypeId(idgen), arg.owner)
  1386. copyTypeProps(g, idgen.module, a, arg)
  1387. a[ord(arg.kind == tyArray)] = formal[0]
  1388. result = a
  1389. elif formal.kind in {tyTuple, tySet} and arg.kind == formal.kind:
  1390. result = formal
  1391. else:
  1392. result = arg
  1393. proc skipHiddenSubConv*(n: PNode; g: ModuleGraph; idgen: IdGenerator): PNode =
  1394. if n.kind == nkHiddenSubConv:
  1395. # param: openArray[string] = []
  1396. # [] is an array constructor of length 0 of type string!
  1397. let formal = n.typ
  1398. result = n[1]
  1399. let arg = result.typ
  1400. let dest = takeType(formal, arg, g, idgen)
  1401. if dest == arg and formal.kind != tyUntyped:
  1402. #echo n.info, " came here for ", formal.typeToString
  1403. result = n
  1404. else:
  1405. result = copyTree(result)
  1406. result.typ = dest
  1407. else:
  1408. result = n
  1409. proc getProcConvMismatch*(c: ConfigRef, f, a: PType, rel = isNone): (set[ProcConvMismatch], TTypeRelation) =
  1410. ## Returns a set of the reason of mismatch, and the relation for conversion.
  1411. result[1] = rel
  1412. if tfNoSideEffect in f.flags and tfNoSideEffect notin a.flags:
  1413. # Formal is pure, but actual is not
  1414. result[0].incl pcmNoSideEffect
  1415. result[1] = isNone
  1416. if tfThread in f.flags and a.flags * {tfThread, tfNoSideEffect} == {} and
  1417. optThreadAnalysis in c.globalOptions:
  1418. # noSideEffect implies ``tfThread``!
  1419. result[0].incl pcmNotGcSafe
  1420. result[1] = isNone
  1421. if f.flags * {tfIterator} != a.flags * {tfIterator}:
  1422. # One of them is an iterator so not convertible
  1423. result[0].incl pcmNotIterator
  1424. result[1] = isNone
  1425. if f.callConv != a.callConv:
  1426. # valid to pass a 'nimcall' thingie to 'closure':
  1427. if f.callConv == ccClosure and a.callConv == ccNimCall:
  1428. case result[1]
  1429. of isInferred: result[1] = isInferredConvertible
  1430. of isBothMetaConvertible: result[1] = isBothMetaConvertible
  1431. elif result[1] != isNone: result[1] = isConvertible
  1432. else: result[0].incl pcmDifferentCallConv
  1433. else:
  1434. result[1] = isNone
  1435. result[0].incl pcmDifferentCallConv
  1436. if f.lockLevel.ord != UnspecifiedLockLevel.ord and
  1437. a.lockLevel.ord != UnspecifiedLockLevel.ord:
  1438. # proctypeRel has more logic to catch this difference,
  1439. # so dont need to do `rel = isNone`
  1440. # but it's a pragma mismatch reason which is why it's here
  1441. result[0].incl pcmLockDifference
  1442. proc addPragmaAndCallConvMismatch*(message: var string, formal, actual: PType, conf: ConfigRef) =
  1443. assert formal.kind == tyProc and actual.kind == tyProc
  1444. let (convMismatch, _) = getProcConvMismatch(conf, formal, actual)
  1445. var
  1446. gotPragmas = ""
  1447. expectedPragmas = ""
  1448. for reason in convMismatch:
  1449. case reason
  1450. of pcmDifferentCallConv:
  1451. message.add "\n Calling convention mismatch: got '{.$1.}', but expected '{.$2.}'." % [$actual.callConv, $formal.callConv]
  1452. of pcmNoSideEffect:
  1453. expectedPragmas.add "noSideEffect, "
  1454. of pcmNotGcSafe:
  1455. expectedPragmas.add "gcsafe, "
  1456. of pcmLockDifference:
  1457. gotPragmas.add("locks: " & $actual.lockLevel & ", ")
  1458. expectedPragmas.add("locks: " & $formal.lockLevel & ", ")
  1459. of pcmNotIterator: discard
  1460. if expectedPragmas.len > 0:
  1461. gotPragmas.setLen(max(0, gotPragmas.len - 2)) # Remove ", "
  1462. expectedPragmas.setLen(max(0, expectedPragmas.len - 2)) # Remove ", "
  1463. message.add "\n Pragma mismatch: got '{.$1.}', but expected '{.$2.}'." % [gotPragmas, expectedPragmas]
  1464. proc processPragmaAndCallConvMismatch(msg: var string, formal, actual: PType, conf: ConfigRef) =
  1465. if formal.kind == tyProc and actual.kind == tyProc:
  1466. msg.addPragmaAndCallConvMismatch(formal, actual, conf)
  1467. case compatibleEffects(formal, actual)
  1468. of efCompat: discard
  1469. of efRaisesDiffer:
  1470. msg.add "\n.raise effects differ"
  1471. of efRaisesUnknown:
  1472. msg.add "\n.raise effect is 'can raise any'"
  1473. of efTagsDiffer:
  1474. msg.add "\n.tag effects differ"
  1475. of efTagsUnknown:
  1476. msg.add "\n.tag effect is 'any tag allowed'"
  1477. of efLockLevelsDiffer:
  1478. msg.add "\nlock levels differ"
  1479. of efEffectsDelayed:
  1480. msg.add "\n.effectsOf annotations differ"
  1481. of efTagsIllegal:
  1482. msg.add "\n.notTag catched an illegal effect"
  1483. proc typeMismatch*(conf: ConfigRef; info: TLineInfo, formal, actual: PType, n: PNode) =
  1484. if formal.kind != tyError and actual.kind != tyError:
  1485. let actualStr = typeToString(actual)
  1486. let formalStr = typeToString(formal)
  1487. let desc = typeToString(formal, preferDesc)
  1488. let x = if formalStr == desc: formalStr else: formalStr & " = " & desc
  1489. let verbose = actualStr == formalStr or optDeclaredLocs in conf.globalOptions
  1490. var msg = "type mismatch:"
  1491. if verbose: msg.add "\n"
  1492. if conf.isDefined("nimLegacyTypeMismatch"):
  1493. msg.add " got <$1>" % actualStr
  1494. else:
  1495. msg.add " got '$1' for '$2'" % [actualStr, n.renderTree]
  1496. if verbose:
  1497. msg.addDeclaredLoc(conf, actual)
  1498. msg.add "\n"
  1499. msg.add " but expected '$1'" % x
  1500. if verbose: msg.addDeclaredLoc(conf, formal)
  1501. var a = formal
  1502. var b = actual
  1503. if formal.kind == tyArray and actual.kind == tyArray:
  1504. a = formal[1]
  1505. b = actual[1]
  1506. processPragmaAndCallConvMismatch(msg, a, b, conf)
  1507. elif formal.kind == tySequence and actual.kind == tySequence:
  1508. a = formal[0]
  1509. b = actual[0]
  1510. processPragmaAndCallConvMismatch(msg, a, b, conf)
  1511. else:
  1512. processPragmaAndCallConvMismatch(msg, a, b, conf)
  1513. localError(conf, info, msg)
  1514. proc isTupleRecursive(t: PType, cycleDetector: var IntSet): bool =
  1515. if t == nil:
  1516. return false
  1517. if cycleDetector.containsOrIncl(t.id):
  1518. return true
  1519. case t.kind
  1520. of tyTuple:
  1521. var cycleDetectorCopy: IntSet
  1522. for i in 0..<t.len:
  1523. assign(cycleDetectorCopy, cycleDetector)
  1524. if isTupleRecursive(t[i], cycleDetectorCopy):
  1525. return true
  1526. of tyAlias, tyRef, tyPtr, tyGenericInst, tyVar, tyLent, tySink,
  1527. tyArray, tyUncheckedArray, tySequence, tyDistinct:
  1528. return isTupleRecursive(t.lastSon, cycleDetector)
  1529. else:
  1530. return false
  1531. proc isTupleRecursive*(t: PType): bool =
  1532. var cycleDetector = initIntSet()
  1533. isTupleRecursive(t, cycleDetector)
  1534. proc isException*(t: PType): bool =
  1535. # check if `y` is object type and it inherits from Exception
  1536. assert(t != nil)
  1537. var t = t.skipTypes(abstractInst)
  1538. while t.kind == tyObject:
  1539. if t.sym != nil and t.sym.magic == mException: return true
  1540. if t[0] == nil: break
  1541. t = skipTypes(t[0], abstractPtrs)
  1542. return false
  1543. proc isDefectException*(t: PType): bool =
  1544. var t = t.skipTypes(abstractPtrs)
  1545. while t.kind == tyObject:
  1546. if t.sym != nil and t.sym.owner != nil and
  1547. sfSystemModule in t.sym.owner.flags and
  1548. t.sym.name.s == "Defect":
  1549. return true
  1550. if t[0] == nil: break
  1551. t = skipTypes(t[0], abstractPtrs)
  1552. return false
  1553. proc isSinkTypeForParam*(t: PType): bool =
  1554. # a parameter like 'seq[owned T]' must not be used only once, but its
  1555. # elements must, so we detect this case here:
  1556. result = t.skipTypes({tyGenericInst, tyAlias}).kind in {tySink, tyOwned}
  1557. when false:
  1558. if isSinkType(t):
  1559. if t.skipTypes({tyGenericInst, tyAlias}).kind in {tyArray, tyVarargs, tyOpenArray, tySequence}:
  1560. result = false
  1561. else:
  1562. result = true
  1563. proc lookupFieldAgain*(ty: PType; field: PSym): PSym =
  1564. var ty = ty
  1565. while ty != nil:
  1566. ty = ty.skipTypes(skipPtrs)
  1567. assert(ty.kind in {tyTuple, tyObject})
  1568. result = lookupInRecord(ty.n, field.name)
  1569. if result != nil: break
  1570. ty = ty[0]
  1571. if result == nil: result = field
  1572. proc isCharArrayPtr*(t: PType; allowPointerToChar: bool): bool =
  1573. let t = t.skipTypes(abstractInst)
  1574. if t.kind == tyPtr:
  1575. let pointsTo = t[0].skipTypes(abstractInst)
  1576. case pointsTo.kind
  1577. of tyUncheckedArray:
  1578. result = pointsTo[0].kind == tyChar
  1579. of tyArray:
  1580. result = pointsTo[1].kind == tyChar and firstOrd(nil, pointsTo[0]) == 0 and
  1581. skipTypes(pointsTo[0], {tyRange}).kind in {tyInt..tyInt64}
  1582. of tyChar:
  1583. result = allowPointerToChar
  1584. else:
  1585. discard
  1586. proc lacksMTypeField*(typ: PType): bool {.inline.} =
  1587. (typ.sym != nil and sfPure in typ.sym.flags) or tfFinal in typ.flags