diff --git a/compiler/ast.nim b/compiler/ast.nim index bc28cff845..bafc02dba2 100644 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -1680,3 +1680,10 @@ type template initSymMapping*(): SymMapping = initIdTable[PSym]() template initTypeMapping*(): TypeMapping = initIdTable[PType]() + +proc sameModules*(a, b: PSym): bool {.inline.} = + assert a.kind == skModule and b.kind == skModule + result = a.position == b.position + +proc sameOwners*(a, b: PSym): bool = + result = a == b or (a.kind == skModule and b.kind == skModule and a.position == b.position) or a.id == b.id diff --git a/compiler/cgen.nim b/compiler/cgen.nim index b380b136d2..591979aea1 100644 --- a/compiler/cgen.nim +++ b/compiler/cgen.nim @@ -1543,7 +1543,7 @@ proc genProcLvl2(m: BModule, prc: PSym) = # externally-to-the-current-module defined proc, also important # to do the declaredProtos check before the call to genProcPrototype if isReloadable(m, prc) and prc.id notin m.declaredProtos and - q != nil and q.module.id != m.module.id: + q != nil and not sameModules(q.module, m.module): m.s[cfsDynLibInit].add('\t') m.s[cfsDynLibInit].addAssignment(prc.loc.snippet, cCast(getProcTypeCast(m, prc), @@ -1601,7 +1601,7 @@ proc genVarPrototype(m: BModule, n: PNode) = if (lfNoDecl in sym.loc.flags) or contains(m.declaredThings, sym.id): return - if sym.owner.id != m.module.id: + if not sameOwners(sym.owner, m.module): # else we already have the symbol generated! assert(sym.loc.snippet != "") incl(m.declaredThings, sym.id) diff --git a/compiler/nifbackend.nim b/compiler/nifbackend.nim index 39da0d762e..fa293bbfe3 100644 --- a/compiler/nifbackend.nim +++ b/compiler/nifbackend.nim @@ -131,11 +131,18 @@ proc generateCode*(g: ModuleGraph; mainFileIdx: FileIndex) = # during code generation of `main.nim` we can trigger the code generation # of symbols in different modules so we need to finish these modules # here later, after the above loop! + # Important: The main module must be finished LAST so that all other modules + # have registered their init procs before genMainProc uses them. + var mainModule: BModule = nil for m in BModuleList(g.backend).mods: if m != nil: assert m.module != nil - #if sfMainModule notin m.module.flags: - finishModule g, m + if sfMainModule in m.module.flags: + mainModule = m + else: + finishModule g, m + if mainModule != nil: + finishModule g, mainModule # Write C files cgenWriteModules(g.backend, g.config) diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim index c86af27c91..be9e409108 100644 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -2361,7 +2361,7 @@ proc semCppMember(c: PContext; s: PSym; n: PNode) = typ = typ.elementType if typ.kind != tyObject: localError(c.config, n.info, pragmaName & " must be either ptr to object or object type.") - if typ.owner.id == s.owner.id and c.module.id == s.owner.id: + if sameOwners(typ.owner, s.owner) and sameOwners(c.module, s.owner): c.graph.memberProcsPerType.mgetOrPut(typ.itemId, @[]).add s else: localError(c.config, n.info, diff --git a/compiler/suggest.nim b/compiler/suggest.nim index 5c3265dba2..a1cd8b9237 100644 --- a/compiler/suggest.nim +++ b/compiler/suggest.nim @@ -356,12 +356,12 @@ proc filterSymNoOpr(s: PSym; prefix: PNode; res: var PrefixMatch): bool {.inline not isKeyword(s.name) proc fieldVisible*(c: PContext, f: PSym): bool {.inline.} = - let fmoduleId = getModule(f).id - result = sfExported in f.flags or fmoduleId == c.module.id + let fmodule = getModule(f) + result = sfExported in f.flags or sameModules(fmodule, c.module) if not result: for module in c.friendModules: - if fmoduleId == module.id: return true + if sameModules(fmodule, module): return true if f.kind == skField: var symObj = f.owner.typ.toObjectFromRefPtrGeneric.sym assert symObj != nil