View mode: basic / threaded / horizontal-split · Log in · Help
October 19, 2012
Re: Const ref and rvalues again...
On Friday, 19 October 2012 at 00:03:49 UTC, Timon Gehr wrote:
>
> Const is different in D and in C++. Relating const and rvalues 
> is arbitrary and does not make a lot of sense.
>
> Regarding 'in ref'/'scope ref': What should 'scope' apply to in
>
> void foo(scope ref int* x);

Not sure what you mean with "relating." I'm not making any claims 
about there being a relationship between rvalues and constness.

This is about finding a way that you can define a function which 
safely accepts lvalues and rvalues without having to make a copy. 
If we specify the argument as "ref in", then we can safely pass 
for example the number 5 to it. And this would never break 
existing code, so that something like swap(5, 4) would never be 
possible code.

For the example that you gave you'd be unable to store the 
address of x. So doing

int** storage;
void foo(scope ref int * x)
{
    storage = &x;
}

would be illegal.

@jerro: the same thing: I'm not trying to fix the problem that 
you mention. I'm trying to define a function which can safely 
accept rvalues and lvalues without having to make a copy.
October 19, 2012
Re: Const ref and rvalues again...
On 10/19/2012 03:26 AM, Malte Skarupke wrote:
> On Friday, 19 October 2012 at 00:03:49 UTC, Timon Gehr wrote:
>>
>> Const is different in D and in C++. Relating const and rvalues is
>> arbitrary and does not make a lot of sense.
>>
>> Regarding 'in ref'/'scope ref': What should 'scope' apply to in
>>
>> void foo(scope ref int* x);
>
> Not sure what you mean with "relating." I'm not making any claims about
> there being a relationship between rvalues and constness.
>

You do it again right away:

> This is about finding a way that you can define a function which safely
> accepts lvalues and rvalues without having to make a copy. If we specify
> the argument as "ref in", then we can safely pass for example the number
                  ^~~~~~~~
                    const
> 5 to it.
  ^
rvalue

> And this would never break existing code, so that something
> like swap(5, 4) would never be possible code.
>

That does not break existing code except code that checks validity of
code, but every language change does that.

> For the example that you gave you'd be unable to store the address of x.
> So doing
>
> int** storage;
> void foo(scope ref int * x)
> {
>      storage = &x;
> }
>
> would be illegal.
>

Then how to specify that the value of x cannot be escaped?
I'm in favour of doing it the other way round and disallow escaping of
ref parameters without an unsafe cast.

> @jerro: the same thing: I'm not trying to fix the problem that you
> mention. I'm trying to define a function which can safely accept rvalues
> and lvalues without having to make a copy.
October 19, 2012
Re: Const ref and rvalues again...
> @jerro: the same thing: I'm not trying to fix the problem that 
> you mention. I'm trying to define a function which can safely 
> accept rvalues and lvalues without having to make a copy.

My point was that saving an address of a const ref parameter is 
already unsafe if you call the function with a local variable as 
the parameter. If this behavior seems problematic to you when it 
concerns rvalues, it should seem equally problematic when it 
comes to local variables. It doesn't make sense to make passing 
rvalues as const ref parameters illegal because of this problem, 
when passing local variables causes the same problem and is 
legal. It would only make sense to introduce "in ref" whith an 
intent to solve this problem, if local variables would also have 
to be passed as "in ref" (or some kind of scope ref, not 
necessarily const). But that would break pretty much all code 
that uses ref.

The only case I can think of when passing a local variable as 
const ref is safe, but passing an rvalue wouldn't be, is when the 
called function returns the address of the const parameter (or 
assigns it to some other ref parameter).
October 19, 2012
Re: Const ref and rvalues again...
On 2012-10-19 04:48, Timon Gehr wrote:

> Then how to specify that the value of x cannot be escaped?
> I'm in favour of doing it the other way round and disallow escaping of
> ref parameters without an unsafe cast.

"scope" is supposed to be used to prevent this.

-- 
/Jacob Carlborg
October 19, 2012
Re: Const ref and rvalues again...
On Friday, 19 October 2012 at 07:53:30 UTC, Jacob Carlborg wrote:
> On 2012-10-19 04:48, Timon Gehr wrote:
>
>> Then how to specify that the value of x cannot be escaped?
>> I'm in favour of doing it the other way round and disallow 
>> escaping of
>> ref parameters without an unsafe cast.
>
> "scope" is supposed to be used to prevent this.

I like Timon's idea. "scope" is a bad fit in that the default 
should be the safe option. Unfortunately this does have the 
potential to brake lots of code, perhaps even if we limit it to 
@safe code.
An argument could be made that it's worth the breakage for @safe 
code to insure better safety.
October 19, 2012
Re: Const ref and rvalues again...
On 10/19/2012 09:53 AM, Jacob Carlborg wrote:
> On 2012-10-19 04:48, Timon Gehr wrote:
>
>> Then how to specify that the value of x cannot be escaped?
>> I'm in favour of doing it the other way round and disallow escaping of
>> ref parameters without an unsafe cast.
>
> "scope" is supposed to be used to prevent this.
>

Sure, but how?

void goo(scope int* x){
    global0 = x; // should clearly be disallowed
}

void foo(scope ref int*** x){
    global1 = &x; // ?
    global2 = x;  // ?
    global3 = *x; // ?
    globall4 = **x; // ?
}

Maybe we need this:

