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

Two different enum values with the same short name should "poison" the slot they're in, rather than refuse to merge global symbols in Rakudo #3641

Open
p6rt opened this issue Jan 11, 2015 · 3 comments
Labels
Bug

Comments

@p6rt
Copy link

@p6rt p6rt commented Jan 11, 2015

Migrated from rt.perl.org#123583 (status was 'open')

Searchable as RT123583$

@p6rt

This comment has been minimized.

Copy link
Author

@p6rt p6rt commented Jan 11, 2015

From @masak

<masak> here​: https://gist.github.com/masak/406d687c3e4e0684c013

Inlined here for your benefit​:

$ cat X.pm
enum X is export <A B>;
$ cat Y.pm
enum Y is export <B W>;
$ perl6 -I. -e 'use X; use Y'
===SORRY!===
Merging GLOBAL symbols failed​: duplicate definition of symbol B

<masak> by my reading of S12, this should work, but then you're not
allowed to refer to just `B`; you have to say `X​::B` or `Y​::B`.
<masak> (and if you also import a `sub B { ... }` from somewhere, it
takes precedence and "un-poisons" the slot for itself)
<moritz> that takes slot &B
<masak> no doubt -- but I'm talking about what happens when you write
`B` in code after that.
<masak> if the sub has been imported, that's a call to `&B`.
<moritz> that should resolve to &B, yes
* moritz skims S12
<masak> but if it hasn't, then it's still a compile-time error,
because it's not clear if you're referring to `X​::B` or `Y​::B`.
<moritz> Since there is an enum C<OK>, the function C<OK> may only be
<moritz> called using parentheses, never in list operator form.
<moritz> so you'd be able to call B() when the B slot is poisoned, but
not just 'B args', iiuc
<moritz> ah yes
<moritz> "If there is
<moritz> a collision on two enum values that cancels them both, the function
<moritz> still may only be called with parentheses, since the enum key
<moritz> is "poisoned"."
<masak> right.
<masak> that's the only reference to the concept of poisoning I've found.
<masak> it mentions the effect in passing, but it's pretty clear about it.
* masak submits rakudobug
<moritz> masak​: S12 doesn't talk about in which circumstances
poisoning, so I'd assume it happens everywhere
<moritz> so, also in importation/exportation
<masak> moritz​: ah, you mean between any two imported symbols?
<masak> moritz​: that's very possible.
<moritz> masak​: no
<masak> moritz​: but enum values are a bit special in that they're
essentially short-form aliases for their real unambiguous names.
<masak> moritz​: like, `True` is short for `Bool​::True`.
<moritz> yes
<moritz> masak​: I mean between two imported enum items vs. two
declared-here enum items
<masak> moritz​: oh, that's entirely possible, yes.
<masak> moritz​: though I could equally well argue that the
declared-here enum value takes precedence...
<moritz> with "everywhere" I meant "at declaration and at {ex,im}portation"
<masak> declaring something feels like much more of a "conscious act"
than importation.
<masak> like, you might not know you're importing a `B`, but you
definitely know you're declaring one!

To summarize​: the error message "Merging GLOBAL symbols failed​:
duplicate definition of symbol B" on importing Y.pm is wrong. That
should work without an error. Referring to `B` after that in code
should be a (compile-time) error, though. This is the "poisoning"
effect referred to by S12.

The rest of the discussion is pertinent, but doesn't figure in the
closability of this ticket.

@p6rt

This comment has been minimized.

Copy link
Author

@p6rt p6rt commented Dec 1, 2017

From @AlexDaniel

Still reproducible (2017.11, HEAD(5929887)), but with a slightly different error​:

===SORRY!=== Error while compiling -e
Cannot import the following symbols from X, because they already exist in this lexical scope​:  B, A
at -e​:1
------> use X⏏; use Y

On 2015-01-11 05​:44​:26, masak wrote​:

<masak> here​: https://gist.github.com/masak/406d687c3e4e0684c013

Inlined here for your benefit​:

$ cat X.pm
enum X is export <A B>;
$ cat Y.pm
enum Y is export <B W>;
$ perl6 -I. -e 'use X; use Y'
===SORRY!===
Merging GLOBAL symbols failed​: duplicate definition of symbol B

<masak> by my reading of S12, this should work, but then you're not
allowed to refer to just `B`; you have to say `X​::B` or `Y​::B`.
<masak> (and if you also import a `sub B { ... }` from somewhere, it
takes precedence and "un-poisons" the slot for itself)
<moritz> that takes slot &B
<masak> no doubt -- but I'm talking about what happens when you write
`B` in code after that.
<masak> if the sub has been imported, that's a call to `&B`.
<moritz> that should resolve to &B, yes
* moritz skims S12
<masak> but if it hasn't, then it's still a compile-time error,
because it's not clear if you're referring to `X​::B` or `Y​::B`.
<moritz> Since there is an enum C<OK>, the function C<OK> may only be
<moritz> called using parentheses, never in list operator form.
<moritz> so you'd be able to call B() when the B slot is poisoned, but
not just 'B args', iiuc
<moritz> ah yes
<moritz> "If there is
<moritz> a collision on two enum values that cancels them both, the function
<moritz> still may only be called with parentheses, since the enum key
<moritz> is "poisoned"."
<masak> right.
<masak> that's the only reference to the concept of poisoning I've found.
<masak> it mentions the effect in passing, but it's pretty clear about it.
* masak submits rakudobug
<moritz> masak​: S12 doesn't talk about in which circumstances
poisoning, so I'd assume it happens everywhere
<moritz> so, also in importation/exportation
<masak> moritz​: ah, you mean between any two imported symbols?
<masak> moritz​: that's very possible.
<moritz> masak​: no
<masak> moritz​: but enum values are a bit special in that they're
essentially short-form aliases for their real unambiguous names.
<masak> moritz​: like, `True` is short for `Bool​::True`.
<moritz> yes
<moritz> masak​: I mean between two imported enum items vs. two
declared-here enum items
<masak> moritz​: oh, that's entirely possible, yes.
<masak> moritz​: though I could equally well argue that the
declared-here enum value takes precedence...
<moritz> with "everywhere" I meant "at declaration and at {ex,im}portation"
<masak> declaring something feels like much more of a "conscious act"
than importation.
<masak> like, you might not know you're importing a `B`, but you
definitely know you're declaring one!

To summarize​: the error message "Merging GLOBAL symbols failed​:
duplicate definition of symbol B" on importing Y.pm is wrong. That
should work without an error. Referring to `B` after that in code
should be a (compile-time) error, though. This is the "poisoning"
effect referred to by S12.

The rest of the discussion is pertinent, but doesn't figure in the
closability of this ticket.

@p6rt

This comment has been minimized.

Copy link
Author

@p6rt p6rt commented Dec 1, 2017

The RT System itself - Status changed from 'new' to 'open'

@p6rt p6rt added the Bug label Jan 5, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
1 participant
You can’t perform that action at this time.