ccing ppl from related discussion
/cc @Araq @dom96 @PMunch @mratsim
silent hijacking is bad.
now that https://github.com/nim-lang/Nim/commit/2f7b979e384ff6cc750e123939401a72c3f59093 was committed, I think we should do the following (see rationale below)
Error: ambiguous identifier instead of hijacking it; see example belowsee https://github.com/nim-lang/Nim/issues/8066 for related discussion
when defined(case5):
import typetraits
type
X {.pure.} = enum
blue
red
magenta
Y = enum
blue
orange
red
echo int(red) # prints 2 (not 1, nonpure takes over currently) but should give ambiguity error as in https://github.com/nim-lang/Nim/commit/2f7b979e384ff6cc750e123939401a72c3f59093
imagine following scenario:
# thirdpartylib1.nim:
type
X* {.pure.} = enum
blue
red
magenta
# thirdpartylib2.nim:
# nothing yet
# myapp.nim:
import thirdpartylib1
import thirdpartylib2
call_c_library(int(red)) # call_c_library(1)
later thirdpartylib2.nim gets udpated as follows:
type
Y* = enum
blue
orange
red
Now call_c_library(int(red)) calls call_c_library(2)
this can lead to nasty bugs under the nose of application writer.
Instead the only sane way here is to give compile error: Error: ambiguous identifier (P1)
Which leads to P2 and P3 since now pure and impure would mean the same thing, modulo nit below (which shouldn't be relevant enough to warrant having 2 concepts)
int.red , pure doesn't unless the symbol is qualified: X.red.int or int(red) ; if we are to do P2 and P3, I'm fine with either rule (allow or disallow UFCS without qualification (when unambigious))I suggest following pure's rules in all cases
that seems in line with https://irclogs.nim-lang.org/22-10-2017.html#13:54:23
14:05:21 | Araq | well the point is to remove the whole distinction between the two enum types
echo int(red) # prints 2 (not 1, nonpure takes over currently) but should give ambiguity error
No, it works as expected and documented. It's true that I want to merge pure and non-pure enums though, eventually.
imagine following scenario...
These scenarios can always be conjectured and are not convincing. If they were, we wouldn't embrace overloading to begin with.
That isn't a very obscure scenario though.. I'd imagine a lot of people using enums this way, and any module that happens to use the same value for an enum would break that.. I'm still for bringing pure enums back, can't really see a reason to remove them..
Once we merged pure with non-pure enums completely the scenario is gone. And yes, call_c_library(int(red)) is a completely contrived example.
These scenarios can always be conjectured and are not convincing. If they were, we wouldn't embrace overloading to begin with.
with overloading you'd get compile error: ambiguous call: foo matches both foo(...) and foo(...) ; the case where it'd change meaning are more contrived: eg when thirdpartylib1 removes a foo overload and thirdpartylib2 adds a foo overload, for example.
And yes, call_c_library(int(red)) is a completely contrived example.
I don't think this is contrived, I just gave a simple example. This arises in many other scenarios, that silently give different results instead of compile error:
echo red
foo(red) # where `foo` is generic (and itself calls thing that accept either form of `red`)
$red
int(red)
type(red).name
type(red).sizeof
...
Once we merged pure with non-pure enums completely the scenario is gone.
great, then let's keep this issue open to track this :) ; so looks like we agree on P1,P2,P3
before merging pure and impure enum we need to resolve how they work in other aspects; see P2a: things to resolve before merging pure and impure (I just updated that paragraph)
@araq confirmed on gitter https://gitter.im/nim-lang/Nim?at=5bafb1e019b139275a1de6ac that
nonpure enum will be changed to behave as current pure enum (with pure's new meaning introduced since https://github.com/nim-lang/Nim/commit/2f7b979e384ff6cc750e123939401a72c3f59093), which allows both Foo.red and red wherever un-ambiguous), making {.pure.} both the new default and a no-op; this would therefore close this issue since "nonpure enum can hijack pure enum" won't happen after that.
(please correct me if I mis-understood)
I can confirm that's what will be done.
EDIT: i read somewhere (sorry, forgot whether it was in IRC or forum or github) that pure is now a no-op (ie implicit), however that's still not the case in latest devel (b2a5195e92f8852a47ca70136b103bc374b73393); pure and non pure still have different semantics
eg1:
type Goo = enum
goo0,
goo1,
type Foo {.pure.} = enum
foo0,
foo1,
proc main()=
echo goo0.int
# echo foo0.int # Error: undeclared identifier: 'foo0'
echo int(foo0)
eg2:
same hijicking issue as mentioned in top post
This issue has been automatically marked as stale because it has not had recent activity. If you think it is still a valid issue, write a comment below; otherwise it will be closed. Thank you for your contributions.
Most helpful comment
I can confirm that's what will be done.