Skip to content

Commit

Permalink
fixes #8066
Browse files Browse the repository at this point in the history
  • Loading branch information
Araq committed Aug 30, 2018
1 parent fab4498 commit 2f7b979
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 10 deletions.
10 changes: 8 additions & 2 deletions compiler/importer.nim
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,15 @@ proc readExceptSet*(c: PContext, n: PNode): IntSet =
result.incl(ident.id)

proc importPureEnumField*(c: PContext; s: PSym) =
var check = strTableGet(c.importTable.symbols, s.name)
let check = strTableGet(c.importTable.symbols, s.name)
if check == nil:
strTableAdd(c.pureEnumFields, s)
let checkB = strTableGet(c.pureEnumFields, s.name)
if checkB == nil:
strTableAdd(c.pureEnumFields, s)
else:
# mark as ambigous:
incl(c.ambiguousSymbols, checkB.id)
incl(c.ambiguousSymbols, s.id)

proc rawImportSymbol(c: PContext, s: PSym) =
# This does not handle stubs, because otherwise loading on demand would be
Expand Down
2 changes: 1 addition & 1 deletion compiler/lookups.nim
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,7 @@ else:
template fixSpelling(n: PNode; ident: PIdent; op: untyped) = discard

proc errorUseQualifier*(c: PContext; info: TLineInfo; s: PSym) =
var err = "Error: ambiguous identifier: '" & s.name.s & "'"
var err = "ambiguous identifier: '" & s.name.s & "'"
var ti: TIdentIter
var candidate = initIdentIter(ti, c.importTable.symbols, s.name)
var i = 0
Expand Down
25 changes: 18 additions & 7 deletions doc/manual.rst
Original file line number Diff line number Diff line change
Expand Up @@ -937,8 +937,12 @@ Now the following holds::
ord(south) == 2
ord(west) == 3

# Also allowed:
ord(Direction.west) == 3

Thus, north < east < south < west. The comparison operators can be used
with enumeration types.
with enumeration types. Instead of ``north`` etc, the enum value can also
be qualified with the enum type that it resides in, ``Direction.north``.

For better interfacing to other programming languages, the fields of enum
types can be assigned an explicit ordinal value. However, the ordinal values
Expand Down Expand Up @@ -974,18 +978,25 @@ As can be seen from the example, it is possible to both specify a field's
ordinal value and its string value by using a tuple. It is also
possible to only specify one of them.

An enum can be marked with the ``pure`` pragma so that it's fields are not
added to the current scope, so they always need to be accessed
via ``MyEnum.value``:
An enum can be marked with the ``pure`` pragma so that it's fields are
added to a special module specific hidden scope that is only queried
as the last attempt. Only non-ambiguous symbols are added to this scope.
But one can always access these via type qualification written
as ``MyEnum.value``:

.. code-block:: nim
type
MyEnum {.pure.} = enum
valueA, valueB, valueC, valueD
valueA, valueB, valueC, valueD, amb
OtherEnum {.pure.} = enum
valueX, valueY, valueZ, amb
echo valueA # error: Unknown identifier
echo MyEnum.valueA # works
echo valueA # MyEnum.valueA
echo amb # Error: Unclear whether it's MyEnum.amb or OtherEnum.amb
echo MyEnum.amb # OK.
String type
Expand Down
19 changes: 19 additions & 0 deletions tests/enum/tpure_enums_conflict.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
discard """
errormsg: "ambiguous identifier: 'amb'"
line: 19
"""

# bug #8066

when true:
type
MyEnum {.pure.} = enum
valueA, valueB, valueC, valueD, amb

OtherEnum {.pure.} = enum
valueX, valueY, valueZ, amb


echo valueA # MyEnum.valueA
echo MyEnum.amb # OK.
echo amb # Error: Unclear whether it's MyEnum.amb or OtherEnum.amb

0 comments on commit 2f7b979

Please sign in to comment.