January 24, 2012
Should aliases be allowed to raise the accessibility of a symbol?

http://d.puremagic.com/issues/show_bug.cgi?id=4533
http://d.puremagic.com/issues/show_bug.cgi?id=6013
January 24, 2012
> Should aliases be allowed to raise the accessibility of a symbol?

Yeah I do use that by having a private template function and public aliases to certain instances.
January 24, 2012
"Martin Nowak" <dawg@dawgfoto.de> wrote in message news:mailman.782.1327427928.16222.digitalmars-d@puremagic.com...
> Should aliases be allowed to raise the accessibility of a symbol?
>
> http://d.puremagic.com/issues/show_bug.cgi?id=4533 http://d.puremagic.com/issues/show_bug.cgi?id=6013

Yes.


January 24, 2012
"Nick Sabalausky" <a@a.a> wrote in message news:jfnag6$317n$1@digitalmars.com...
> "Martin Nowak" <dawg@dawgfoto.de> wrote in message news:mailman.782.1327427928.16222.digitalmars-d@puremagic.com...
>> Should aliases be allowed to raise the accessibility of a symbol?
>>
>> http://d.puremagic.com/issues/show_bug.cgi?id=4533 http://d.puremagic.com/issues/show_bug.cgi?id=6013
>
> Yes.
>

How else are you going to separate the interface for the internal implementation of a template from its for-public-consumption interface?

This whole issue is literally *NO* different from "Should a public pointer/reference be allowed to point to private data?" or "Should a public function be allowed to expose a private one?" The answer is: "Obviously yes".

I don't understand why anyone thinks this is any different just because they're aliases instead of pointers/references/functions/etc. All the arguments against public alias to private symbols apply equally to these questions too, and in those cases nobody would even question it. What is it about aliases that suddenly trips people up and makes them think the whole concept of accessibility should be flipped around on its head?


January 24, 2012
On Tuesday, 24 January 2012 at 22:26:37 UTC, Nick Sabalausky wrote:
> This whole issue is literally *NO* different from "Should a public pointer/reference be allowed to point to private data?" or "Should a public function be allowed to expose a private one?" The answer is: "Obviously yes".

Things can be obvious in different ways.

For example, one could argue that it's also obvious that an alias should behave exactly the same as the thing it aliases. Allowing aliases to change protection would break that.

For the record, I agree that the answer should be "yes", but it's not a decision that should be made rashly. If we aren't careful, we could introduce a hole in the protection system in a non-obvious way. C++'s protection system has a non-obvious hole: http://bloglitb.blogspot.com/2010/07/access-to-private-members-thats-easy.html

Again, I agree, but what's obvious isn't always true, so it needs to be considered in depth.
January 25, 2012
On 01/25/2012 12:09 AM, Peter Alexander wrote:
> On Tuesday, 24 January 2012 at 22:26:37 UTC, Nick Sabalausky wrote:
>> This whole issue is literally *NO* different from "Should a public
>> pointer/reference be allowed to point to private data?" or "Should a
>> public function be allowed to expose a private one?" The answer is:
>> "Obviously yes".
>
> Things can be obvious in different ways.
>
> For example, one could argue that it's also obvious that an alias should
> behave exactly the same as the thing it aliases. Allowing aliases to
> change protection would break that.

The accessibility of something is not part of its behavior.

>
> For the record, I agree that the answer should be "yes", but it's not a
> decision that should be made rashly. If we aren't careful, we could
> introduce a hole in the protection system in a non-obvious way. C++'s
> protection system has a non-obvious hole:
> http://bloglitb.blogspot.com/2010/07/access-to-private-members-thats-easy.html
>

Non-obvious? Perfectly obvious: Access checking rules do not apply to names in explicit template instantiations. It is an explicit rule that states access checking is subverted.

>
> Again, I agree, but what's obvious isn't always true, so it needs to be
> considered in depth.

Accessibility-raising aliases are trivially safe, because the alias declaration must have access to the aliased symbol.
January 25, 2012
On Wednesday, 25 January 2012 at 00:08:25 UTC, Timon Gehr wrote:
> Accessibility-raising aliases are trivially safe, because the alias declaration must have access to the aliased symbol.

You are probably right about not introducing holes, but I can imagine this getting tricky, and perhaps confusing in some cases. Here are some off the top of my head.

module A;
private class Foo {}
public alias Foo Bar;

In other modules that import A:

Bar b = new typeof(b)(); // typeof(b) is Foo. Is this allowed?

T foo(T)(T x) { return new T(); }
Bar b;
b = foo(b); // T is deduced to Foo, should this work?

Bar b = new Bar();
mixin("b = new " ~ typeof(b).stringof ~ "();"); // This fails, the string is "Foo"


