semtypinst.nim 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616
  1. #
  2. #
  3. # The Nim Compiler
  4. # (c) Copyright 2015 Andreas Rumpf
  5. #
  6. # See the file "copying.txt", included in this
  7. # distribution, for details about the copyright.
  8. #
  9. # This module does the instantiation of generic types.
  10. import ast, astalgo, msgs, types, magicsys, semdata, renderer, options,
  11. lineinfos
  12. const
  13. tfInstClearedFlags = {tfHasMeta, tfUnresolved}
  14. proc checkPartialConstructedType(conf: ConfigRef; info: TLineInfo, t: PType) =
  15. if tfAcyclic in t.flags and skipTypes(t, abstractInst).kind != tyObject:
  16. localError(conf, info, "invalid pragma: acyclic")
  17. elif t.kind in {tyVar, tyLent} and t.sons[0].kind in {tyVar, tyLent}:
  18. localError(conf, info, "type 'var var' is not allowed")
  19. proc checkConstructedType*(conf: ConfigRef; info: TLineInfo, typ: PType) =
  20. var t = typ.skipTypes({tyDistinct})
  21. if t.kind in tyTypeClasses: discard
  22. elif tfAcyclic in t.flags and skipTypes(t, abstractInst).kind != tyObject:
  23. localError(conf, info, "invalid pragma: acyclic")
  24. elif t.kind in {tyVar, tyLent} and t.sons[0].kind in {tyVar, tyLent}:
  25. localError(conf, info, "type 'var var' is not allowed")
  26. elif computeSize(conf, t) == szIllegalRecursion:
  27. localError(conf, info, "illegal recursion in type '" & typeToString(t) & "'")
  28. t = typ.skipTypes({tyGenericInst})
  29. if t.kind == tyArray and tfUncheckedArray in t.flags:
  30. t[0].flags.incl tfUncheckedArray # mark range of unchecked array also unchecked
  31. when false:
  32. if t.kind == tyObject and t.sons[0] != nil:
  33. if t.sons[0].kind != tyObject or tfFinal in t.sons[0].flags:
  34. localError(info, errInheritanceOnlyWithNonFinalObjects)
  35. proc searchInstTypes*(key: PType): PType =
  36. let genericTyp = key.sons[0]
  37. if not (genericTyp.kind == tyGenericBody and
  38. key.sons[0] == genericTyp and genericTyp.sym != nil): return
  39. when not defined(nimNoNilSeqs):
  40. if genericTyp.sym.typeInstCache == nil: return
  41. for inst in genericTyp.sym.typeInstCache:
  42. if inst.id == key.id: return inst
  43. if inst.sons.len < key.sons.len:
  44. # XXX: This happens for prematurely cached
  45. # types such as Channel[empty]. Why?
  46. # See the notes for PActor in handleGenericInvocation
  47. return
  48. if not sameFlags(inst, key):
  49. continue
  50. block matchType:
  51. for j in 1 .. high(key.sons):
  52. # XXX sameType is not really correct for nested generics?
  53. if not compareTypes(inst.sons[j], key.sons[j],
  54. flags = {ExactGenericParams}):
  55. break matchType
  56. return inst
  57. proc cacheTypeInst*(inst: PType) =
  58. # XXX: add to module's generics
  59. # update the refcount
  60. let gt = inst.sons[0]
  61. let t = if gt.kind == tyGenericBody: gt.lastSon else: gt
  62. if t.kind in {tyStatic, tyGenericParam} + tyTypeClasses:
  63. return
  64. gt.sym.typeInstCache.add(inst)
  65. type
  66. LayeredIdTable* = object
  67. topLayer*: TIdTable
  68. nextLayer*: ptr LayeredIdTable
  69. TReplTypeVars* = object
  70. c*: PContext
  71. typeMap*: ptr LayeredIdTable # map PType to PType
  72. symMap*: TIdTable # map PSym to PSym
  73. localCache*: TIdTable # local cache for remembering alraedy replaced
  74. # types during instantiation of meta types
  75. # (they are not stored in the global cache)
  76. info*: TLineInfo
  77. allowMetaTypes*: bool # allow types such as seq[Number]
  78. # i.e. the result contains unresolved generics
  79. skipTypedesc*: bool # wether we should skip typeDescs
  80. owner*: PSym # where this instantiation comes from
  81. recursionLimit: int
  82. proc replaceTypeVarsTAux(cl: var TReplTypeVars, t: PType): PType
  83. proc replaceTypeVarsS(cl: var TReplTypeVars, s: PSym): PSym
  84. proc replaceTypeVarsN*(cl: var TReplTypeVars, n: PNode; start=0): PNode
  85. proc initLayeredTypeMap*(pt: TIdTable): LayeredIdTable =
  86. copyIdTable(result.topLayer, pt)
  87. proc newTypeMapLayer*(cl: var TReplTypeVars): LayeredIdTable =
  88. result.nextLayer = cl.typeMap
  89. initIdTable(result.topLayer)
  90. proc lookup(typeMap: ptr LayeredIdTable, key: PType): PType =
  91. var tm = typeMap
  92. while tm != nil:
  93. result = PType(idTableGet(tm.topLayer, key))
  94. if result != nil: return
  95. tm = tm.nextLayer
  96. template put(typeMap: ptr LayeredIdTable, key, value: PType) =
  97. idTablePut(typeMap.topLayer, key, value)
  98. template checkMetaInvariants(cl: TReplTypeVars, t: PType) =
  99. when false:
  100. if t != nil and tfHasMeta in t.flags and
  101. cl.allowMetaTypes == false:
  102. echo "UNEXPECTED META ", t.id, " ", instantiationInfo(-1)
  103. debug t
  104. writeStackTrace()
  105. proc replaceTypeVarsT*(cl: var TReplTypeVars, t: PType): PType =
  106. result = replaceTypeVarsTAux(cl, t)
  107. checkMetaInvariants(cl, result)
  108. proc prepareNode(cl: var TReplTypeVars, n: PNode): PNode =
  109. let t = replaceTypeVarsT(cl, n.typ)
  110. if t != nil and t.kind == tyStatic and t.n != nil:
  111. return if tfUnresolved in t.flags: prepareNode(cl, t.n)
  112. else: t.n
  113. result = copyNode(n)
  114. result.typ = t
  115. if result.kind == nkSym: result.sym = replaceTypeVarsS(cl, n.sym)
  116. let isCall = result.kind in nkCallKinds
  117. for i in 0 ..< n.safeLen:
  118. # XXX HACK: ``f(a, b)``, avoid to instantiate `f`
  119. if isCall and i == 0: result.add(n[i])
  120. else: result.add(prepareNode(cl, n[i]))
  121. proc isTypeParam(n: PNode): bool =
  122. # XXX: generic params should use skGenericParam instead of skType
  123. return n.kind == nkSym and
  124. (n.sym.kind == skGenericParam or
  125. (n.sym.kind == skType and sfFromGeneric in n.sym.flags))
  126. proc reResolveCallsWithTypedescParams(cl: var TReplTypeVars, n: PNode): PNode =
  127. # This is needed for tgenericshardcases
  128. # It's possible that a generic param will be used in a proc call to a
  129. # typedesc accepting proc. After generic param substitution, such procs
  130. # should be optionally instantiated with the correct type. In order to
  131. # perform this instantiation, we need to re-run the generateInstance path
  132. # in the compiler, but it's quite complicated to do so at the moment so we
  133. # resort to a mild hack; the head symbol of the call is temporary reset and
  134. # overload resolution is executed again (which may trigger generateInstance).
  135. if n.kind in nkCallKinds and sfFromGeneric in n[0].sym.flags:
  136. var needsFixing = false
  137. for i in 1 ..< n.safeLen:
  138. if isTypeParam(n[i]): needsFixing = true
  139. if needsFixing:
  140. n.sons[0] = newSymNode(n.sons[0].sym.owner)
  141. return cl.c.semOverloadedCall(cl.c, n, n, {skProc, skFunc}, {})
  142. for i in 0 ..< n.safeLen:
  143. n.sons[i] = reResolveCallsWithTypedescParams(cl, n[i])
  144. return n
  145. proc replaceTypeVarsN(cl: var TReplTypeVars, n: PNode; start=0): PNode =
  146. if n == nil: return
  147. result = copyNode(n)
  148. if n.typ != nil:
  149. result.typ = replaceTypeVarsT(cl, n.typ)
  150. checkMetaInvariants(cl, result.typ)
  151. case n.kind
  152. of nkNone..pred(nkSym), succ(nkSym)..nkNilLit:
  153. discard
  154. of nkSym:
  155. result.sym = replaceTypeVarsS(cl, n.sym)
  156. if result.sym.typ.kind == tyVoid:
  157. # don't add the 'void' field
  158. result = newNode(nkRecList, n.info)
  159. of nkRecWhen:
  160. var branch: PNode = nil # the branch to take
  161. for i in countup(0, sonsLen(n) - 1):
  162. var it = n.sons[i]
  163. if it == nil: illFormedAst(n, cl.c.config)
  164. case it.kind
  165. of nkElifBranch:
  166. checkSonsLen(it, 2, cl.c.config)
  167. var cond = prepareNode(cl, it.sons[0])
  168. var e = cl.c.semConstExpr(cl.c, cond)
  169. if e.kind != nkIntLit:
  170. internalError(cl.c.config, e.info, "ReplaceTypeVarsN: when condition not a bool")
  171. if e.intVal != 0 and branch == nil: branch = it.sons[1]
  172. of nkElse:
  173. checkSonsLen(it, 1, cl.c.config)
  174. if branch == nil: branch = it.sons[0]
  175. else: illFormedAst(n, cl.c.config)
  176. if branch != nil:
  177. result = replaceTypeVarsN(cl, branch)
  178. else:
  179. result = newNodeI(nkRecList, n.info)
  180. of nkStaticExpr:
  181. var n = prepareNode(cl, n)
  182. n = reResolveCallsWithTypedescParams(cl, n)
  183. result = if cl.allowMetaTypes: n
  184. else: cl.c.semExpr(cl.c, n)
  185. else:
  186. var length = sonsLen(n)
  187. if length > 0:
  188. newSons(result, length)
  189. if start > 0:
  190. result.sons[0] = n.sons[0]
  191. for i in countup(start, length - 1):
  192. result.sons[i] = replaceTypeVarsN(cl, n.sons[i])
  193. proc replaceTypeVarsS(cl: var TReplTypeVars, s: PSym): PSym =
  194. if s == nil: return nil
  195. # symbol is not our business:
  196. if cl.owner != nil and s.owner != cl.owner:
  197. return s
  198. # XXX: Bound symbols in default parameter expressions may reach here.
  199. # We cannot process them, becase `sym.n` may point to a proc body with
  200. # cyclic references that will lead to an infinite recursion.
  201. # Perhaps we should not use a black-list here, but a whitelist instead
  202. # (e.g. skGenericParam and skType).
  203. # Note: `s.magic` may be `mType` in an example such as:
  204. # proc foo[T](a: T, b = myDefault(type(a)))
  205. if s.kind == skProc or s.magic != mNone:
  206. return s
  207. #result = PSym(idTableGet(cl.symMap, s))
  208. #if result == nil:
  209. result = copySym(s, false)
  210. incl(result.flags, sfFromGeneric)
  211. #idTablePut(cl.symMap, s, result)
  212. result.owner = s.owner
  213. result.typ = replaceTypeVarsT(cl, s.typ)
  214. result.ast = replaceTypeVarsN(cl, s.ast)
  215. proc lookupTypeVar(cl: var TReplTypeVars, t: PType): PType =
  216. result = cl.typeMap.lookup(t)
  217. if result == nil:
  218. if cl.allowMetaTypes or tfRetType in t.flags: return
  219. localError(cl.c.config, t.sym.info, "cannot instantiate: '" & typeToString(t) & "'")
  220. result = errorType(cl.c)
  221. # In order to prevent endless recursions, we must remember
  222. # this bad lookup and replace it with errorType everywhere.
  223. # These code paths are only active in "nim check"
  224. cl.typeMap.put(t, result)
  225. elif result.kind == tyGenericParam and not cl.allowMetaTypes:
  226. internalError(cl.c.config, cl.info, "substitution with generic parameter")
  227. proc instCopyType*(cl: var TReplTypeVars, t: PType): PType =
  228. # XXX: relying on allowMetaTypes is a kludge
  229. result = copyType(t, t.owner, cl.allowMetaTypes)
  230. if cl.allowMetaTypes: return
  231. result.flags.incl tfFromGeneric
  232. if not (t.kind in tyMetaTypes or
  233. (t.kind == tyStatic and t.n == nil)):
  234. result.flags.excl tfInstClearedFlags
  235. when false:
  236. if newDestructors:
  237. result.assignment = nil
  238. #result.destructor = nil
  239. result.sink = nil
  240. template typeBound(c, newty, oldty, field, info) =
  241. let opr = newty.field
  242. if opr != nil and sfFromGeneric notin opr.flags:
  243. # '=' needs to be instantiated for generics when the type is constructed:
  244. newty.field = c.instTypeBoundOp(c, opr, oldty, info, attachedAsgn, 1)
  245. proc handleGenericInvocation(cl: var TReplTypeVars, t: PType): PType =
  246. # tyGenericInvocation[A, tyGenericInvocation[A, B]]
  247. # is difficult to handle:
  248. const eqFlags = eqTypeFlags + {tfGcSafe}
  249. var body = t.sons[0]
  250. if body.kind != tyGenericBody:
  251. internalError(cl.c.config, cl.info, "no generic body")
  252. var header: PType = t
  253. # search for some instantiation here:
  254. if cl.allowMetaTypes:
  255. result = PType(idTableGet(cl.localCache, t))
  256. else:
  257. result = searchInstTypes(t)
  258. if result != nil and eqFlags*result.flags == eqFlags*t.flags: return
  259. for i in countup(1, sonsLen(t) - 1):
  260. var x = t.sons[i]
  261. if x.kind in {tyGenericParam}:
  262. x = lookupTypeVar(cl, x)
  263. if x != nil:
  264. if header == t: header = instCopyType(cl, t)
  265. header.sons[i] = x
  266. propagateToOwner(header, x)
  267. else:
  268. propagateToOwner(header, x)
  269. if header != t:
  270. # search again after first pass:
  271. result = searchInstTypes(header)
  272. if result != nil and eqFlags*result.flags == eqFlags*t.flags: return
  273. else:
  274. header = instCopyType(cl, t)
  275. result = newType(tyGenericInst, t.sons[0].owner)
  276. result.flags = header.flags
  277. # be careful not to propagate unnecessary flags here (don't use rawAddSon)
  278. result.sons = @[header.sons[0]]
  279. # ugh need another pass for deeply recursive generic types (e.g. PActor)
  280. # we need to add the candidate here, before it's fully instantiated for
  281. # recursive instantions:
  282. if not cl.allowMetaTypes:
  283. cacheTypeInst(result)
  284. else:
  285. idTablePut(cl.localCache, t, result)
  286. let oldSkipTypedesc = cl.skipTypedesc
  287. cl.skipTypedesc = true
  288. var typeMapLayer = newTypeMapLayer(cl)
  289. cl.typeMap = addr(typeMapLayer)
  290. for i in countup(1, sonsLen(t) - 1):
  291. var x = replaceTypeVarsT(cl, t.sons[i])
  292. assert x.kind != tyGenericInvocation
  293. header.sons[i] = x
  294. propagateToOwner(header, x)
  295. cl.typeMap.put(body.sons[i-1], x)
  296. for i in countup(1, sonsLen(t) - 1):
  297. # if one of the params is not concrete, we cannot do anything
  298. # but we already raised an error!
  299. rawAddSon(result, header.sons[i])
  300. let bbody = lastSon body
  301. var newbody = replaceTypeVarsT(cl, bbody)
  302. let bodyIsNew = newbody != bbody
  303. cl.skipTypedesc = oldSkipTypedesc
  304. newbody.flags = newbody.flags + (t.flags + body.flags - tfInstClearedFlags)
  305. result.flags = result.flags + newbody.flags - tfInstClearedFlags
  306. cl.typeMap = cl.typeMap.nextLayer
  307. # This is actually wrong: tgeneric_closure fails with this line:
  308. #newbody.callConv = body.callConv
  309. # This type may be a generic alias and we want to resolve it here.
  310. # One step is enough, because the recursive nature of
  311. # handleGenericInvocation will handle the alias-to-alias-to-alias case
  312. if newbody.isGenericAlias: newbody = newbody.skipGenericAlias
  313. rawAddSon(result, newbody)
  314. checkPartialConstructedType(cl.c.config, cl.info, newbody)
  315. let dc = newbody.deepCopy
  316. if cl.allowMetaTypes == false:
  317. if dc != nil and sfFromGeneric notin newbody.deepCopy.flags:
  318. # 'deepCopy' needs to be instantiated for
  319. # generics *when the type is constructed*:
  320. newbody.deepCopy = cl.c.instTypeBoundOp(cl.c, dc, result, cl.info,
  321. attachedDeepCopy, 1)
  322. if bodyIsNew and newbody.typeInst == nil:
  323. #doassert newbody.typeInst == nil
  324. newbody.typeInst = result
  325. if tfRefsAnonObj in newbody.flags and newbody.kind != tyGenericInst:
  326. # can come here for tyGenericInst too, see tests/metatype/ttypeor.nim
  327. # need to look into this issue later
  328. assert newbody.kind in {tyRef, tyPtr}
  329. if newbody.lastSon.typeInst != nil:
  330. #internalError(cl.c.config, cl.info, "ref already has a 'typeInst' field")
  331. discard
  332. else:
  333. newbody.lastSon.typeInst = result
  334. cl.c.typesWithOps.add((newbody, result))
  335. let mm = skipTypes(bbody, abstractPtrs)
  336. if tfFromGeneric notin mm.flags:
  337. # bug #5479, prevent endless recursions here:
  338. incl mm.flags, tfFromGeneric
  339. let methods = mm.methods
  340. for col, meth in items(methods):
  341. # we instantiate the known methods belonging to that type, this causes
  342. # them to be registered and that's enough, so we 'discard' the result.
  343. discard cl.c.instTypeBoundOp(cl.c, meth, result, cl.info,
  344. attachedAsgn, col)
  345. excl mm.flags, tfFromGeneric
  346. proc eraseVoidParams*(t: PType) =
  347. # transform '(): void' into '()' because old parts of the compiler really
  348. # don't deal with '(): void':
  349. if t.sons[0] != nil and t.sons[0].kind == tyVoid:
  350. t.sons[0] = nil
  351. for i in 1 ..< t.sonsLen:
  352. # don't touch any memory unless necessary
  353. if t.sons[i].kind == tyVoid:
  354. var pos = i
  355. for j in i+1 ..< t.sonsLen:
  356. if t.sons[j].kind != tyVoid:
  357. t.sons[pos] = t.sons[j]
  358. t.n.sons[pos] = t.n.sons[j]
  359. inc pos
  360. setLen t.sons, pos
  361. setLen t.n.sons, pos
  362. return
  363. proc skipIntLiteralParams*(t: PType) =
  364. for i in 0 ..< t.sonsLen:
  365. let p = t.sons[i]
  366. if p == nil: continue
  367. let skipped = p.skipIntLit
  368. if skipped != p:
  369. t.sons[i] = skipped
  370. if i > 0: t.n.sons[i].sym.typ = skipped
  371. # when the typeof operator is used on a static input
  372. # param, the results gets infected with static as well:
  373. if t.sons[0] != nil and t.sons[0].kind == tyStatic:
  374. t.sons[0] = t.sons[0].base
  375. proc propagateFieldFlags(t: PType, n: PNode) =
  376. # This is meant for objects and tuples
  377. # The type must be fully instantiated!
  378. if n.isNil:
  379. return
  380. #internalAssert n.kind != nkRecWhen
  381. case n.kind
  382. of nkSym:
  383. propagateToOwner(t, n.sym.typ)
  384. of nkRecList, nkRecCase, nkOfBranch, nkElse:
  385. for son in n:
  386. propagateFieldFlags(t, son)
  387. else: discard
  388. proc replaceTypeVarsTAux(cl: var TReplTypeVars, t: PType): PType =
  389. template bailout =
  390. if cl.recursionLimit > 100:
  391. # bail out, see bug #2509. But note this caching is in general wrong,
  392. # look at this example where TwoVectors should not share the generic
  393. # instantiations (bug #3112):
  394. # type
  395. # Vector[N: static[int]] = array[N, float64]
  396. # TwoVectors[Na, Nb: static[int]] = (Vector[Na], Vector[Nb])
  397. result = PType(idTableGet(cl.localCache, t))
  398. if result != nil: return result
  399. inc cl.recursionLimit
  400. result = t
  401. if t == nil: return
  402. if t.kind in {tyStatic, tyGenericParam} + tyTypeClasses:
  403. let lookup = cl.typeMap.lookup(t)
  404. if lookup != nil: return lookup
  405. case t.kind
  406. of tyGenericInvocation:
  407. result = handleGenericInvocation(cl, t)
  408. if result.lastSon.kind == tyUserTypeClass:
  409. result.kind = tyUserTypeClassInst
  410. of tyGenericBody:
  411. localError(cl.c.config, cl.info, "cannot instantiate: '" & typeToString(t) & "'")
  412. result = errorType(cl.c)
  413. #result = replaceTypeVarsT(cl, lastSon(t))
  414. of tyFromExpr:
  415. if cl.allowMetaTypes: return
  416. # This assert is triggered when a tyFromExpr was created in a cyclic
  417. # way. You should break the cycle at the point of creation by introducing
  418. # a call such as: `n.typ = makeTypeFromExpr(c, n.copyTree)`
  419. # Otherwise, the cycle will be fatal for the prepareNode call below
  420. assert t.n.typ != t
  421. var n = prepareNode(cl, t.n)
  422. if n.kind != nkEmpty:
  423. n = cl.c.semConstExpr(cl.c, n)
  424. if n.typ.kind == tyTypeDesc:
  425. # XXX: sometimes, chained typedescs enter here.
  426. # It may be worth investigating why this is happening,
  427. # because it may cause other bugs elsewhere.
  428. result = n.typ.skipTypes({tyTypeDesc})
  429. # result = n.typ.base
  430. else:
  431. if n.typ.kind != tyStatic:
  432. # XXX: In the future, semConstExpr should
  433. # return tyStatic values to let anyone make
  434. # use of this knowledge. The patching here
  435. # won't be necessary then.
  436. result = newTypeS(tyStatic, cl.c)
  437. result.sons = @[n.typ]
  438. result.n = n
  439. else:
  440. result = n.typ
  441. of tyInt, tyFloat:
  442. result = skipIntLit(t)
  443. of tyTypeDesc:
  444. let lookup = cl.typeMap.lookup(t)
  445. if lookup != nil:
  446. result = lookup
  447. if tfUnresolved in t.flags or cl.skipTypedesc: result = result.base
  448. elif t.sons[0].kind != tyNone:
  449. result = makeTypeDesc(cl.c, replaceTypeVarsT(cl, t.sons[0]))
  450. of tyUserTypeClass, tyStatic:
  451. result = t
  452. of tyGenericInst, tyUserTypeClassInst:
  453. bailout()
  454. result = instCopyType(cl, t)
  455. idTablePut(cl.localCache, t, result)
  456. for i in 1 ..< result.sonsLen:
  457. result.sons[i] = replaceTypeVarsT(cl, result.sons[i])
  458. propagateToOwner(result, result.lastSon)
  459. else:
  460. if containsGenericType(t):
  461. #if not cl.allowMetaTypes:
  462. bailout()
  463. result = instCopyType(cl, t)
  464. result.size = -1 # needs to be recomputed
  465. #if not cl.allowMetaTypes:
  466. idTablePut(cl.localCache, t, result)
  467. for i in countup(0, sonsLen(result) - 1):
  468. if result.sons[i] != nil:
  469. var r = replaceTypeVarsT(cl, result.sons[i])
  470. if result.kind == tyObject:
  471. # carefully coded to not skip the precious tyGenericInst:
  472. let r2 = r.skipTypes({tyAlias, tySink})
  473. if r2.kind in {tyPtr, tyRef}:
  474. r = skipTypes(r2, {tyPtr, tyRef})
  475. result.sons[i] = r
  476. if result.kind != tyArray or i != 0:
  477. propagateToOwner(result, r)
  478. # bug #4677: Do not instantiate effect lists
  479. result.n = replaceTypeVarsN(cl, result.n, ord(result.kind==tyProc))
  480. case result.kind
  481. of tyArray:
  482. let idx = result.sons[0]
  483. internalAssert cl.c.config, idx.kind != tyStatic
  484. of tyObject, tyTuple:
  485. propagateFieldFlags(result, result.n)
  486. of tyProc:
  487. eraseVoidParams(result)
  488. skipIntLiteralParams(result)
  489. else: discard
  490. proc instAllTypeBoundOp*(c: PContext, info: TLineInfo) =
  491. var i = 0
  492. while i < c.typesWithOps.len:
  493. let (newty, oldty) = c.typesWithOps[i]
  494. typeBound(c, newty, oldty, destructor, info)
  495. typeBound(c, newty, oldty, sink, info)
  496. typeBound(c, newty, oldty, assignment, info)
  497. inc i
  498. setLen(c.typesWithOps, 0)
  499. proc initTypeVars*(p: PContext, typeMap: ptr LayeredIdTable, info: TLineInfo;
  500. owner: PSym): TReplTypeVars =
  501. initIdTable(result.symMap)
  502. initIdTable(result.localCache)
  503. result.typeMap = typeMap
  504. result.info = info
  505. result.c = p
  506. result.owner = owner
  507. proc replaceTypesInBody*(p: PContext, pt: TIdTable, n: PNode;
  508. owner: PSym, allowMetaTypes = false): PNode =
  509. var typeMap = initLayeredTypeMap(pt)
  510. var cl = initTypeVars(p, addr(typeMap), n.info, owner)
  511. cl.allowMetaTypes = allowMetaTypes
  512. pushInfoContext(p.config, n.info)
  513. result = replaceTypeVarsN(cl, n)
  514. popInfoContext(p.config)
  515. proc replaceTypesForLambda*(p: PContext, pt: TIdTable, n: PNode;
  516. original, new: PSym): PNode =
  517. var typeMap = initLayeredTypeMap(pt)
  518. var cl = initTypeVars(p, addr(typeMap), n.info, original)
  519. idTablePut(cl.symMap, original, new)
  520. pushInfoContext(p.config, n.info)
  521. result = replaceTypeVarsN(cl, n)
  522. popInfoContext(p.config)
  523. proc generateTypeInstance*(p: PContext, pt: TIdTable, info: TLineInfo,
  524. t: PType): PType =
  525. var typeMap = initLayeredTypeMap(pt)
  526. var cl = initTypeVars(p, addr(typeMap), info, nil)
  527. pushInfoContext(p.config, info)
  528. result = replaceTypeVarsT(cl, t)
  529. popInfoContext(p.config)
  530. proc prepareMetatypeForSigmatch*(p: PContext, pt: TIdTable, info: TLineInfo,
  531. t: PType): PType =
  532. var typeMap = initLayeredTypeMap(pt)
  533. var cl = initTypeVars(p, addr(typeMap), info, nil)
  534. cl.allowMetaTypes = true
  535. pushInfoContext(p.config, info)
  536. result = replaceTypeVarsT(cl, t)
  537. popInfoContext(p.config)
  538. template generateTypeInstance*(p: PContext, pt: TIdTable, arg: PNode,
  539. t: PType): untyped =
  540. generateTypeInstance(p, pt, arg.info, t)