summary refs log tree commit diff stats
diff options
context:
space:
mode:
authormetagn <metagngn@gmail.com>2024-05-14 12:26:33 +0300
committerGitHub <noreply@github.com>2024-05-14 11:26:33 +0200
commit81a937ce1f23e443a2b60375a0961bafa5b8bd06 (patch)
tree82fcf2cc1028d5d4cd0a430412c34bf03381b62d
parentc91b33aaba4234d8abdf04af102d71b86e285c58 (diff)
downloadNim-81a937ce1f23e443a2b60375a0961bafa5b8bd06.tar.gz
ignore modules when looking up symbol with expected type (#23597)
fixes #23596

When importing a module and declaring an overloadable symbol with the
same name as the module in the same scope, the module symbol can take
over and make the declared overload impossible to access. Previously
enum overloading had a quirk that bypassed this in a context where a
specific enum type was expected but this was removed in #23588. Now this
is bypassed in every place where a specific type is expected since
module symbols don't have a type and so wouldn't be compatible anyway.

But the issue still exists in places where no type is expected like `let
x = modulename`. I don't see a way of fixing this without nerfing module
symbols to the point where they're not accessible by default, which
might break some macro code.
-rw-r--r--compiler/semexprs.nim2
-rw-r--r--tests/lookups/tmoduleclash1.nim13
-rw-r--r--tests/lookups/tmoduleclash2.nim6
3 files changed, 20 insertions, 1 deletions
diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim
index 6893f7287..8fcf5936e 100644
--- a/compiler/semexprs.nim
+++ b/compiler/semexprs.nim
@@ -3029,7 +3029,7 @@ proc resolveIdentToSym(c: PContext, n: PNode, resultNode: var PNode,
   # result is nil on error or if a node that can't produce a sym is resolved
   let ident = considerQuotedIdent(c, n)
   var filter = {low(TSymKind)..high(TSymKind)}
-  if efNoEvaluateGeneric in flags:
+  if efNoEvaluateGeneric in flags or expectedType != nil:
     # `a[...]` where `a` is a module or package is not possible
     filter.excl {skModule, skPackage}
   let candidates = lookUpCandidates(c, ident, filter)
diff --git a/tests/lookups/tmoduleclash1.nim b/tests/lookups/tmoduleclash1.nim
new file mode 100644
index 000000000..7058f691e
--- /dev/null
+++ b/tests/lookups/tmoduleclash1.nim
@@ -0,0 +1,13 @@
+# issue #23596
+
+import std/heapqueue
+type Algo = enum heapqueue, quick
+when false:
+  let x = heapqueue
+let y: Algo = heapqueue
+proc bar*(algo=quick) =
+  var x: HeapQueue[int]
+  case algo
+  of heapqueue: echo 1 # `Algo.heapqueue` works on devel
+  of quick: echo 2
+  echo x.len
diff --git a/tests/lookups/tmoduleclash2.nim b/tests/lookups/tmoduleclash2.nim
new file mode 100644
index 000000000..958da2299
--- /dev/null
+++ b/tests/lookups/tmoduleclash2.nim
@@ -0,0 +1,6 @@
+import std/heapqueue
+proc heapqueue(x: int) = discard
+let x: proc (x: int) = heapqueue
+let y: proc = heapqueue
+when false:
+  let z = heapqueue