www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Should protection attributes disambiguate?

reply Peter Alexander <peter.alexander.au gmail.com> writes:
I'm working on a fix to http://d.puremagic.com/issues/show_bug.cgi?id=6180

Essentially the problem boils down to:

- Module A has a private symbol named x
- Module B has a public symbol named x
- Module C imports A and B and tries to use x unqualified

Should the fact that B.x is public and A.x is private disambiguate the 
usage in module C to use B.x, or is that still an ambiguous unqualified 
usage of variable x that requires manual qualification/disambiguation?
Jun 20 2011
next sibling parent reply "Nick Sabalausky" <a a.a> writes:
"Peter Alexander" <peter.alexander.au gmail.com> wrote in message 
news:itog87$2ed9$1 digitalmars.com...
 I'm working on a fix to http://d.puremagic.com/issues/show_bug.cgi?id=6180

 Essentially the problem boils down to:

 - Module A has a private symbol named x
 - Module B has a public symbol named x
 - Module C imports A and B and tries to use x unqualified

 Should the fact that B.x is public and A.x is private disambiguate the 
 usage in module C to use B.x, or is that still an ambiguous unqualified 
 usage of variable x that requires manual qualification/disambiguation?

If something's private, it's supposed to be an "internal-only" sort of thing. Private. Outside its own module, it shouldn't even be visibile and it's existence shouldn't have any effect. So I'd say unqualfied use of x inside C should definitely be allowed and resolve to B.x.
Jun 20 2011
next sibling parent reply "Nick Sabalausky" <a a.a> writes:
"Nick Sabalausky" <a a.a> wrote in message 
news:itoiji$2hsk$1 digitalmars.com...
 "Peter Alexander" <peter.alexander.au gmail.com> wrote in message 
 news:itog87$2ed9$1 digitalmars.com...
 I'm working on a fix to 
 http://d.puremagic.com/issues/show_bug.cgi?id=6180

 Essentially the problem boils down to:

 - Module A has a private symbol named x
 - Module B has a public symbol named x
 - Module C imports A and B and tries to use x unqualified

 Should the fact that B.x is public and A.x is private disambiguate the 
 usage in module C to use B.x, or is that still an ambiguous unqualified 
 usage of variable x that requires manual qualification/disambiguation?

If something's private, it's supposed to be an "internal-only" sort of thing. Private. Outside its own module, it shouldn't even be visibile and it's existence shouldn't have any effect. So I'd say unqualfied use of x inside C should definitely be allowed and resolve to B.x.

I'd add that IMO, to do otherwise would break encapsulation (or at least put a big ugly dent in it).
Jun 20 2011
parent reply Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
On 6/21/11, Jonathan M Davis <jmdavisProg gmx.com> wrote:
 That's not necessarily a bug

Maybe the naming of the issue is wrong, but it has to be a bug: http://d.puremagic.com/issues/show_bug.cgi?id=6180 If private symbols are not usable, then creating an object of a private class type is a pretty major bug, methinks.
Jun 20 2011
parent Kagamin <spam here.lot> writes:
Andrej Mitrovic Wrote:

 Maybe the naming of the issue is wrong, but it has to be a bug:
 http://d.puremagic.com/issues/show_bug.cgi?id=6180
 
 If private symbols are not usable, then creating an object of a
 private class type is a pretty major bug, methinks.

Currently access modifiers are not implemented for user-defined types, lol.
Jun 20 2011
prev sibling next sibling parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
Note that there is a bug with private symbols right now. If you have a
private class in module A, a public function with the same name in
module B and a module C that imports them both, the two names will
clash. I've reported this recently.
Jun 20 2011
prev sibling parent reply "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On 2011-06-20 15:43, Nick Sabalausky wrote:
 "Nick Sabalausky" <a a.a> wrote in message
 news:itoiji$2hsk$1 digitalmars.com...
 
 "Peter Alexander" <peter.alexander.au gmail.com> wrote in message
 news:itog87$2ed9$1 digitalmars.com...
 
 I'm working on a fix to
 http://d.puremagic.com/issues/show_bug.cgi?id=6180
 
 Essentially the problem boils down to:
 
 - Module A has a private symbol named x
 - Module B has a public symbol named x
 - Module C imports A and B and tries to use x unqualified
 
 Should the fact that B.x is public and A.x is private disambiguate the
 usage in module C to use B.x, or is that still an ambiguous unqualified
 usage of variable x that requires manual qualification/disambiguation?

