Skip Menu |
Report information
Id: 123583
Status: open
Priority: 0/
Queue: perl6

Owner: Nobody
Requestors: masak <cmasak [at] gmail.com>
Cc:
AdminCc:

Severity: (no value)
Tag: Bug
Platform: (no value)
Patch Status: (no value)
VM: (no value)



Subject: [BUG] 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
To: rakudobug [...] perl.org
From: Carl Mäsak <cmasak [...] gmail.com>
Date: Sun, 11 Jan 2015 14:44:13 +0100
Download (untitled) / with headers
text/plain 2.8k
<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.
Still reproducible (2017.11, HEAD(5929887)), but with a slightly different error:

Show quoted text
===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:
Show quoted text
> <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.




This service is sponsored and maintained by Best Practical Solutions and runs on Perl.org infrastructure.

For issues related to this RT instance (aka "perlbug"), please contact perlbug-admin at perl.org