void foo(scope ref int*** x);   // ?
void foo(ref int(***)scope  x); // no escaping of x, *x, **x
void foo(ref int*(**)scope x);  // may escape **x
void foo(ref int**(*)scope x);  // may escape *x, **x

What about &x?
October 20, 2012
Re: Const ref and rvalues again...
On Friday, 19 October 2012 at 13:00:52 UTC, Timon Gehr wrote:
> On 10/19/2012 09:53 AM, Jacob Carlborg wrote:
>> On 2012-10-19 04:48, Timon Gehr wrote:
>>
>>> Then how to specify that the value of x cannot be escaped?
>>> I'm in favour of doing it the other way round and disallow 
>>> escaping of
>>> ref parameters without an unsafe cast.
>>
>> "scope" is supposed to be used to prevent this.
>>
>
> Sure, but how?
>
> void goo(scope int* x){
>     global0 = x; // should clearly be disallowed
> }
>
> void foo(scope ref int*** x){
>     global1 = &x; // ?
>     global2 = x;  // ?
>     global3 = *x; // ?
>     globall4 = **x; // ?
> }
>
> Maybe we need this:
>
> void foo(scope ref int*** x);   // ?
> void foo(ref int(***)scope  x); // no escaping of x, *x, **x
> void foo(ref int*(**)scope x);  // may escape **x
> void foo(ref int**(*)scope x);  // may escape *x, **x
>
> What about &x?

No scope should mean that you can not escape the address of 
something. So

void goo(scope int* x)
{
    global0 = x;
}

Should be allowed. Scope in this case applies to the pointer. Not 
to the thing it's pointing to. The scope keyword is not 
transitive. That wouldn't make sense. It is perfectly legal to 
have a scoped pointer to something allocated on the heap.


Whereas

void goo(scope ref int x)
{
    global0 = &x;
}

Should NOT be allowed. It looks like it's the same code, but in 
this case x is an integer. In the last example x was a pointer to 
an integer.

So it comes down to this:

void goo(scope int* x)
{
    global0 = x; // copying is allowed
    //global1 = &x; // referencing is not allowed
}
October 21, 2012
Re: Const ref and rvalues again...
On 10/20/2012 08:25 PM, Malte Skarupke wrote:
> ...
>
> So it comes down to this:
>
> void goo(scope int* x)
> {
>      global0 = x; // copying is allowed
>      //global1 = &x; // referencing is not allowed
> }
>
>

That is useless.
October 21, 2012
Re: Const ref and rvalues again...
On Friday, 19 October 2012 at 00:03:49 UTC, Timon Gehr wrote:
> Const is different in D and in C++. Relating const and rvalues 
> is arbitrary and does not make a lot of sense.

It's actually pretty much the same concept in both languages 
except for the transitiveness in D. An implicit rvalue => _const_ 
ref conversion is something completely different than an rvalue 
=> mutable ref conversion, and this distinction is sadly largely 
lost in the linked thread, which is why I tried to re-initiate 
the discussion with another recent thread. Arguments passed by 
mutable references are expected to be changed by the called 
function, so passing rvalues does indeed not make much sense in 
that case (side effects may get lost, quite possibly 
unintentionally).

On Friday, 19 October 2012 at 01:26:35 UTC, Malte Skarupke wrote:
> This is about finding a way that you can define a function 
> which safely accepts lvalues and rvalues without having to make 
> a copy.

EXACTLY! Something telling the compiler: pass the argument by 
const reference instead of a costly const copy, if possible. So 
for an lvalue, pass directly its address; for an rvalue, allocate 
the temporary on the stack and then pass its address:

<code>
T foo(in ref T bla) { return bla; }

T lvalue;
foo(lvalue); // fine

foo(foo(lvalue)); // error: rvalue!
// required compiler magic:
immutable tmp = foo(lvalue); foo(tmp);
/* possibly in dedicated scope for
   immediate destruction of tmp    */
</code>

Currently having to allocate all rvalues manually is frankly both 
ugly and a pain in the ass, as would be the other alternative: 
overloading foo().

On Friday, 19 October 2012 at 03:49:56 UTC, jerro wrote:
> My point was that saving an address of a const ref parameter is 
> already unsafe if you call the function with a local variable 
> as the parameter. If this behavior seems problematic to you 
> when it concerns rvalues, it should seem equally problematic 
> when it comes to local variables. It doesn't make sense to make 
> passing rvalues as const ref parameters illegal because of this 
> problem, when passing local variables causes the same problem 
> and is legal. [...]
> The only case I can think of when passing a local variable as 
> const ref is safe, but passing an rvalue wouldn't be, is when 
> the called function returns the address of the const parameter 
> (or assigns it to some other ref parameter).

Exactly my thoughts regarding this escaping aspect, which I don't 
see as big issue. The compiler magic illustrated in the previous 
example without dedicated scope for temporaries would make 
passing rvalues exactly as safe/unsafe as passing local variables.
October 22, 2012
Re: Const ref and rvalues again...
On 10/22/2012 12:18 AM, martin wrote:
> On Friday, 19 October 2012 at 00:03:49 UTC, Timon Gehr wrote:
>> Const is different in D and in C++. Relating const and rvalues is
>> arbitrary and does not make a lot of sense.
>
> It's actually pretty much the same concept in both languages except for
> the transitiveness in D.

Case closed.
1 2 3 4 5 6
Top | Discussion index | About this forum | D home