If something's private, it's supposed to be an "internal-only" sort of thing. Private. Outside its own module, it shouldn't even be visibile and it's existence shouldn't have any effect. So I'd say unqualfied use of x inside C should definitely be allowed and resolve to B.x.

I'd add that IMO, to do otherwise would break encapsulation (or at least put a big ugly dent in it).

Well, except that access modifiers are _access_ modifiers. They indicate whether you can _use_ a particular symbol, not whether you can see it. So, the fact that a symbol is private has _zero_ affect on whether other modules can see it. That being said, the only situation that I can think of where it would cause a problem for private to be used as part part of the disambiguation process would be if you're trying to use a symbol which is private (not realizing that it's private) and end up using a symbol with the same name which you actually can access, and it manages to compile, and you end up using a symbol other than the one that you intended. Now, I wouldn't expect that to be a big problem - particularly since in most cases, the symbols likely wouldn't be able to be used the same and compile - but it is at least theoretically a concern. Personally, I think that the gain in making it so that the compiler can assume that a private symbol doesn't enter into overload sets or whatnot would far outweigh that one, particular problem. - Jonathan M Davis
Jun 20 2011
parent "Nick Sabalausky" <a a.a> writes:
"Jonathan M Davis" <jmdavisProg gmx.com> wrote in message 
news:mailman.1058.1308610718.14074.digitalmars-d puremagic.com...
 On 2011-06-20 15:43, Nick Sabalausky wrote:
 "Nick Sabalausky" <a a.a> wrote in message
 news:itoiji$2hsk$1 digitalmars.com...

 "Peter Alexander" <peter.alexander.au gmail.com> wrote in message
 news:itog87$2ed9$1 digitalmars.com...

 I'm working on a fix to
 http://d.puremagic.com/issues/show_bug.cgi?id=6180

 Essentially the problem boils down to:

 - Module A has a private symbol named x
 - Module B has a public symbol named x
 - Module C imports A and B and tries to use x unqualified

 Should the fact that B.x is public and A.x is private disambiguate the
 usage in module C to use B.x, or is that still an ambiguous 
 unqualified
 usage of variable x that requires manual qualification/disambiguation?

If something's private, it's supposed to be an "internal-only" sort of thing. Private. Outside its own module, it shouldn't even be visibile and it's existence shouldn't have any effect. So I'd say unqualfied use of x inside C should definitely be allowed and resolve to B.x.

I'd add that IMO, to do otherwise would break encapsulation (or at least put a big ugly dent in it).

Well, except that access modifiers are _access_ modifiers. They indicate whether you can _use_ a particular symbol, not whether you can see it. So, the fact that a symbol is private has _zero_ affect on whether other modules can see it.

Technically, maybe, but there's not much point in seeing it if you can't access it.
 That being said, the only situation that I can think of where it would 
 cause a
 problem for private to be used as part part of the disambiguation process
 would be if you're trying to use a symbol which is private (not realizing 
 that
 it's private) and end up using a symbol with the same name which you 
 actually
 can access, and it manages to compile, and you end up using a symbol other
 than the one that you intended. Now, I wouldn't expect that to be a big
 problem - particularly since in most cases, the symbols likely wouldn't be
 able to be used the same and compile - but it is at least theoretically a
 concern.

Yea, certainly true. But you can have problems the other way too: A module introduces a new private class/function/variable solely for it's own personal use, and it just happens to have the same name as a public member of some other module. So all the code that uses that public member ends up broken, just because the internal details of something else got changed. So like you, I think the benefits of not letting private stuff participate in overload resolution are well worth the risk of that rare scenario you describe.
 Personally, I think that the gain in making it so that the compiler can 
 assume
 that a private symbol doesn't enter into overload sets or whatnot would 
 far
 outweigh that one, particular problem.

Jun 20 2011
prev sibling next sibling parent reply Jonathan M Davis <jmdavisProg gmx.com> writes:
On 2011-06-20 17:36, Andrej Mitrovic wrote:
 On 6/21/11, Jonathan M Davis <jmdavisProg gmx.com> wrote:
 That's not necessarily a bug

Maybe the naming of the issue is wrong, but it has to be a bug: http://d.puremagic.com/issues/show_bug.cgi?id=6180 If private symbols are not usable, then creating an object of a private class type is a pretty major bug, methinks.

