Skip to content

Commit

Permalink
always lookup pure enum symbols if expected type is enum (#23976)
Browse files Browse the repository at this point in the history
fixes #23689

Normally pure enum symbols only "exist" in lookup if nothing else with
the same name is in scope. But if an expression is expected to be an
enum type, we know that ambiguity can be resolved between different
symbols based on their type, so we can include the normally inaccessible
pure enum fields in the ambiguity resolution in the case that the
expected enum type is actually a pure enum. This handles the use case in
the issue of the type inference for enums reverted in #23588.

I know pure enums are supposed to be on their way out so this might seem
excessive, but the `pure` pragma can't be removed in the code in the
issue due to a redefinition error, they have to be separated into
different modules. Normal enums can still resolve the ambiguity here
though. I always think about making a list of all the remaining use
cases for pure enums and I always forget.

Will close #23694 if CI passes
  • Loading branch information
metagn authored Aug 17, 2024
1 parent 0ffc049 commit a354b18
Show file tree
Hide file tree
Showing 3 changed files with 20 additions and 3 deletions.
5 changes: 3 additions & 2 deletions compiler/lookups.nim
Original file line number Diff line number Diff line change
Expand Up @@ -632,9 +632,10 @@ type

const allExceptModule = {low(TSymKind)..high(TSymKind)} - {skModule, skPackage}

proc lookUpCandidates*(c: PContext, ident: PIdent, filter: set[TSymKind]): seq[PSym] =
proc lookUpCandidates*(c: PContext, ident: PIdent, filter: set[TSymKind],
includePureEnum = false): seq[PSym] =
result = searchInScopesFilterBy(c, ident, filter)
if result.len == 0:
if skEnumField in filter and (result.len == 0 or includePureEnum):
result.add allPureEnumFields(c, ident)

proc qualifiedLookUp*(c: PContext, n: PNode, flags: set[TLookupFlag]): PSym =
Expand Down
5 changes: 4 additions & 1 deletion compiler/semexprs.nim
Original file line number Diff line number Diff line change
Expand Up @@ -3107,7 +3107,10 @@ proc resolveIdentToSym(c: PContext, n: PNode, resultNode: var PNode,
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)
let includePureEnum = expectedType != nil and
expectedType.skipTypes(abstractRange-{tyDistinct}).kind == tyEnum
let candidates = lookUpCandidates(c, ident, filter,
includePureEnum = includePureEnum)
if candidates.len == 0:
result = errorUndeclaredIdentifierHint(c, ident, n.info)
elif candidates.len == 1 or {efNoEvaluateGeneric, efInCall} * flags != {}:
Expand Down
13 changes: 13 additions & 0 deletions tests/enum/ttypenameconflict.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# issue #23689

type
MyEnum {.pure.} = enum
A, B, C, D

B = object
field: int

let x: MyEnum = B
doAssert $x == "B"
doAssert typeof(x) is MyEnum
doAssert x in {A, B}

0 comments on commit a354b18

Please sign in to comment.