diff options
author | metagn <metagngn@gmail.com> | 2022-10-01 14:30:23 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-10-01 13:30:23 +0200 |
commit | cfff454cf9852be9df2020c3a2d192caaa2f418a (patch) | |
tree | fa22a0b1a8cb255b2ac239c6f417d5487e11a0c6 /compiler | |
parent | 24b81e9df6d871bd036d5e38efe631489999a4b7 (diff) | |
download | Nim-cfff454cf9852be9df2020c3a2d192caaa2f418a.tar.gz |
closed ambiguous enum defaults to first overload (#20457)
* closed ambiguous enum defaults to first overload * add warning * turn to hint * work around config
Diffstat (limited to 'compiler')
-rw-r--r-- | compiler/condsyms.nim | 1 | ||||
-rw-r--r-- | compiler/lineinfos.nim | 2 | ||||
-rw-r--r-- | compiler/semexprs.nim | 8 | ||||
-rw-r--r-- | compiler/semstmts.nim | 14 | ||||
-rw-r--r-- | compiler/semtypes.nim | 4 |
5 files changed, 23 insertions, 6 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) |