semtypinst.nim 27 KB

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