summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--compiler/condsyms.nim1
-rw-r--r--compiler/lineinfos.nim2
-rw-r--r--compiler/semexprs.nim8
-rw-r--r--compiler/semstmts.nim14
-rw-r--r--compiler/semtypes.nim4
-rw-r--r--config/nim.cfg4
-rw-r--r--tests/ambsym/tambsym3.nim7
-rw-r--r--tests/enum/tcrossmodule.nim5
8 files changed, 37 insertions, 8 deletions
diff --git a/compiler/condsyms.nim b/compiler/condsyms.nim
index 332a802ab..10f4b86ab 100644
--- a/compiler/condsyms.nim
+++ b/compiler/condsyms.nim
@@ -143,3 +143,4 @@ proc initDefines*(symbols: StringTableRef) =
   defineSymbol("nimHasTopDownInference")
   defineSymbol("nimHasTemplateRedefinitionPragma")
   defineSymbol("nimHasCstringCase")
+  defineSymbol("nimHasAmbiguousEnumHint")
diff --git a/compiler/lineinfos.nim b/compiler/lineinfos.nim
index ec1643960..05f4eba5a 100644
--- a/compiler/lineinfos.nim
+++ b/compiler/lineinfos.nim
@@ -96,6 +96,7 @@ type
     hintPattern = "Pattern", hintExecuting = "Exec", hintLinking = "Link", hintDependency = "Dependency",
     hintSource = "Source", hintPerformance = "Performance", hintStackTrace = "StackTrace",
     hintGCStats = "GCStats", hintGlobalVar = "GlobalVar", hintExpandMacro = "ExpandMacro",
+    hintAmbiguousEnum = "AmbiguousEnum",
     hintUser = "User", hintUserRaw = "UserRaw", hintExtendedContext = "ExtendedContext",
     hintMsgOrigin = "MsgOrigin", # since 1.3.5
     hintDeclaredLoc = "DeclaredLoc", # since 1.5.1
@@ -209,6 +210,7 @@ const
     hintGCStats: "$1",
     hintGlobalVar: "global variable declared here",
     hintExpandMacro: "expanded macro: $1",
+    hintAmbiguousEnum: "$1",
     hintUser: "$1",
     hintUserRaw: "$1",
     hintExtendedContext: "$1",
diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim
index a0753010a..0c6500408 100644
--- a/compiler/semexprs.nim
+++ b/compiler/semexprs.nim
@@ -87,6 +87,14 @@ proc semExprWithType(c: PContext, n: PNode, flags: TExprFlags = {}, expectedType
   result = semExprCheck(c, n, flags, expectedType)
   if result.typ == nil and efInTypeof in flags:
     result.typ = c.voidType
+  elif (result.typ == nil or result.typ.kind == tyNone) and
+      result.kind == nkClosedSymChoice and
+      result[0].sym.kind == skEnumField:
+    # if overloaded enum field could not choose a type from a closed list,
+    # choose the first resolved enum field, i.e. the latest in scope
+    # to mirror old behavior
+    msgSymChoiceUseQualifier(c, result, hintAmbiguousEnum)
+    result = result[0]
   elif result.typ == nil or result.typ == c.enforceVoidContext:
     localError(c.config, n.info, errExprXHasNoType %
                 renderTree(result, {renderNoComments}))
diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim
index 1b98f5c1a..4f01f508e 100644
--- a/compiler/semstmts.nim
+++ b/compiler/semstmts.nim
@@ -574,9 +574,13 @@ proc semVarMacroPragma(c: PContext, a: PNode, n: PNode): PNode =
                 pragma(c, defs[lhsPos][namePos].sym, defs[lhsPos][pragmaPos], validPragmas)
         return result
 
-proc errorSymChoiceUseQualifier(c: PContext; n: PNode) =
+proc msgSymChoiceUseQualifier(c: PContext; n: PNode; note = errGenerated) =
   assert n.kind in nkSymChoices
-  var err = "ambiguous identifier: '" & $n[0] & "'"
+  var err =
+    if note == hintAmbiguousEnum:
+      "ambiguous enum field '$1' assumed to be of type $2, this will become an error in the future" % [$n[0], typeToString(n[0].typ)]
+    else:
+      "ambiguous identifier: '" & $n[0] & "'"
   var i = 0
   for child in n:
     let candidate = child.sym
@@ -584,7 +588,7 @@ proc errorSymChoiceUseQualifier(c: PContext; n: PNode) =
     else: err.add "\n"
     err.add "  " & candidate.owner.name.s & "." & candidate.name.s
     inc i
-  localError(c.config, n.info, errGenerated, err)
+  message(c.config, n.info, note, err)
 
 proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode =
   var b: PNode
@@ -611,8 +615,8 @@ proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode =
     if a[^1].kind != nkEmpty:
       def = semExprWithType(c, a[^1], {}, typ)
 
-      if def.kind in nkSymChoices and def[0].typ.skipTypes(abstractInst).kind == tyEnum:
-        errorSymChoiceUseQualifier(c, def)
+      if def.kind in nkSymChoices and def[0].sym.kind == skEnumField:
+        msgSymChoiceUseQualifier(c, def, errGenerated)
       elif def.kind == nkSym and def.sym.kind in {skTemplate, skMacro}:
         typFlags.incl taIsTemplateOrMacro
       elif def.typ.kind == tyTypeDesc and c.p.owner.kind != skMacro:
diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim
index 0a823f20a..d033d5f44 100644
--- a/compiler/semtypes.nim
+++ b/compiler/semtypes.nim
@@ -591,7 +591,9 @@ proc semCaseBranch(c: PContext, t, branch: PNode, branchIndex: int,
       branch[i] = semCaseBranchRange(c, t, b, covered)
     else:
       # constant sets and arrays are allowed:
-      var r = semConstExpr(c, b)
+      # set expected type to selector type for type inference
+      # even if it can be a different type like a set or array
+      var r = semConstExpr(c, b, expectedType = t[0].typ)
       if r.kind in {nkCurly, nkBracket} and r.len == 0 and branch.len == 2:
         # discarding ``{}`` and ``[]`` branches silently
         delSon(branch, 0)
diff --git a/config/nim.cfg b/config/nim.cfg
index 55b7a41c1..9f50a1f84 100644
--- a/config/nim.cfg
+++ b/config/nim.cfg
@@ -15,6 +15,10 @@ cc = gcc
 --parallel_build: "0" # 0 to auto-detect number of processors
 
 hint[LineTooLong]=off
+@if nimHasAmbiguousEnumHint:
+  # not needed if hint is a style check
+  hint[AmbiguousEnum]=off
+@end
 #hint[XDeclaredButNotUsed]=off
 
 threads:on
diff --git a/tests/ambsym/tambsym3.nim b/tests/ambsym/tambsym3.nim
index 0558517bd..e50f9c461 100644
--- a/tests/ambsym/tambsym3.nim
+++ b/tests/ambsym/tambsym3.nim
@@ -1,12 +1,15 @@
 discard """
-  errormsg: "ambiguous identifier"
+  errormsg: "ambiguous enum field"
   file: "tambsym3.nim"
-  line: 11
+  line: 14
 """
 # Test ambiguous symbols
 
 import mambsym1, times
 
+{.hint[AmbiguousEnum]: on.}
+{.hintAsError[AmbiguousEnum]: on.}
+
 var
   v = mDec #ERROR_MSG ambiguous identifier
 
diff --git a/tests/enum/tcrossmodule.nim b/tests/enum/tcrossmodule.nim
index 1e97fd1ee..c21072198 100644
--- a/tests/enum/tcrossmodule.nim
+++ b/tests/enum/tcrossmodule.nim
@@ -8,3 +8,8 @@ template t =
   doAssert some(Success)
 
 t()
+
+block: # legacy support for behavior before overloadableEnums
+  # warning: ambiguous enum field 'Success' assumed to be of type MyEnum
+  let x = {Success}
+  doAssert x is set[MyEnum]