Just thinking about this has made me change my position. Accessibility raising aliases should not be allowed. It's a minefield.
January 25, 2012
"Peter Alexander" <peter.alexander.au@gmail.com> wrote in message news:bfhygfbdlubuwelaqfws@dfeed.kimsufi.thecybershadow.net...
>
> For example, one could argue that it's also obvious that an alias should behave exactly the same as the thing it aliases. Allowing aliases to change protection would break that.
>

FWIW, If someone were to argue that, my response would be something like:

1. If you wanted it *exactly* the same, you wouldn't have aliased it at all. So naturally, that "exactly" is subject to reasonable exceptions.

2. Protection levels apply to symbols, not the construct or data the symbol refers to.

3. (Just reiterating I guess:) Protection levels are not, should not, and cannot realistically be transitive.

> For the record, I agree that the answer should be "yes", but it's


January 25, 2012
"Peter Alexander" <peter.alexander.au@gmail.com> wrote in message news:jzvidktaqmkptrooimvt@dfeed.kimsufi.thecybershadow.net...
> On Wednesday, 25 January 2012 at 00:08:25 UTC, Timon Gehr wrote:
>> Accessibility-raising aliases are trivially safe, because the alias declaration must have access to the aliased symbol.
>
> You are probably right about not introducing holes, but I can imagine this getting tricky, and perhaps confusing in some cases. Here are some off the top of my head.
>
> module A;
> private class Foo {}
> public alias Foo Bar;
>
> In other modules that import A:
>
> Bar b = new typeof(b)(); // typeof(b) is Foo. Is this allowed?
>
> T foo(T)(T x) { return new T(); }
> Bar b;
> b = foo(b); // T is deduced to Foo, should this work?
>
> Bar b = new Bar();
> mixin("b = new " ~ typeof(b).stringof ~ "();"); // This fails, the string
> is "Foo"
>

In all the above, the type *should* be Bar, not Foo (although it might not currently be - I'd consider that something that needs to be changed). Bar should refer to Foo *behind the scenes*, and as such, the fact that it refers to something else behind the scenes is totally irrelevent.

This would also seem to be related to issue of error messages currently referring to the underlying type insted of the aliased type (which I'm convinced is the wrong way round).

>
> Just thinking about this has made me change my position. Accessibility raising aliases should not be allowed. It's a minefield.

The issue is not with aliases, accessability already has a natural grey area:

====================
module lib;

private struct Foo {}

// Should any of these be allowed?
public Foo getFoo() { return Foo(); }
public void takeFoo(Foo f) {}
struct Bar
{
    Foo f;
}

------

module main;
import lib;

getFoo();  // Allowed?

takeFoo(getFoo());  // Allowed?

Bar b;  // Allowed?

takeFoo(b.f);   // Allowed?

b.f = getFoo();   // Allowed?

// Allowed? If so, can you *do* anything with x?
auto x = getFoo();

====================


January 25, 2012
On 01/25/2012 01:59 AM, Peter Alexander wrote:
> On Wednesday, 25 January 2012 at 00:08:25 UTC, Timon Gehr wrote:
>> Accessibility-raising aliases are trivially safe, because the alias
>> declaration must have access to the aliased symbol.
>
> You are probably right about not introducing holes, but I can imagine
> this getting tricky, and perhaps confusing in some cases. Here are some
> off the top of my head.
>
> module A;
> private class Foo {}
> public alias Foo Bar;
>
> In other modules that import A:
>
> Bar b = new typeof(b)(); // typeof(b) is Foo. Is this allowed?
>
> T foo(T)(T x) { return new T(); }
> Bar b;
> b = foo(b); // T is deduced to Foo, should this work?
>
> Bar b = new Bar();
> mixin("b = new " ~ typeof(b).stringof ~ "();"); // This fails, the
> string is "Foo"
>
>
> Just thinking about this has made me change my position. Accessibility
> raising aliases should not be allowed. It's a minefield.

That is a valid counter-argument. While I am sure these issues could be sorted out, it would probably amount to over-engineering. This is basically the only useful use case worth considering:

private template Tmpl(T){...}
public alias Tmpl!int foo;

Tmpl and Tmpl!int are two _distinct symbols_, and there is no dedicated syntax to make just one of them accessible.

Therefore, this use case could be allowed as a special case: Explicit use of Tmpl from another module would be forbidden, but the instance Tmpl!int would be public under the name foo. (While explicitly instantiating Tmpl!int would fail, because Tmpl is not accessible (or ideally not visible).)

There would be no public/private aliasing, and therefore all the issues you mentioned would not exist in this case.


« First   ‹ Prev
1 2 3
Top | Discussion index | About this forum | D home