Oh, yes. That's a bug. But having two symbols which clash where one is private and the other public isn't a bug. It may be a design decision which merits revisiting, but as I understand it, it's a natural consequence of the fact that access modifiers modify access, not visibility. - Jonathan M Davis
Jun 20 2011
parent reply "Nick Sabalausky" <a a.a> writes:
"Jonathan M Davis" <jmdavisProg gmx.com> wrote in message 
news:mailman.1064.1308621500.14074.digitalmars-d puremagic.com...
 On 2011-06-20 17:36, Andrej Mitrovic wrote:
 On 6/21/11, Jonathan M Davis <jmdavisProg gmx.com> wrote:
 That's not necessarily a bug

Maybe the naming of the issue is wrong, but it has to be a bug: http://d.puremagic.com/issues/show_bug.cgi?id=6180 If private symbols are not usable, then creating an object of a private class type is a pretty major bug, methinks.

Oh, yes. That's a bug. But having two symbols which clash where one is private and the other public isn't a bug. It may be a design decision which merits revisiting, but as I understand it, it's a natural consequence of the fact that access modifiers modify access, not visibility.

Isn't visibility a form of access? Regardless, I think it's clear that the whole point of a private "access" modifier is to make things *private* and safely encapsulated. The current situation clearly breaks this. And since visibility without access is useless, I don't see any reason to even get into the subtle semantics of "visibility" vs "access" at all.
Jun 20 2011
next sibling parent Kagamin <spam here.lot> writes:
Nick Sabalausky Wrote:

 And since visibility without access is useless

I can think of a possibility that visibility of private symbols can indicate wrong access modifiers, though it's difficult to figure out a use case.
Jun 20 2011
prev sibling parent Peter Alexander <peter.alexander.au gmail.com> writes:
On 21/06/11 3:45 AM, Nick Sabalausky wrote:
 Isn't visibility a form of access?

 Regardless, I think it's clear that the whole point of a private "access"
 modifier is to make things *private* and safely encapsulated. The current
 situation clearly breaks this. And since visibility without access is
 useless, I don't see any reason to even get into the subtle semantics of
 "visibility" vs "access" at all.

It does break the idea of encapsulation a little, but we have to consider the side effects: As Jonathan says, it's possible that someone could try to use a private symbol and instead get a public symbol from another module. Depending on the situation, this could introduce subtle incorrect behavior that is difficult to detect. It's rare, but it could happen. You rightly argued the other way that someone could add a private symbol, which then causes user code to fail to compile due to a ambiguity. That sucks, but it is just an inconvenience that is easily solved by qualifying usage of the symbol. There is no possibility of subtle, difficult-to-detect behavior. I'm kind of on the fence with this. There's definitely merit to both sides of the argument.
Jun 21 2011
prev sibling next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On 2011-06-20 19:45, Nick Sabalausky wrote:
 "Jonathan M Davis" <jmdavisProg gmx.com> wrote in message
 news:mailman.1064.1308621500.14074.digitalmars-d puremagic.com...
 
 On 2011-06-20 17:36, Andrej Mitrovic wrote:
 On 6/21/11, Jonathan M Davis <jmdavisProg gmx.com> wrote:
 That's not necessarily a bug

Maybe the naming of the issue is wrong, but it has to be a bug: http://d.puremagic.com/issues/show_bug.cgi?id=6180 If private symbols are not usable, then creating an object of a private class type is a pretty major bug, methinks.

Oh, yes. That's a bug. But having two symbols which clash where one is private and the other public isn't a bug. It may be a design decision which merits revisiting, but as I understand it, it's a natural consequence of the fact that access modifiers modify access, not visibility.

Isn't visibility a form of access? Regardless, I think it's clear that the whole point of a private "access" modifier is to make things *private* and safely encapsulated. The current situation clearly breaks this. And since visibility without access is useless, I don't see any reason to even get into the subtle semantics of "visibility" vs "access" at all.

It matters for stuff like NVI (Non-Virtual Inheritance). In that particular case, you overload a private function but you can't call it. You couldn't overload it if you couldn't see it. So, there _are_ cases where it matters, and it _is_ an important distinction. It's just that it matters infrequently enough that most people don't realize that there is such a distinction. But distinction or not, I don't see why we couldn't just make it so that any attempt to use a symbol where the clashing symbol can't be used anyway just doesn't clash by ignoring the private symbol in such cases. - Jonathan M Davis
Jun 20 2011
prev sibling next sibling parent so <so so.so> writes:
On Tue, 21 Jun 2011 06:04:28 +0300, Jonathan M Davis <jmdavisProg gmx.com>  
wrote:

 It matters for stuff like NVI (Non-Virtual Inheritance). In that  
 particular
 case, you overload a private function but you can't call it. You couldn't
 overload it if you couldn't see it. So, there _are_ cases where it  
 matters,
 and it _is_ an important distinction. It's just that it matters  
 infrequently
 enough that most people don't realize that there is such a distinction.  
 But
 distinction or not, I don't see why we couldn't just make it so that any
 attempt to use a symbol where the clashing symbol can't be used anyway  
 just
 doesn't clash by ignoring the private symbol in such cases.

 - Jonathan M Davis

