semtypinst.nim 25 KB

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