From ee2b480da629f23ced29a244ca706e4dd650f235 Mon Sep 17 00:00:00 2001 From: ringabout <43030857+ringabout@users.noreply.github.com> Date: Fri, 19 Sep 2025 02:50:46 +0800 Subject: [PATCH] makes `DuplicateModuleImport` back to an error (#25178) fixes #24998 Basically it retraces back to the situation before https://github.com/nim-lang/Nim/pull/18366 and https://github.com/nim-lang/Nim/pull/18362, i.e. ```nim import fuzz/a import fuzz/a ``` ```nim import fuzz/a from buzz/a ``` ```nim import fuzz/a except nil from fuzz/a import addInt ``` All of these cases are now flagged as invalid and triggers a redefinition error, i.e., each module name importing is treated as consistent as the symbol definition kinda annoying for importing/exporting with `when conditions` though ref https://github.com/nim-lang/Nim/issues/18762 https://github.com/nim-lang/Nim/issues/20907 ```nim from std/strutils import toLower when not defined(js): from std/strutils import toUpper ``` (cherry picked from commit 87ee9c84cb8cba3a404af235755c80037aefea6b) --- changelog.md | 2 ++ compiler/condsyms.nim | 2 ++ compiler/lookups.nim | 2 +- compiler/nim.cfg | 2 ++ compiler/suggest.nim | 2 +- lib/pure/terminal.nim | 7 +------ lib/system/alloc.nim | 1 - lib/system/strmantle.nim | 4 +--- 8 files changed, 10 insertions(+), 12 deletions(-) diff --git a/changelog.md b/changelog.md index cf2d4cb170..959f105669 100644 --- a/changelog.md +++ b/changelog.md @@ -25,6 +25,8 @@ errors. - `std/parsesql` has been moved to a nimble package, use `nimble` or `atlas` to install it. +- With `-d:nimPreviewDuplicateModuleError`, importing two modules that share the same name becomes a compile-time error. This includes importing the same module more than once. Use `import foo as foo1` (or other aliases) to avoid collisions. + ## Standard library additions and changes [//]: # "Additions:" diff --git a/compiler/condsyms.nim b/compiler/condsyms.nim index 81cc40f3f6..8bfcb2dac8 100644 --- a/compiler/condsyms.nim +++ b/compiler/condsyms.nim @@ -171,3 +171,5 @@ proc initDefines*(symbols: StringTableRef) = defineSymbol("nimHasJsNoLambdaLifting") defineSymbol("nimHasDefaultFloatRoundtrip") defineSymbol("nimHasXorSet") + + defineSymbol("nimHasPreviewDuplicateModuleError") diff --git a/compiler/lookups.nim b/compiler/lookups.nim index 34f65973cf..acaad9d9b4 100644 --- a/compiler/lookups.nim +++ b/compiler/lookups.nim @@ -388,7 +388,7 @@ proc addDeclAt*(c: PContext; scope: PScope, sym: PSym, info: TLineInfo) = if sym.name.id == ord(wUnderscore): return let conflict = scope.addUniqueSym(sym) if conflict != nil: - if sym.kind == skModule and conflict.kind == skModule: + if sym.kind == skModule and conflict.kind == skModule and not c.config.isDefined("nimPreviewDuplicateModuleError"): # 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. diff --git a/compiler/nim.cfg b/compiler/nim.cfg index 0cc8c476ec..9dab29eeed 100644 --- a/compiler/nim.cfg +++ b/compiler/nim.cfg @@ -12,6 +12,8 @@ define:nimPreviewNonVarDestructor define:nimPreviewCheckedClose define:nimPreviewAsmSemSymbol define:nimPreviewCStringComparisons +define:nimPreviewDuplicateModuleError + threads:off #import:"$projectpath/testability" diff --git a/compiler/suggest.nim b/compiler/suggest.nim index 1317fb2e48..3953936eb6 100644 --- a/compiler/suggest.nim +++ b/compiler/suggest.nim @@ -35,7 +35,7 @@ import prefixmatches, suggestsymdb from wordrecg import wDeprecated, wError, wAddr, wYield -import std/[algorithm, sets, parseutils, tables, os] +import std/[algorithm, sets, parseutils, os] when defined(nimsuggest): import pathutils # importer diff --git a/lib/pure/terminal.nim b/lib/pure/terminal.nim index 91f0910585..895f658e4d 100644 --- a/lib/pure/terminal.nim +++ b/lib/pure/terminal.nim @@ -100,7 +100,7 @@ const stylePrefix = "\e[" when defined(windows): - import std/[winlean, os] + import std/os const DUPLICATE_SAME_ACCESS = 2 @@ -926,8 +926,6 @@ when defined(windows): stdout.write "\n" else: - import std/termios - proc readPasswordFromStdin*(prompt: string, password: var string): bool {.tags: [ReadIOEffect, WriteIOEffect].} = password.setLen(0) @@ -981,9 +979,6 @@ proc isTrueColorSupported*(): bool = ## Returns true if a terminal supports true color. return getTerminal().trueColorIsSupported -when defined(windows): - import std/os - proc enableTrueColors*() = ## Enables true color. var term = getTerminal() diff --git a/lib/system/alloc.nim b/lib/system/alloc.nim index 63a0970536..fcb7ccb0c8 100644 --- a/lib/system/alloc.nim +++ b/lib/system/alloc.nim @@ -12,7 +12,6 @@ include osalloc import std/private/syslocks -import std/sysatomics template track(op, address, size) = when defined(memTracker): diff --git a/lib/system/strmantle.nim b/lib/system/strmantle.nim index 694ef64257..92a8653f2a 100644 --- a/lib/system/strmantle.nim +++ b/lib/system/strmantle.nim @@ -8,9 +8,7 @@ # # Compilerprocs for strings that do not depend on the string implementation. - -import std/private/digitsutils - +import std/private/digitsutils as digitsutils2 proc cmpStrings(a, b: string): int {.inline, compilerproc.} = let alen = a.len