Good example, is it only this or are there any others? I am asking because i think this particular use case doesn't justify visibility but not access. If i got it right, we are talking about something like this: module base1; private import base; struct base1 : base { } module base2; import base1; struct base2 : base1 { } Shouldn't compiler just issue an error whenever base1 accessed outside of the module it belongs? With its current state, it just encourages bad design as far as i can see. First of all inheriting from a class/interface/struct that is imported private implies this new class is going to be an implementation detail, hidden from user. If it wasn't intended, why would you import it private?
Jun 21 2011
prev sibling next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On 2011-06-21 05:40, so wrote:
 On Tue, 21 Jun 2011 06:04:28 +0300, Jonathan M Davis <jmdavisProg gmx.com>
 
 wrote:
 It matters for stuff like NVI (Non-Virtual Inheritance). In that
 particular
 case, you overload a private function but you can't call it. You couldn't
 overload it if you couldn't see it. So, there _are_ cases where it
 matters,
 and it _is_ an important distinction. It's just that it matters
 infrequently
 enough that most people don't realize that there is such a distinction.
 But
 distinction or not, I don't see why we couldn't just make it so that any
 attempt to use a symbol where the clashing symbol can't be used anyway
 just
 doesn't clash by ignoring the private symbol in such cases.
 
 - Jonathan M Davis

Good example, is it only this or are there any others? I am asking because i think this particular use case doesn't justify visibility but not access. If i got it right, we are talking about something like this: module base1; private import base; struct base1 : base { } module base2; import base1; struct base2 : base1 { } Shouldn't compiler just issue an error whenever base1 accessed outside of the module it belongs? With its current state, it just encourages bad design as far as i can see. First of all inheriting from a class/interface/struct that is imported private implies this new class is going to be an implementation detail, hidden from user. If it wasn't intended, why would you import it private?

??? private import a; and import a; are identical. There is no difference. When you import that doesn't affect any modules that import you. Now, making an import _public_ affects other modules, because then anyone who imports you also imports the other module, but imports are private by default. So, I don't understand what you're saying here. The compiler does issue an error when you try and use a symbol which is private to another module. The issue here is that if there's another symbol which clashes which you _can_ access, the compiler forces you to give its full path instead of assuming that you mean the public one (which you _can_ use) and not the private one (which you can't). - Jonathan M Davis
Jun 21 2011
prev sibling next sibling parent so <so so.so> writes:
On Tue, 21 Jun 2011 18:43:51 +0300, Jonathan M Davis <jmdavisProg gmx.com>  
wrote:

 ???

 private import a;

 and

 import a;

Uh, yeah you are right. I meant something like: module base1; private struct base; struct base1 : base { }
Jun 21 2011
prev sibling parent "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On 2011-06-21 09:00, so wrote:
 On Tue, 21 Jun 2011 18:43:51 +0300, Jonathan M Davis <jmdavisProg gmx.com>
 
 wrote:
 ???
 
 private import a;
 
 and
 
 import a;

Uh, yeah you are right. I meant something like: module base1; private struct base; struct base1 : base { }

In such a case, the current implementation complains if you try and use base, which is exactly what it should be doing. It'll tell you that base is private and that you don't have access to it. If it were completely hidden, then the error message would end up saying something about base not existing, which could be far more confusing, since base _does_ exist. The issue here is that if you had your own base which you imported from another module, the compiler is going to complain about that base and base1.base clashing instead of assuming that you meant your base, since base1.base is private. All that is required here is adjusting how symbols collisions are dealt with when one of the symbols is private. There's no need to adjust how access modifiers work globally. And there are _definitely_ people out there who think that NVI justifies visibility without access. But regardless of that, I believe that that's how public and private work in every C-derived language which has them. The exact implications of that may very from language to language depending on what they do or don't allow you to do, but as far as I know, access modifiers are always _access_ modifiers and not visibility modifiers. - Jonathan M Davis
Jun 21 2011