From ae83058be2ab48ddd39375ae5d714a8d7d8036c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juan=20M=20G=C3=B3mez?= Date: Fri, 21 Apr 2023 14:40:13 +0100 Subject: [PATCH] implements #21620: allowing to import multiple modules with shared names (#21628) (cherry picked from commit c136ebf1ed0812f019895acc5aeeda8fde75ed00) --- compiler/importer.nim | 6 ++++++ compiler/lookups.nim | 21 +++++++++++++-------- compiler/semdata.nim | 1 + tests/import/t21496.nim | 2 +- 4 files changed, 21 insertions(+), 9 deletions(-) diff --git a/compiler/importer.nim b/compiler/importer.nim index 79d68e2a3f..de50ac5aa9 100644 --- a/compiler/importer.nim +++ b/compiler/importer.nim @@ -225,6 +225,11 @@ proc importForwarded(c: PContext, n: PNode, exceptSet: IntSet; fromMod: PSym; im for i in 0..n.safeLen-1: importForwarded(c, n[i], exceptSet, fromMod, importSet) +proc addUnique[T](x: var seq[T], y: sink T) {.noSideEffect.} = + for i in 0..high(x): + if x[i] == y: return + x.add y + proc importModuleAs(c: PContext; n: PNode, realModule: PSym, importHidden: bool): PSym = result = realModule template createModuleAliasImpl(ident): untyped = @@ -242,6 +247,7 @@ proc importModuleAs(c: PContext; n: PNode, realModule: PSym, importHidden: bool) result.options.incl optImportHidden c.unusedImports.add((result, n.info)) c.importModuleMap[result.id] = realModule.id + c.importModuleLookup.mgetOrPut(realModule.name.id, @[]).addUnique realModule.id proc transformImportAs(c: PContext; n: PNode): tuple[node: PNode, importHidden: bool] = var ret: typeof(result) diff --git a/compiler/lookups.nim b/compiler/lookups.nim index 0ab3f5aed3..9e6da157d6 100644 --- a/compiler/lookups.nim +++ b/compiler/lookups.nim @@ -8,7 +8,7 @@ # # This module implements lookup helpers. -import std/[algorithm, strutils] +import std/[algorithm, strutils, tables] import intsets, ast, astalgo, idents, semdata, types, msgs, options, renderer, nimfix/prettybase, lineinfos, modulegraphs, astmsgs @@ -311,14 +311,15 @@ proc wrongRedefinition*(c: PContext; info: TLineInfo, s: string; proc addDeclAt*(c: PContext; scope: PScope, sym: PSym, info: TLineInfo) = let conflict = scope.addUniqueSym(sym) if conflict != nil: - if sym.kind == skModule and conflict.kind == skModule and - sym.position == conflict.position: + if sym.kind == skModule and conflict.kind == skModule: # e.g.: import foo; import foo # xxx we could refine this by issuing a different hint for the case - # where a duplicate import happens inside an include. - localError(c.config, info, hintDuplicateModuleImport, - "duplicate import of '$1'; previous import here: $2" % - [sym.name.s, c.config $ conflict.info]) + # where a duplicate import happens inside an include. + if c.importModuleMap[sym.id] == c.importModuleMap[conflict.id]: + #only hints if the conflict is the actual module not just a shared name + localError(c.config, info, hintDuplicateModuleImport, + "duplicate import of '$1'; previous import here: $2" % + [sym.name.s, c.config $ conflict.info]) else: wrongRedefinition(c, info, sym.name.s, conflict.info, errGenerated) @@ -594,7 +595,11 @@ proc qualifiedLookUp*(c: PContext, n: PNode, flags: set[TLookupFlag]): PSym = if m == c.module: result = strTableGet(c.topLevelScope.symbols, ident).skipAlias(n, c.config) else: - result = someSym(c.graph, m, ident).skipAlias(n, c.config) + if c.importModuleLookup.getOrDefault(m.name.id).len > 1: + var amb: bool + result = errorUseQualifier(c, n.info, m, amb) + else: + result = someSym(c.graph, m, ident).skipAlias(n, c.config) if result == nil and checkUndeclared in flags: result = errorUndeclaredIdentifierHint(c, n[1], ident) elif n[1].kind == nkSym: diff --git a/compiler/semdata.nim b/compiler/semdata.nim index 5e317612d9..a5f0ca90a4 100644 --- a/compiler/semdata.nim +++ b/compiler/semdata.nim @@ -162,6 +162,7 @@ type lastTLineInfo*: TLineInfo sideEffects*: Table[int, seq[(TLineInfo, PSym)]] # symbol.id index inUncheckedAssignSection*: int + importModuleLookup*: Table[int, seq[int]] # (module.ident.id, [module.id]) template config*(c: PContext): ConfigRef = c.graph.config diff --git a/tests/import/t21496.nim b/tests/import/t21496.nim index 568f2ac515..b49d830b0e 100644 --- a/tests/import/t21496.nim +++ b/tests/import/t21496.nim @@ -1,5 +1,5 @@ discard """ - errormsg: "redefinition of 'm21496'; previous declaration here: t21496.nim(5, 12)" + errormsg: "ambiguous identifier: 'm21496'" """ import fizz/m21496, buzz/m21496