summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--compiler/lookups.nim35
-rw-r--r--compiler/semexprs.nim5
-rw-r--r--tests/enum/tambiguousoverloads.nim26
-rw-r--r--tests/enum/toverloadable_enums.nim8
-rw-r--r--tests/lookups/tambsym3.nim7
5 files changed, 67 insertions, 14 deletions
diff --git a/compiler/lookups.nim b/compiler/lookups.nim
index 3cf759981..90f9a9b2b 100644
--- a/compiler/lookups.nim
+++ b/compiler/lookups.nim
@@ -254,6 +254,41 @@ proc searchInScopesFilterBy*(c: PContext, s: PIdent, filter: TSymKinds): seq[PSy
         if s.kind in filter:
           result.add s
 
+proc isAmbiguous*(c: PContext, s: PIdent, filter: TSymKinds, sym: var PSym): bool =
+  result = false
+  block outer:
+    for scope in allScopes(c.currentScope):
+      var ti: TIdentIter
+      var candidate = initIdentIter(ti, scope.symbols, s)
+      var scopeHasCandidate = false
+      while candidate != nil:
+        if candidate.kind in filter:
+          if scopeHasCandidate:
+            # 2 candidates in same scope, ambiguous
+            return true
+          else:
+            scopeHasCandidate = true
+            sym = candidate
+        candidate = nextIdentIter(ti, scope.symbols)
+      if scopeHasCandidate:
+        # scope had a candidate but wasn't ambiguous
+        return false
+
+  var importsHaveCandidate = false
+  var marked = initIntSet()
+  for im in c.imports.mitems:
+    for s in symbols(im, marked, s, c.graph):
+      if s.kind in filter:
+        if importsHaveCandidate:
+          # 2 candidates among imports, ambiguous
+          return true
+        else:
+          importsHaveCandidate = true
+          sym = s
+  if importsHaveCandidate:
+    # imports had a candidate but wasn't ambiguous
+    return false
+
 proc errorSym*(c: PContext, n: PNode): PSym =
   ## creates an error symbol to avoid cascading errors (for IDE support)
   var m = n
diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim
index e9f90dcc0..001ce958a 100644
--- a/compiler/semexprs.nim
+++ b/compiler/semexprs.nim
@@ -92,7 +92,10 @@ proc semExprCheck(c: PContext, n: PNode, flags: TExprFlags, expectedType: PType
 
 proc ambiguousSymChoice(c: PContext, orig, n: PNode): PNode =
   let first = n[0].sym
-  if first.kind == skEnumField:
+  var foundSym: PSym = nil
+  if first.kind == skEnumField and
+      not isAmbiguous(c, first.name, {skEnumField}, foundSym) and
+      foundSym == first:
     # choose the first resolved enum field, i.e. the latest in scope
     # to mirror behavior before overloadable enums
     if hintAmbiguousEnum in c.config.notes:
diff --git a/tests/enum/tambiguousoverloads.nim b/tests/enum/tambiguousoverloads.nim
new file mode 100644
index 000000000..1b0d92608
--- /dev/null
+++ b/tests/enum/tambiguousoverloads.nim
@@ -0,0 +1,26 @@
+discard """
+cmd: "nim check --hints:off $file"
+"""
+
+block: # bug #21887
+  type
+    EnumA = enum A = 300, B
+    EnumB = enum A = 10
+    EnumC = enum C
+
+  doAssert typeof(EnumC(A)) is EnumC #[tt.Error
+                       ^ ambiguous identifier 'A' -- use one of the following:
+  EnumA.A: EnumA
+  EnumB.A: EnumB]#
+
+block: # issue #22598
+  type
+    A = enum
+      red
+    B = enum
+      red
+
+  let a = red #[tt.Error
+          ^ ambiguous identifier 'red' -- use one of the following:
+  A.red: A
+  B.red: B]#
diff --git a/tests/enum/toverloadable_enums.nim b/tests/enum/toverloadable_enums.nim
index 5fdcb1823..9bb551467 100644
--- a/tests/enum/toverloadable_enums.nim
+++ b/tests/enum/toverloadable_enums.nim
@@ -118,11 +118,3 @@ block: # test with macros/templates
   doAssert isOneMS(e2)
   doAssert isOneT(e1)
   doAssert isOneT(e2)
-
-block: # bug #21908
-  type
-    EnumA = enum A = 300, B
-    EnumB = enum A = 10
-    EnumC = enum C
-
-  doAssert typeof(EnumC(A)) is EnumC
diff --git a/tests/lookups/tambsym3.nim b/tests/lookups/tambsym3.nim
index e50f9c461..6e7589cd8 100644
--- a/tests/lookups/tambsym3.nim
+++ b/tests/lookups/tambsym3.nim
@@ -1,15 +1,12 @@
 discard """
-  errormsg: "ambiguous enum field"
+  errormsg: "ambiguous identifier 'mDec' -- use one of the following:"
   file: "tambsym3.nim"
-  line: 14
+  line: 11
 """
 # Test ambiguous symbols
 
 import mambsym1, times
 
-{.hint[AmbiguousEnum]: on.}
-{.hintAsError[AmbiguousEnum]: on.}
-
 var
   v = mDec #ERROR_MSG ambiguous identifier