Re: Logical location of template instantiations

2016-07-08 Thread Jonathan M Davis via Digitalmars-d
On Friday, July 08, 2016 15:08:35 Timon Gehr via Digitalmars-d wrote:
> On 08.07.2016 09:45, Jonathan M Davis via Digitalmars-d wrote:
> > On Thursday, July 07, 2016 23:20:28 Timon Gehr via Digitalmars-d wrote:
> >> On 07.07.2016 17:11, Jonathan M Davis via Digitalmars-d wrote:
> >>>So,
> >>>
> >>> the buck would have to be passed at every point that the symbol were
> >>> passed
> >>> as an alias argument such that the check for accessibility was only done
> >>> when the symbol first became an alias.
> >>> ...
> >>
> >> No, it is way simpler than that. Just don't ever check for visibility of
> >> the symbol accessed through an alias.
> >
> > It has to be checked at some point, otherwise using a template alias
> > parameter would allow you to completely bypass the accessibility
> > modifiers.
> > It's just that it seems like it should be checked at the point where the
> > symbol is passed to the template and not within the template itself,
> > whereas right now, it's checked within the template.
> >
> > - Jonathan M Davis
>
> (That's what I said. In any case, it is simple to implement.)

Well, then I misunderstood what you meant. But if it's simple to implement,
then it seems to me that it's almost certainly the way we should go. It
would solve the accessibility problem in a clean way without having to
instantiate the template extra times.

- Jonathan M Davis



Re: Logical location of template instantiations

2016-07-08 Thread Timon Gehr via Digitalmars-d

On 08.07.2016 09:45, Jonathan M Davis via Digitalmars-d wrote:

On Thursday, July 07, 2016 23:20:28 Timon Gehr via Digitalmars-d wrote:

On 07.07.2016 17:11, Jonathan M Davis via Digitalmars-d wrote:

   So,

the buck would have to be passed at every point that the symbol were
passed
as an alias argument such that the check for accessibility was only done
when the symbol first became an alias.
...


No, it is way simpler than that. Just don't ever check for visibility of
the symbol accessed through an alias.


It has to be checked at some point, otherwise using a template alias
parameter would allow you to completely bypass the accessibility modifiers.
It's just that it seems like it should be checked at the point where the
symbol is passed to the template and not within the template itself, whereas
right now, it's checked within the template.

- Jonathan M Davis



(That's what I said. In any case, it is simple to implement.)


Re: Logical location of template instantiations

2016-07-08 Thread Jonathan M Davis via Digitalmars-d
On Thursday, July 07, 2016 23:20:28 Timon Gehr via Digitalmars-d wrote:
> On 07.07.2016 17:11, Jonathan M Davis via Digitalmars-d wrote:
> >   So,
> >
> > the buck would have to be passed at every point that the symbol were
> > passed
> > as an alias argument such that the check for accessibility was only done
> > when the symbol first became an alias.
> > ...
>
> No, it is way simpler than that. Just don't ever check for visibility of
> the symbol accessed through an alias.

It has to be checked at some point, otherwise using a template alias
parameter would allow you to completely bypass the accessibility modifiers.
It's just that it seems like it should be checked at the point where the
symbol is passed to the template and not within the template itself, whereas
right now, it's checked within the template.

- Jonathan M Davis



Re: Logical location of template instantiations

2016-07-07 Thread Timon Gehr via Digitalmars-d

On 07.07.2016 17:11, Jonathan M Davis via Digitalmars-d wrote:

  So,
the buck would have to be passed at every point that the symbol were passed
as an alias argument such that the check for accessibility was only done
when the symbol first became an alias.
...


No, it is way simpler than that. Just don't ever check for visibility of 
the symbol accessed through an alias.



Regardless, while that idea makes theoretical sense, I'm not sure that it
makes sense from the standpoint of how alias parameters are currently
implemented.


That ought to be completely irrelevant.


Re: Logical location of template instantiations

2016-07-07 Thread Jonathan M Davis via Digitalmars-d
On Thursday, July 07, 2016 08:39:51 Steven Schveighoffer via Digitalmars-d 
wrote:
> Yes, it is a problem. I still don't understand how the *calling* of a
> private function is the problem, vs. the aliasing of it. Why aren't we
> preventing the aliasing of the private function in the first place (if
> not allowed)? If you can get an alias, you should be able to call it.
>
> I understand that aliases are strange in this way. What we really need
> is an alias to the protection level. An explicit permission given to an
> external template that says "for this one instantiation, you can pretend
> you have access to this".

What would make sense is if the template instantiation ignored the access
level of the aliased symbol and were the same regardless of the access level
of that symbol such that the template compiled regardless, but the check for
accessibility would be done at the call site. Then the template could
compile with a private function just fine, but it wouldn't be callable
except where the private function would be callable.

I suppose that that  could get a bit hairy though when you consider multiple
levels, since if you had something like

void foo(alias pred, Arg)(Arg arg)
{
bar(pred)(arg);
}

void bar(alias pred, Arg)(Arg arg)
{
pred(arg);
}

to work even with foo and bar in different modules so long as foo were
called in a place where the function being passed to it were callable. So,
the buck would have to be passed at every point that the symbol were passed
as an alias argument such that the check for accessibility was only done
when the symbol first became an alias.

Regardless, while that idea makes theoretical sense, I'm not sure that it
makes sense from the standpoint of how alias parameters are currently
implemented. I'm inclined to think though that something along those lines
would be the best solution (at least from a usability perspective, not
necessarily from the compiler's perspective).

- Jonathan M Davis



Re: Logical location of template instantiations

2016-07-07 Thread Tofu Ninja via Digitalmars-d
On Thursday, 7 July 2016 at 12:39:51 UTC, Steven Schveighoffer 
wrote:
Yes, it is a problem. I still don't understand how the 
*calling* of a private function is the problem, vs. the 
aliasing of it. Why aren't we preventing the aliasing of the 
private function in the first place (if not allowed)? If you 
can get an alias, you should be able to call it.


I understand that aliases are strange in this way. What we 
really need is an alias to the protection level. An explicit 
permission given to an external template that says "for this 
one instantiation, you can pretend you have access to this".


A workaround, of course, is to use a delegate.

I came across this when learning vibe.d, which gets around the 
requirement in an interesting way: 
https://github.com/rejectedsoftware/vibe.d/issues/1516


-Steve


It makes sense that the aliasing a private member works, when it 
is made at the instantiation site it is perfectly visible. It 
only gets mucked up when the alias travels out of that context 
into the template where it is no longer visible.


Re: Logical location of template instantiations

2016-07-07 Thread Steven Schveighoffer via Digitalmars-d

On 7/7/16 7:49 AM, Tofu Ninja wrote:

On Friday, 1 July 2016 at 19:13:45 UTC, Steven Schveighoffer wrote:

Emplace needs a constructor alias parameter.

-Steve


That wouldn't work as emplace wouldn't be able to use the alias if it
was private...

void main(){
 import other;
 test!foo();
}

private void foo(){}
##
module other;
void test(alias pred)(){
pred();
}



other.d(5): Error: function main.foo is not accessible from module other
main.d(9): Error: template instance other.test!(foo) error instantiating


Yes, it is a problem. I still don't understand how the *calling* of a 
private function is the problem, vs. the aliasing of it. Why aren't we 
preventing the aliasing of the private function in the first place (if 
not allowed)? If you can get an alias, you should be able to call it.


I understand that aliases are strange in this way. What we really need 
is an alias to the protection level. An explicit permission given to an 
external template that says "for this one instantiation, you can pretend 
you have access to this".


A workaround, of course, is to use a delegate.

I came across this when learning vibe.d, which gets around the 
requirement in an interesting way: 
https://github.com/rejectedsoftware/vibe.d/issues/1516


-Steve


Re: Logical location of template instantiations

2016-07-07 Thread Tofu Ninja via Digitalmars-d
On Friday, 1 July 2016 at 19:13:45 UTC, Steven Schveighoffer 
wrote:

Emplace needs a constructor alias parameter.

-Steve


That wouldn't work as emplace wouldn't be able to use the alias 
if it was private...


void main(){
 import other;
 test!foo();
}

private void foo(){}
##
module other;
void test(alias pred)(){
pred();
}



other.d(5): Error: function main.foo is not accessible from 
module other
main.d(9): Error: template instance other.test!(foo) error 
instantiating


Re: Logical location of template instantiations

2016-07-01 Thread Lodovico Giaretta via Digitalmars-d
On Friday, 1 July 2016 at 19:13:45 UTC, Steven Schveighoffer 
wrote:

On 7/1/16 3:02 PM, Timon Gehr wrote:


The current module (that declares 'S') might not be the only 
module that
uses emplace to construct 'S' instances. We want to hide the 
constructor

of 'S' from other modules, but not from the current module.
But both modules get identical template instances, so either 
both see
the private constructor (through emplace), or none does. To 
fix this
properly, there should hence be a way for the two modules to 
receive

distinct template instances.


Emplace needs a constructor alias parameter.

-Steve


Yes, this looks like a sensible solution.


Re: Logical location of template instantiations

2016-07-01 Thread Steven Schveighoffer via Digitalmars-d

On 7/1/16 3:02 PM, Timon Gehr wrote:


The current module (that declares 'S') might not be the only module that
uses emplace to construct 'S' instances. We want to hide the constructor
of 'S' from other modules, but not from the current module.
But both modules get identical template instances, so either both see
the private constructor (through emplace), or none does. To fix this
properly, there should hence be a way for the two modules to receive
distinct template instances.


Emplace needs a constructor alias parameter.

-Steve


Re: Logical location of template instantiations

2016-07-01 Thread Timon Gehr via Digitalmars-d

On 27.06.2016 18:25, Lodovico Giaretta wrote:

import std.conv, core.memory;

struct S
{
 int x;
 private this(int val)
 {
 x = val;
 }
}

void main()
{
 auto ptr = cast(S*)GC.malloc(S.sizeof);
 auto s = ptr.emplace(3);
}

This code does not work, as  the call `ptr.emplace(3)` creates a new
concrete implementation of emplace with parameters `S` and `int`, which
logically belongs to module std.conv, and so has no access to the
private constructor.

But, logically speaking, as I'm able to construct objects of S, I should
also be able to emplace them (which is the same thing, logically) while
inside my module. What I mean is that in this situation it would be
better if the call `ptr.emplace(3)` created a new concrete
implementation of emplace inside the module that called it, to have the
correct access permissions.

This is not the first time I run into this limitation (not only with
functions, but also with structs), so I wonder: wouldn't it be worth a
way to get this behaviour?

Thank you for your time.

Lodovico Giaretta


The current module (that declares 'S') might not be the only module that 
uses emplace to construct 'S' instances. We want to hide the constructor 
of 'S' from other modules, but not from the current module.
But both modules get identical template instances, so either both see 
the private constructor (through emplace), or none does. To fix this 
properly, there should hence be a way for the two modules to receive 
distinct template instances.


Re: Logical location of template instantiations

2016-07-01 Thread Jacob Carlborg via Digitalmars-d

On 01/07/16 16:14, Steven Schveighoffer wrote:


Right, but this puts allocators at a lower footing than the GC which has
no problem with private ctors. I would have expected to be able to build
using allocators and private ctors.


It's possible to bypass protection using pointers.

--
/Jacob Carlborg


Re: Logical location of template instantiations

2016-07-01 Thread Basile B. via Digitalmars-d

On Monday, 27 June 2016 at 16:25:27 UTC, Lodovico Giaretta wrote:

[...]

This is not the first time I run into this limitation (not only 
with functions, but also with structs), so I wonder: wouldn't 
it be worth a way to get this behaviour?


Yes it would be worth. Several ppl have already hit this wall, 
including me. You can vote for this enhancement, it proposes to 
give a "super visual acuity" to traits such as getMember or 
getOverloads:


https://issues.dlang.org/show_bug.cgi?id=15371

You might also look at `hasUDA` from std.traits because it used 
to be affected by this issue.


Re: Logical location of template instantiations

2016-07-01 Thread Basile B. via Digitalmars-d
On Friday, 1 July 2016 at 14:14:00 UTC, Steven Schveighoffer 
wrote:

On 7/1/16 9:46 AM, Andrei Alexandrescu wrote:

On 07/01/2016 09:08 AM, Steven Schveighoffer wrote:




I wonder what the plans are for std.allocator on this, as I 
would think

it would run into the same issues. Andrei?


emplace only works with accessible constructors. I understand 
sometimes
it's reasonable to ask for more flexibility, but there are 
limitations.


Right, but this puts allocators at a lower footing than the GC 
which has no problem with private ctors. I would have expected 
to be able to build using allocators and private ctors.


-Steve


+1


Re: Logical location of template instantiations

2016-07-01 Thread Steven Schveighoffer via Digitalmars-d

On 7/1/16 9:46 AM, Andrei Alexandrescu wrote:

On 07/01/2016 09:08 AM, Steven Schveighoffer wrote:




I wonder what the plans are for std.allocator on this, as I would think
it would run into the same issues. Andrei?


emplace only works with accessible constructors. I understand sometimes
it's reasonable to ask for more flexibility, but there are limitations.


Right, but this puts allocators at a lower footing than the GC which has 
no problem with private ctors. I would have expected to be able to build 
using allocators and private ctors.


-Steve


Re: Logical location of template instantiations

2016-07-01 Thread Jacob Carlborg via Digitalmars-d

On 01/07/16 15:46, Andrei Alexandrescu wrote:


emplace only works with accessible constructors. I understand sometimes
it's reasonable to ask for more flexibility, but there are limitations.


It's possible to bypass the protection using a pointer. An alternative 
would be to not invoke the constructor and let the users to that themselves.


--
/Jacob Carlborg


Re: Logical location of template instantiations

2016-07-01 Thread Andrei Alexandrescu via Digitalmars-d

On 07/01/2016 09:08 AM, Steven Schveighoffer wrote:

On 6/27/16 12:25 PM, Lodovico Giaretta wrote:

import std.conv, core.memory;

struct S
{
int x;
private this(int val)
{
x = val;
}
}

void main()
{
auto ptr = cast(S*)GC.malloc(S.sizeof);
auto s = ptr.emplace(3);
}

This code does not work, as  the call `ptr.emplace(3)` creates a new
concrete implementation of emplace with parameters `S` and `int`, which
logically belongs to module std.conv, and so has no access to the
private constructor.

But, logically speaking, as I'm able to construct objects of S, I should
also be able to emplace them (which is the same thing, logically) while
inside my module. What I mean is that in this situation it would be
better if the call `ptr.emplace(3)` created a new concrete
implementation of emplace inside the module that called it, to have the
correct access permissions.


I wonder what the plans are for std.allocator on this, as I would think
it would run into the same issues. Andrei?


emplace only works with accessible constructors. I understand sometimes 
it's reasonable to ask for more flexibility, but there are limitations. 
-- Andrei




Re: Logical location of template instantiations

2016-07-01 Thread Jacob Carlborg via Digitalmars-d

On 01/07/16 11:57, Lodovico Giaretta wrote:

Ping...

Maybe I'm just saying bullshit, but...
Am I really the only one who faced this need?


You're not the only one, it's been brought up before. A 
solution/workaround is that "emplace" invokes the constructor using a 
function pointer, what will bypass the protection.


--
/Jacob Carlborg


Re: Logical location of template instantiations

2016-07-01 Thread Steven Schveighoffer via Digitalmars-d

On 6/27/16 12:25 PM, Lodovico Giaretta wrote:

import std.conv, core.memory;

struct S
{
int x;
private this(int val)
{
x = val;
}
}

void main()
{
auto ptr = cast(S*)GC.malloc(S.sizeof);
auto s = ptr.emplace(3);
}

This code does not work, as  the call `ptr.emplace(3)` creates a new
concrete implementation of emplace with parameters `S` and `int`, which
logically belongs to module std.conv, and so has no access to the
private constructor.

But, logically speaking, as I'm able to construct objects of S, I should
also be able to emplace them (which is the same thing, logically) while
inside my module. What I mean is that in this situation it would be
better if the call `ptr.emplace(3)` created a new concrete
implementation of emplace inside the module that called it, to have the
correct access permissions.


I wonder what the plans are for std.allocator on this, as I would think 
it would run into the same issues. Andrei?


-Steve


Re: Logical location of template instantiations

2016-07-01 Thread Enamex via Digitalmars-d

On Friday, 1 July 2016 at 12:08:49 UTC, Lodovico Giaretta wrote:
On Friday, 1 July 2016 at 11:45:12 UTC, Robert burner Schadek 
wrote:
IMO, this is one of these places where theory meets practice. 
Do what works, write a comment explaining the problem, and 
move on ;-)


Yes, well, I successfully bypassed my issues with this thing, 
but I wanted to share my thoughts about the need to express 
this kind of thing (i.e. to give a template instantiation the 
privileges of the instantiating module), and to know if someone 
else has some opinion on this matter.


Yeah. I don't know if it's _needed_ by enough people or by the 
language, but a way to force templates to be hijacked while being 
instantiated (not at point of definition but at instantiation; 
though I imagine this might prove troublesome for reflection and 
template identity, somehow) if we want to. The default hygienic 
behavior is great, but bypassing it when needed is not.


Re: Logical location of template instantiations

2016-07-01 Thread Lodovico Giaretta via Digitalmars-d
On Friday, 1 July 2016 at 11:45:12 UTC, Robert burner Schadek 
wrote:
IMO, this is one of these places where theory meets practice. 
Do what works, write a comment explaining the problem, and move 
on ;-)


Yes, well, I successfully bypassed my issues with this thing, but 
I wanted to share my thoughts about the need to express this kind 
of thing (i.e. to give a template instantiation the privileges of 
the instantiating module), and to know if someone else has some 
opinion on this matter.


Re: Logical location of template instantiations

2016-07-01 Thread Robert burner Schadek via Digitalmars-d
IMO, this is one of these places where theory meets practice. Do 
what works, write a comment explaining the problem, and move on 
;-)


Re: Logical location of template instantiations

2016-07-01 Thread Lodovico Giaretta via Digitalmars-d

Ping...

Maybe I'm just saying bullshit, but...
Am I really the only one who faced this need?




Logical location of template instantiations

2016-06-27 Thread Lodovico Giaretta via Digitalmars-d

import std.conv, core.memory;

struct S
{
int x;
private this(int val)
{
x = val;
}
}

void main()
{
auto ptr = cast(S*)GC.malloc(S.sizeof);
auto s = ptr.emplace(3);
}

This code does not work, as  the call `ptr.emplace(3)` creates a 
new concrete implementation of emplace with parameters `S` and 
`int`, which logically belongs to module std.conv, and so has no 
access to the private constructor.


But, logically speaking, as I'm able to construct objects of S, I 
should also be able to emplace them (which is the same thing, 
logically) while inside my module. What I mean is that in this 
situation it would be better if the call `ptr.emplace(3)` created 
a new concrete implementation of emplace inside the module that 
called it, to have the correct access permissions.


This is not the first time I run into this limitation (not only 
with functions, but also with structs), so I wonder: wouldn't it 
be worth a way to get this behaviour?


Thank you for your time.

Lodovico Giaretta