diff --git a/compiler/layeredtable.nim b/compiler/layeredtable.nim index 064253264b55..565fb9546411 100644 --- a/compiler/layeredtable.nim +++ b/compiler/layeredtable.nim @@ -3,11 +3,18 @@ import ast type LayeredIdTableObj* {.acyclic.} = object + ## stack of type binding contexts implemented as a linked list topLayer*: TypeMapping + ## the mappings on the current layer nextLayer*: ref LayeredIdTableObj - previousLen*: int # used to track if bindings were added + ## the parent type binding context, possibly `nil` + previousLen*: int + ## total length of the bindings up to the parent layer, + ## used to track if new bindings were added const useRef = not defined(gcDestructors) + # implementation detail, only arc/orc doesn't cause issues when + # using LayeredIdTable as an object and not a ref when useRef: type LayeredIdTable* = ref LayeredIdTableObj @@ -18,9 +25,13 @@ proc initLayeredTypeMap*(pt: sink TypeMapping = initTypeMapping()): LayeredIdTab result = LayeredIdTable(topLayer: pt, nextLayer: nil) proc shallowCopy*(pt: LayeredIdTable): LayeredIdTable {.inline.} = + ## copies only the type bindings of the current layer, but not any parent layers, + ## useful for write-only bindings result = LayeredIdTable(topLayer: pt.topLayer, nextLayer: pt.nextLayer, previousLen: pt.previousLen) proc currentLen*(pt: LayeredIdTable): int = + ## the sum of the cached total binding count of the parents and + ## the current binding count, just used to track if bindings were added pt.previousLen + pt.topLayer.len proc newTypeMapLayer*(pt: LayeredIdTable): LayeredIdTable = @@ -51,6 +62,7 @@ proc lookup(typeMap: ref LayeredIdTableObj, key: ItemId): PType = tm = tm.nextLayer template lookup*(typeMap: ref LayeredIdTableObj, key: PType): PType = + ## recursively looks up binding of `key` in all parent layers lookup(typeMap, key.itemId) when not useRef: @@ -66,4 +78,5 @@ proc put(typeMap: var LayeredIdTable, key: ItemId, value: PType) {.inline.} = typeMap.topLayer[key] = value template put*(typeMap: var LayeredIdTable, key, value: PType) = + ## binds `key` to `value` only in current layer put(typeMap, key.itemId, value) diff --git a/compiler/seminst.nim b/compiler/seminst.nim index 179176c69fc8..e132e048a16c 100644 --- a/compiler/seminst.nim +++ b/compiler/seminst.nim @@ -237,7 +237,7 @@ proc instantiateProcType(c: PContext, pt: LayeredIdTable, # will need to use openScope, addDecl, etc. #addDecl(c, prc) pushInfoContext(c.config, info) - var typeMap = shallowCopy(pt) + var typeMap = shallowCopy(pt) # use previous bindings without writing to them var cl = initTypeVars(c, typeMap, info, nil) var result = instCopyType(cl, prc.typ) let originalParams = result.n diff --git a/compiler/semtypinst.nim b/compiler/semtypinst.nim index 0b57ac22afca..ce5e3e9a652b 100644 --- a/compiler/semtypinst.nim +++ b/compiler/semtypinst.nim @@ -775,7 +775,7 @@ proc initTypeVars*(p: PContext, typeMap: LayeredIdTable, info: TLineInfo; proc replaceTypesInBody*(p: PContext, pt: LayeredIdTable, n: PNode; owner: PSym, allowMetaTypes = false, fromStaticExpr = false, expectedType: PType = nil): PNode = - var typeMap = shallowCopy(pt) + var typeMap = shallowCopy(pt) # use previous bindings without writing to them var cl = initTypeVars(p, typeMap, n.info, owner) cl.allowMetaTypes = allowMetaTypes pushInfoContext(p.config, n.info) @@ -784,7 +784,7 @@ proc replaceTypesInBody*(p: PContext, pt: LayeredIdTable, n: PNode; proc prepareTypesInBody*(p: PContext, pt: LayeredIdTable, n: PNode; owner: PSym = nil): PNode = - var typeMap = shallowCopy(pt) + var typeMap = shallowCopy(pt) # use previous bindings without writing to them var cl = initTypeVars(p, typeMap, n.info, owner) pushInfoContext(p.config, n.info) result = prepareNode(cl, n) @@ -823,7 +823,7 @@ proc generateTypeInstance*(p: PContext, pt: LayeredIdTable, info: TLineInfo, # pt: Table with type mappings: T -> int # Desired result: Foo[int] # proc (x: T = 0); T -> int ----> proc (x: int = 0) - var typeMap = shallowCopy(pt) + var typeMap = shallowCopy(pt) # use previous bindings without writing to them var cl = initTypeVars(p, typeMap, info, nil) pushInfoContext(p.config, info) result = replaceTypeVarsT(cl, t) @@ -835,7 +835,7 @@ proc generateTypeInstance*(p: PContext, pt: LayeredIdTable, info: TLineInfo, proc prepareMetatypeForSigmatch*(p: PContext, pt: LayeredIdTable, info: TLineInfo, t: PType): PType = - var typeMap = shallowCopy(pt) + var typeMap = shallowCopy(pt) # use previous bindings without writing to them var cl = initTypeVars(p, typeMap, info, nil) cl.allowMetaTypes = true pushInfoContext(p.config, info)