April 10, 2015 Re: DIP77 - Fix unsafe RC pass by 'ref' | ||||
---|---|---|---|---|
| ||||
Posted in reply to Martin Nowak | On 4/10/2015 2:20 PM, Martin Nowak wrote: > On 04/10/2015 12:29 PM, Walter Bright wrote: >>> >>> So someone passes an RCO via ref to avoid the inc/dec, and because >>> that imposes >>> safety issues we turn it into some sort of pass by value under the hood, >>> defeating the purpose, and provide an opt-out via @system opAssign. >> >> Or you could pass it by const ref (which is what Rust essentially does). > > Maybe I'm missing something, but this proposal seems to make `ref RCO` > fairly useless, because it creates a copy anyhow. Not if you read the copy elision section. > Assigning a RefCounted is marked @system, That's kind of throwing in the towel, isn't it? > pass-by-ref is @safe. > What's missing, you want to be able to use RefCounted in @safe code? Why > not pass it by value then? That would pin the object and you could elide > the additional inc/dec just like you propose to elide the temporary copies. > It's more efficient to pass a smart pointer like RefCounted by-value anyhow. |
April 10, 2015 Re: DIP77 - Fix unsafe RC pass by 'ref' | ||||
---|---|---|---|---|
| ||||
Posted in reply to Martin Nowak | On 4/10/2015 2:11 PM, Martin Nowak wrote:
> On 04/09/2015 01:10 AM, Walter Bright wrote:
>> http://wiki.dlang.org/DIP77
>
> In the first problem example:
>
> struct S {
> RCArray!T array;
> }
> void main() {
> auto s = S(RCArray!T([T()])); // s.array's refcount is now 1
> foo(s, s.array[0]); // pass by ref
> }
> void foo(ref S s, ref T t) {
> s.array = RCArray!T([]); // drop the old s.array
> t.doSomething(); // oops, t is gone
> }
>
> What do you do to pin s.array?
>
> auto tmp = s;
>
> or
>
> auto tmp = s.array;
>
The latter.
|
April 10, 2015 Re: DIP77 - Fix unsafe RC pass by 'ref' | ||||
---|---|---|---|---|
| ||||
Posted in reply to Martin Nowak | On Friday, 10 April 2015 at 21:20:32 UTC, Martin Nowak wrote:
> Assigning a RefCounted is marked @system, pass-by-ref is @safe.
> What's missing, you want to be able to use RefCounted in @safe code? Why
> not pass it by value then?
This actually sounds quite logical to me - passing an RC object by ref doesn't sound very safe to begin with.
|
April 10, 2015 Re: DIP77 - Fix unsafe RC pass by 'ref' | ||||
---|---|---|---|---|
| ||||
Posted in reply to Walter Bright | On 2015-04-10 21:29:19 +0000, Walter Bright <newshound2@digitalmars.com> said: > On 4/10/2015 2:11 PM, Martin Nowak wrote: >> On 04/09/2015 01:10 AM, Walter Bright wrote: >>> http://wiki.dlang.org/DIP77 >> >> In the first problem example: >> >> struct S { >> RCArray!T array; >> } >> void main() { >> auto s = S(RCArray!T([T()])); // s.array's refcount is now 1 >> foo(s, s.array[0]); // pass by ref >> } >> void foo(ref S s, ref T t) { >> s.array = RCArray!T([]); // drop the old s.array >> t.doSomething(); // oops, t is gone >> } >> >> What do you do to pin s.array? >> >> auto tmp = s; >> >> or >> >> auto tmp = s.array; >> > > The latter. And how is it pinned in this case? struct S { private RCArray!T array; ref T opIndex(int index) return { return array[index]; } void clear() { s.array = RCArray!T([]); } } void main() { auto s = S(RCArray!T([T()])); // s.array's refcount is now 1 foo(s, s[0]); // pass by ref } void foo(ref S s, ref T t) { s.clear(); // drop the old s.array t.doSomething(); // oops, t is gone } -- Michel Fortin michel.fortin@michelf.ca http://michelf.ca |
April 10, 2015 Re: DIP77 - Fix unsafe RC pass by 'ref' | ||||
---|---|---|---|---|
| ||||
Posted in reply to Michel Fortin | On Friday, 10 April 2015 at 21:50:13 UTC, Michel Fortin wrote: > On 2015-04-10 21:29:19 +0000, Walter Bright <newshound2@digitalmars.com> said: > >> On 4/10/2015 2:11 PM, Martin Nowak wrote: >>> On 04/09/2015 01:10 AM, Walter Bright wrote: >>>> http://wiki.dlang.org/DIP77 >>> >>> In the first problem example: >>> >>> struct S { >>> RCArray!T array; >>> } >>> void main() { >>> auto s = S(RCArray!T([T()])); // s.array's refcount is now 1 >>> foo(s, s.array[0]); // pass by ref >>> } >>> void foo(ref S s, ref T t) { >>> s.array = RCArray!T([]); // drop the old s.array >>> t.doSomething(); // oops, t is gone >>> } >>> >>> What do you do to pin s.array? >>> >>> auto tmp = s; >>> >>> or >>> >>> auto tmp = s.array; >>> >> >> The latter. > > And how is it pinned in this case? > > struct S { > private RCArray!T array; > ref T opIndex(int index) return { return array[index]; } > void clear() { s.array = RCArray!T([]); } > } > void main() { > auto s = S(RCArray!T([T()])); // s.array's refcount is now 1 > foo(s, s[0]); // pass by ref > } > void foo(ref S s, ref T t) { > s.clear(); // drop the old s.array > t.doSomething(); // oops, t is gone > } AFAICT it would create a temporary copy of s.array, which would keep t valid. > Nope. It'll scan at compile time the types reachable through the parameters. If any of those types are RCO's that have a type that matches a ref parameter, the ref parameter's RCO will get copied. |
April 10, 2015 Re: DIP77 - Fix unsafe RC pass by 'ref' | ||||
---|---|---|---|---|
| ||||
Posted in reply to Martin Nowak | On Friday, 10 April 2015 at 10:02:01 UTC, Martin Nowak wrote:
> On Wednesday, 8 April 2015 at 23:11:08 UTC, Walter Bright wrote:
>> http://wiki.dlang.org/DIP77
>
> So someone passes an RCO via ref to avoid the inc/dec, and because that imposes safety issues we turn it into some sort of pass by value under the hood, defeating the purpose, and provide an opt-out via @system opAssign.
>
> Wouldn't it more straightforward to make pass-by-ref unsafe (@system) for RCOs?
>
> Then the only thing missing to make this equally powerful, would be an optimization opportunity for the compiler to elide copies of pass-by-value RCOs, e.g. it could avoid calling the postblit when the function retains the refcount.
Only the first pass by ref create a copy. You can then pass the ref down all you want without copy.
That is an acceptable cost IMO.
|
April 10, 2015 Re: DIP77 - Fix unsafe RC pass by 'ref' | ||||
---|---|---|---|---|
| ||||
Posted in reply to Walter Bright | On 04/10/2015 11:29 PM, Walter Bright wrote:
>
> The latter.
Can you update that part in the DIP, it wasn't clear that the temporary selectively pins RCO fields of a normal struct passed by ref.
|
April 10, 2015 Re: DIP77 - Fix unsafe RC pass by 'ref' | ||||
---|---|---|---|---|
| ||||
Posted in reply to Martin Nowak | On Friday, 10 April 2015 at 23:18:59 UTC, Martin Nowak wrote:
> On 04/10/2015 11:29 PM, Walter Bright wrote:
>>
>> The latter.
>
> Can you update that part in the DIP, it wasn't clear that the temporary
> selectively pins RCO fields of a normal struct passed by ref.
If a struct has RCO fields, shouldn't it be an RCO itself, and as such be pinned ?
It sounds like this is implied in the DIP.
|
April 11, 2015 Re: DIP77 - Fix unsafe RC pass by 'ref' | ||||
---|---|---|---|---|
| ||||
Posted in reply to deadalnix | On 2015-04-10 23:22:17 +0000, "deadalnix" <deadalnix@gmail.com> said: > On Friday, 10 April 2015 at 23:18:59 UTC, Martin Nowak wrote: >> On 04/10/2015 11:29 PM, Walter Bright wrote: >>> >>> The latter. >> >> Can you update that part in the DIP, it wasn't clear that the temporary >> selectively pins RCO fields of a normal struct passed by ref. > > If a struct has RCO fields, shouldn't it be an RCO itself, and as such be pinned ? Not necessarily. A @disabled postblit could make it no longer RCO (including a @disabled postblit in one of the fields). > It sounds like this is implied in the DIP. That's what I thought too. But when confronted to a case where that wouldn't work Walter said in this thread that the compiler would make a temporary of the fields. So I'm not too sure what to think anymore. The DIP should clarify what happens with @disabled postblit and RCO fields inside non-RCO structs. -- Michel Fortin michel.fortin@michelf.ca http://michelf.ca |
April 11, 2015 Re: DIP77 - Fix unsafe RC pass by 'ref' | ||||
---|---|---|---|---|
| ||||
Posted in reply to Michel Fortin | On 4/10/2015 2:50 PM, Michel Fortin wrote: > And how is it pinned in this case? > > struct S { > private RCArray!T array; > ref T opIndex(int index) return { return array[index]; } > void clear() { s.array = RCArray!T([]); } > } > void main() { > auto s = S(RCArray!T([T()])); // s.array's refcount is now 1 > foo(s, s[0]); // pass by ref The s[0] is preceded by tmp=s; Because T is reachable from typeof(first argument s) > } > void foo(ref S s, ref T t) { > s.clear(); // drop the old s.array > t.doSomething(); // oops, t is gone > } > |
Copyright © 1999-2021 by the D Language Foundation