Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

nonpure enum can hijack pure enum; instead should give Error: ambiguous identifier ; pure and nonpure should both mean the same thing; pure should be deprecated #8850

Open
2 tasks
timotheecour opened this issue Sep 3, 2018 · 9 comments

Comments

@timotheecour
Copy link
Member

timotheecour commented Sep 3, 2018

ccing ppl from related discussion
/cc @Araq @dom96 @PMunch @mratsim

silent hijacking is bad.

now that 2f7b979 was committed, I think we should do the following (see rationale below)

  • P1: nonpure enum clashing with pure enum should give Error: ambiguous identifier instead of hijacking it; see example below
  • P2: pure and nonpure should both mean the same thing (requires P2a, see below)
  • P3: pure should be deprecated (would become a noop under this proposal)

see #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

rationale:

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)

P2a: things to resolve before merging pure and impure

  • impure allows UFCS: 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))
  • impure disallows 2 enums with a member clash; pure allows it

I suggest following pure's rules in all cases

note

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

links

Pure really removed for enums? - Nim forum

@Araq
Copy link
Member

Araq commented Sep 3, 2018

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.

@Araq
Copy link
Member

Araq commented Sep 3, 2018

imagine following scenario...

These scenarios can always be conjectured and are not convincing. If they were, we wouldn't embrace overloading to begin with.

@PMunch
Copy link
Contributor

PMunch commented Sep 3, 2018

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..

@Araq
Copy link
Member

Araq commented Sep 3, 2018

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.

@timotheecour
Copy link
Member Author

timotheecour commented Sep 3, 2018

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)

@timotheecour
Copy link
Member Author

timotheecour commented Sep 29, 2018

@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 2f7b979), 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)

@Araq
Copy link
Member

Araq commented Sep 29, 2018

I can confirm that's what will be done.

@timotheecour
Copy link
Member Author

timotheecour commented Jan 30, 2019

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 (b2a5195); 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

@stale
Copy link

stale bot commented Aug 4, 2020

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.

@stale stale bot added the stale Staled PR/issues; remove the label after fixing them label Aug 4, 2020
@metagn metagn removed the stale Staled PR/issues; remove the label after fixing them label Sep 18, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants