digitalmars.D - DIP 36: Rvalue References
- Namespace (1/1) Apr 09 2013 http://wiki.dlang.org/DIP36
- kenji hara (19/21) Apr 09 2013 Similar to "auto ref" but no extra template instantiations
- Dicebot (34/41) Apr 10 2013 That is me to blame. I have convinced Namespace that this is the
- Dicebot (3/4) Apr 11 2013 Kenji, got any comments/objections on this point of view? It is
- kenji hara (13/18) Apr 11 2013 I think 'scope ref' should always pass the address of given argument to ...
- Dicebot (4/6) Apr 11 2013 You don't think exposing creation of temporaries is low level
- kenji hara (21/24) Apr 11 2013 No. In this case, it is the purpose of 'scope ref', not is the
- Dicebot (3/35) Apr 11 2013 I trust your judgement then, will update DIP then. But I am still
- Namespace (5/5) Apr 12 2013 Kenji, what do you think, should we / you create a pull request
- Namespace (5/5) Apr 17 2013 Thanks to Kenji there is now a corresponding pull request:
- Minas Mina (3/8) Apr 17 2013 Finally, I'm tired of copy-pasting the same code just to change
- Namespace (1/3) Apr 17 2013 What do you mean?
- Minas Mina (12/15) Apr 17 2013 This:
- Namespace (4/21) Apr 17 2013 Oh, I thought you had anything against the DIP. ^^
- Zach the Mystic (8/11) Apr 17 2013 Yes, this temp ref issue is far more important than the ref
- Namespace (17/25) Apr 20 2013 That is true, but it makes the impression that, with the
- deadalnix (3/14) Apr 20 2013 I don't think adding more to the language is the sane thing to do
- Namespace (5/7) Apr 20 2013 Why not? Could you explain this?
- deadalnix (8/16) Apr 20 2013 Listen, this issue is very real, but it is mostly about
- Namespace (8/15) Apr 20 2013 As far as I remember, you were in favor of the introduction of
- deadalnix (4/20) Apr 20 2013 Half of the standard lib is broken because it is annotated
- Dicebot (4/4) Apr 20 2013 You miss quite an important point - DIP36 does not add new
- Timon Gehr (5/9) Apr 20 2013 _New meaning_ is assigned to existing grammar whose original purpose is
- Manu (38/48) Apr 20 2013 That's not what scope does. Scope promises that the variables will not
- Zach the Mystic (6/37) Apr 20 2013 It's hard to fully understand this example without getMatrix()
- Manu (13/49) Apr 20 2013 s
- deadalnix (7/20) Apr 20 2013 If that is your concern then the DIP36 is a very bad answer to it
- Dicebot (6/12) Apr 21 2013 Automatic annotations are indicators of broken language. If
- Zach the Mystic (18/24) Apr 21 2013 It's possible to make it an error to pass a stack variable to a
- deadalnix (6/24) Apr 21 2013 This is why the notion of lifetime is needed.
- Zach the Mystic (3/36) Apr 20 2013 Yeah, that's kind of what I meant when I said it's a two-for-one
- Timon Gehr (2/5) Apr 21 2013 I prefer to buy separate products separately.
- Manu (3/10) Apr 21 2013 I'm confused, what 2 products are you getting? Which of said products do
- Timon Gehr (14/33) Apr 21 2013 That is the intention, but this formulation is awfully imprecise. Hence
- Manu (18/58) Apr 21 2013 What's the problem here?
- Timon Gehr (28/62) Apr 21 2013 What does 'scope' bind to? How to make it bind to something else (if at
- Zach the Mystic (19/36) Apr 21 2013 I agree this is an issue. We need to enumerate the use cases. Is
- Namespace (6/24) Apr 22 2013 Yes, both cases are allowed. Dicebot initially wanted that scope
- Diggory (26/26) Apr 22 2013 I realise I'm new here but this seems to be suggesting a whole
- Namespace (8/34) Apr 22 2013 This DIP already suggest 'in ref' besides 'scope ref'. 'in' is a
- Diggory (30/77) Apr 22 2013 The definition was somewhat hidden in the language reference and
- Namespace (16/25) Apr 22 2013 I must have overlooked this all the time. I will clean up this
- Zach the Mystic (29/49) Apr 22 2013 In other words, 'scope' would be the default and require no
- Dicebot (3/6) Apr 23 2013 I had quite an impression this was prohibited mostly because of
- Timon Gehr (2/9) Apr 23 2013 It is disallowed in @system code.
- Dicebot (3/4) Apr 23 2013 Ye, I know and always took it as yet another "we care mostly for
- John Colvin (4/21) Apr 20 2013 Sadly, I have to agree on this. As nice as many new feature ideas
- Namespace (9/12) Apr 20 2013 There is no reason to prioritize DIP 36. Kenji, Dicebot and I did
- John Colvin (9/21) Apr 20 2013 How about "on hold"? (Not that I have any say in it at all)
- Namespace (11/19) Apr 20 2013 As long as it is implemented in the near future and we must not
- deadalnix (5/12) Apr 20 2013 The DIP for instance, consider that const scope ref is
- Dicebot (7/20) Apr 21 2013 At least some objections that make sense and I'd love to see in
- Zach the Mystic (8/18) Apr 21 2013 The only thing I could think of was if you want to 'ref' a
- Zach the Mystic (3/7) Apr 21 2013 ('nice' in the sense that it would prove the suggestion to be
- Dicebot (5/12) Apr 23 2013 Taking consistent approach with "ref", they all should have same
- Minas Mina (2/19) Apr 20 2013 I thought D was driven by its community.
- Timon Gehr (2/4) Apr 20 2013 (This is its community.)
- Andrei Alexandrescu (23/30) Apr 22 2013 In a way I wish my not being polite would be the main bottleneck for
- Tove (9/15) Apr 22 2013 Why isn't DIP36 "scope ref" be future compatible with a future
- Namespace (19/44) Apr 22 2013 I'm sorry that you take it so personally, but I know from
- Dicebot (24/48) Apr 23 2013 Thanks for your time. Sometimes even simple "Have seen it, will
- Andrei Alexandrescu (13/43) Apr 23 2013 Yes.
- Dicebot (4/7) Apr 23 2013 Well, ok, that explains everything.
- Manu (25/68) Apr 23 2013 How does it overlap ref? It simply justifies the argument with an extra
- Andrei Alexandrescu (28/103) Apr 23 2013 The best setup would be:
- Steven Schveighoffer (9/17) Apr 23 2013 So no more returning ref? Because if you allow returning ref, you lose ...
- Diggory (2/5) Apr 23 2013 The rules from DIP25/35 show how you can return refs while still
- Steven Schveighoffer (26/31) Apr 23 2013 Those rules disallow the following valid code:
- Diggory (8/8) Apr 23 2013 In that example you could make opOpAssign take a "const ref" and
- Andrei Alexandrescu (4/9) Apr 23 2013 If we can't return ref, ref has failed. (This is what makes the entire
- Manu (7/19) Apr 23 2013 I think the key that's not in this DIP is that it should also return 'sc...
- Andrei Alexandrescu (6/24) Apr 23 2013 We prefer to simplify. Use ref safely for scoped pass-down of resources,...
- Mehrdad (5/7) Apr 23 2013 I think it's fairly well-understood, probably with the same
- Manu (38/138) Apr 23 2013 That's not a good setup at all. It still doesn't make sense.
- Andrei Alexandrescu (11/45) Apr 23 2013 Well "auto ref" means "I don't care whether this is ref or not".
- Timon Gehr (8/57) Apr 23 2013 or "scope ref", to be fair. scope ref on a template would behave
- Steven Schveighoffer (4/8) Apr 23 2013 I agree with this. If @safe code is all that is affected, we will be we...
- Timon Gehr (19/27) Apr 23 2013 Another possibility I consider fine is to implement what Andrei suggests...
- kenji hara (25/44) Apr 23 2013 First of all, we should define words for the discussion.
- Timon Gehr (6/18) Apr 24 2013 We could specify that if there is no influence (to be made more precise)...
- Zach the Mystic (17/36) Apr 20 2013 Patience!
- Namespace (2/2) Apr 21 2013 Well perhaps I am too hasty. I'll wait and see what is happening.
- Zach the Mystic (19/50) Apr 11 2013 I think this is another case of two different features which may
- Zach the Mystic (41/42) Apr 09 2013 // Does not pretend to be @safe any more
- kenji hara (25/64) Apr 09 2013 I think having both 'ref' and 'scope ref' is still reasonable, because:
- Zach the Mystic (45/73) Apr 09 2013 'foo(1) = 10' is indeed completely useless, but I don't think all
- Zach the Mystic (10/20) Apr 09 2013 When said 'bar(1)' was disallowed, I meant that it was considered
- Manu (16/88) Apr 09 2013 Why are you suggesting changing scope to imply ref? This seems wrong. sc...
- Zach the Mystic (11/14) Apr 09 2013 To be clear, I suggested it, not Kenji. The reason scope could
- Manu (9/22) Apr 09 2013 It is though, in the case I demonstrated. A value type can aggregate a
- Mehrdad (3/4) Apr 23 2013 Delegates?
- Zach the Mystic (5/9) Apr 23 2013 Well, I don't know the formal definition of a delegate, but I
- Zach the Mystic (17/26) Apr 10 2013 I think this is a subtle point, but I don't think it's correct. I
- Dicebot (10/11) Apr 23 2013 Kind of. I am thinking that scope is best when transitive for
- Timon Gehr (6/16) Apr 23 2013 (Both of these are in error because static variables are initialized at
- Dicebot (10/15) Apr 23 2013 Because it is an attempt to take/store address of a scope
- kenji hara (9/30) Apr 09 2013 I say that 'scope' itself should not imply 'ref'. It is *possible* but
- Manu (10/46) Apr 09 2013 I think this is a tool that will greatly enhance working with @safe in t...
- Dicebot (7/11) Apr 10 2013 Safety of "ref" is not problem that this DIP tries to solve. It
- Zach the Mystic (5/16) Apr 10 2013 My proposed DIP35 uses 'scope' to enhance DIP25. I don't believe
- Dicebot (8/26) Apr 10 2013 And how it is relevant to DIP36? It solves specific issue. It
- Zach the Mystic (18/35) Apr 10 2013 I would say, if you are going to use a keyword ('scope' in this
- Manu (4/5) Apr 09 2013 YES PLEASE!!
- Dicebot (5/9) Apr 10 2013 When I initially volunteered to help formalize it I had no strong
- deadalnix (3/4) Apr 10 2013 I see no point in adding that much complexity for something that
- Dicebot (4/8) Apr 10 2013 Can you explain this a bit more extensively, probably with some
- Namespace (4/13) Apr 10 2013 I think he means that the Compiler could/should decide, if
- Manu (5/24) Apr 10 2013 Right. Yeah, seems more complex for sure. It's also
- Minas Mina (1/1) Apr 10 2013 I hope this proposal gets implemented soon :)
- deadalnix (11/46) Apr 10 2013 It is certainly more complex on the compiler implementation side.
- Dicebot (13/23) Apr 10 2013 DIP36 was intentionally tweaked in such way so that compiler is
- Manu (5/10) Apr 10 2013 Where's the complexity? I find it intuitive and super useful.
- Jonas Drewsen (18/18) Apr 11 2013 Isn's it too strict? The following example would not work because
2013/4/10 Namespace <rswhite4 googlemail.com>http://wiki.dlang.org/DIP36Typo:Similar to "auto ref" but no extra template instantations.Similar to "auto ref" but no extra template instantiations One question: void test1(scope ref A a) {} test1(A(42)); // safe, this temporary value is valid for mutation and "scope" ensures it does not leak scope A a =3D A(23); // no difference test1(a); void test32(T)(scope ref T id) {} test32(1337); // Prohibited, no address for "1337" test32(a.id); // fine and safe Why test32 does not accept rvalue like test1? I think that "scope ref" should always behave same for rvalue argument - create temporary and take its address to "scope ref" parameter. Consistent behavior with any types is important for the generic programming. Other than comment, looks good. Good work, Randy and =D0=9C=D0=B8=D1=85=D0= =B0=D0=B8=D0=BB! Kenji Hara
Apr 09 2013
On Wednesday, 10 April 2013 at 00:41:54 UTC, kenji hara wrote:Why test32 does not accept rvalue like test1? I think that "scope ref" should always behave same for rvalue argument - create temporary and take its address to "scope ref" parameter. Consistent behavior with any types is important for the generic programming.That is me to blame. I have convinced Namespace that this is the way to go in private conversation and hope to do the same with you ;) Consistent behavior is important but it does not change the fact that there two types of rvalues in the language - raw literals (42, A.init) and constructed temporaries (A()). Accepting rvalues of the first type in as mutable references may be consistent from the point of view of syntax by _extremely_ confusing semantics-wise: void foo(scope ref int x) { x = 32; } void main() { foo(42); // erm, 32 is the new 42 or ref is not actually ref? } Beauty of "in ref" is that in that case user can't use it in any way that may disclose the fact the temporary variable for non-adressable entities is created. For mutable scope ref it is not the case and we must leak implementation details, which is never good. Another concern is that if someone tries to pass "42" as a mutable ref, most likely he does not really wants it to be mutable and "in ref" is a better match. This may not be consistent from the point of view of generic code, but it is now consistent from the point of view of programmer : A(...) construct always create temporaries, raw value literals never do (well, they will for "in ref" but you can't observe it). I think this is much more important. One extra thing to note is that test32 may actually work if it instantiates T as "const int" for 42 (making it "in ref" essentially), but I don't know if D rules allow it.
Apr 10 2013
On Wednesday, 10 April 2013 at 07:43:57 UTC, Dicebot wrote:...Kenji, got any comments/objections on this point of view? It is not that late to change it back ;)
Apr 11 2013
I think 'scope ref' should always pass the address of given argument to the function body. Because 'ref' always means "pass the address of given argument". So, if given argument is an rvalue, compiler will allocate a temporary on stack, save the rvalue in it, and take its address. If argument is an lvalue, take its address directly. It should be always true, eve if the parameter type is small int. Essentially language semantics should not reflect low level implementation detail. After DIP36 is accepted, we will get a full set of tools for efficiency - T, ref T, and scope ref T. From the toolbox, you can choose the most efficient storage class based on the T. void foo(MostEfficientParameters!(int, string, S, int[1024]) params) { ... } Kenji Hara 2013/4/11 Dicebot <m.strashun gmail.com>On Wednesday, 10 April 2013 at 07:43:57 UTC, Dicebot wrote:...Kenji, got any comments/objections on this point of view? It is not that late to change it back ;)
Apr 11 2013
You don't think exposing creation of temporaries is low level implementation detail? On Thursday, 11 April 2013 at 08:14:00 UTC, kenji hara wrote:... Kenji Hara
Apr 11 2013
2013/4/11 Dicebot <m.strashun gmail.com>You don't think exposing creation of temporaries is low level implementation detail?No. In this case, it is the purpose of 'scope ref', not is the implementation details. What is the language semantics and what is the implementation detail - that varies depending on what is properly supported in the language. D explicitly distinguishes lvalues and rvalues, and also defines that rvalue cannot be taken its address (== reference). The purpose of 'scope ref' is that the parameter can be received both lvalues and rvalues with one function body. To receive lvalues, scope ref should take the address of them. As a conclusion, to receive rvalues temporary creation is necessary in caller site. Yes, it mostly represents implementation details, but it is still description of language semantics. This confusion is almost inevitable. Because the essential purpose of 'scope ref' is already "efficiency". Furthermore, note that the desired "efficiency" is not "the speed of argument passing". I recognize that it is "to avoid code bloating of function body". If you need "most efficient argument passing", you should choose it from the argument type. 'scope ref' is not a thing to make the choice automatic. Kenji Hara
Apr 11 2013
On Thursday, 11 April 2013 at 09:27:11 UTC, kenji hara wrote:No. In this case, it is the purpose of 'scope ref', not is the implementation details. What is the language semantics and what is the implementation detail - that varies depending on what is properly supported in the language. D explicitly distinguishes lvalues and rvalues, and also defines that rvalue cannot be taken its address (== reference). The purpose of 'scope ref' is that the parameter can be received both lvalues and rvalues with one function body. To receive lvalues, scope ref should take the address of them. As a conclusion, to receive rvalues temporary creation is necessary in caller site. Yes, it mostly represents implementation details, but it is still description of language semantics. This confusion is almost inevitable. Because the essential purpose of 'scope ref' is already "efficiency". Furthermore, note that the desired "efficiency" is not "the speed of argument passing". I recognize that it is "to avoid code bloating of function body". If you need "most efficient argument passing", you should choose it from the argument type. 'scope ref' is not a thing to make the choice automatic. Kenji HaraI trust your judgement then, will update DIP then. But I am still afraid of confusion.
Apr 11 2013
Kenji, what do you think, should we / you create a pull request for the proposal? Most seem to be very satisfied with the proposal. In addition, a pull request would rather cause that Walter and Andrei join the discussion.
Apr 12 2013
Thanks to Kenji there is now a corresponding pull request: https://github.com/D-Programming-Language/dmd/pull/1903 Let us hope that it will be quickly merged. I still hope that Andrei or Walter say something to this topic. Maybe we have a chance with this pull request. ;)
Apr 17 2013
On Wednesday, 17 April 2013 at 17:50:07 UTC, Namespace wrote:Thanks to Kenji there is now a corresponding pull request: https://github.com/D-Programming-Language/dmd/pull/1903 Let us hope that it will be quickly merged. I still hope that Andrei or Walter say something to this topic. Maybe we have a chance with this pull request. ;)Finally, I'm tired of copy-pasting the same code just to change to "ref". :)
Apr 17 2013
Finally, I'm tired of copy-pasting the same code just to change to "ref". :)What do you mean?
Apr 17 2013
On Wednesday, 17 April 2013 at 19:29:51 UTC, Namespace wrote:This: /// dot product of two Vector3 vectors auto dot(T) (Vector3!T u, Vector3!T v) safe pure nothrow { return u.x * v.x + u.y * v.y + u.z * v.z; } /// dot product of two Vector3 vectors auto dot(T) (ref Vector3!T u, ref Vector3!T v) safe pure nothrow { return u.x * v.x + u.y * v.y + u.z * v.z; }Finally, I'm tired of copy-pasting the same code just to change to "ref". :)What do you mean?
Apr 17 2013
On Wednesday, 17 April 2013 at 20:18:56 UTC, Minas Mina wrote:On Wednesday, 17 April 2013 at 19:29:51 UTC, Namespace wrote:Oh, I thought you had anything against the DIP. ^^ Yes that annoys me as well. That's why I really hope that we can fix this vexing issue soon. :)This: /// dot product of two Vector3 vectors auto dot(T) (Vector3!T u, Vector3!T v) safe pure nothrow { return u.x * v.x + u.y * v.y + u.z * v.z; } /// dot product of two Vector3 vectors auto dot(T) (ref Vector3!T u, ref Vector3!T v) safe pure nothrow { return u.x * v.x + u.y * v.y + u.z * v.z; }Finally, I'm tired of copy-pasting the same code just to change to "ref". :)What do you mean?
Apr 17 2013
On Wednesday, 17 April 2013 at 20:27:27 UTC, Namespace wrote:Oh, I thought you had anything against the DIP. ^^ Yes that annoys me as well. That's why I really hope that we can fix this vexing issue soon. :)Yes, this temp ref issue is far more important than the ref safety issue I've been concerning myself with. I wouldn't mind if the objections I've brought up fall in favor of whatever it takes to get temp ref solved. ref safety is important, but it's nowhere near the shear *annoyingness* factor of rvalue temp refs. But someone besides me would need to evaluate both DIP 35 & 36 to see if there were any real conflicts there.
Apr 17 2013
Yes, this temp ref issue is far more important than the ref safety issue I've been concerning myself with. I wouldn't mind if the objections I've brought up fall in favor of whatever it takes to get temp ref solved. ref safety is important, but it's nowhere near the shear *annoyingness* factor of rvalue temp refs.That is true, but it makes the impression that, with the exception of Kenji, none of the core developers is interested in a solution to this problem. The DIP was not much discussed and the pull request is regularly overlooked / ignored. Also in the discussion on the pull request no comments for Walter or Andrei are found. Although the pull is complete and has passed all the tests and would be ready to merge. Also this thread is completely ignored even though both write in this forum regularly and participate in other discussions. To me this makes the impression that they were not interested in this problem (or in our solution to the problem). Either they want the problem does not solve or try to solve it in their own way and that can take a very long time. At least an annotation what of both is the case or if I see it completely wrong, would be polite.But someone besides me would need to evaluate both DIP 35 & 36 to see if there were any real conflicts there.Yes that would be good.
Apr 20 2013
On Saturday, 20 April 2013 at 14:42:57 UTC, Namespace wrote:I don't think adding more to the language is the sane thing to do right now.Yes, this temp ref issue is far more important than the ref safety issue I've been concerning myself with. I wouldn't mind if the objections I've brought up fall in favor of whatever it takes to get temp ref solved. ref safety is important, but it's nowhere near the shear *annoyingness* factor of rvalue temp refs.That is true, but it makes the impression that, with the exception of Kenji, none of the core developers is interested in a solution to this problem. The DIP was not much discussed and the pull request is regularly overlooked / ignored.
Apr 20 2013
I don't think adding more to the language is the sane thing to do right now.Why not? Could you explain this? This issue is discussed since more than a year and it is a very annoying issue. And even if Walter and Andrei are of this opinion, it would still only polite when they explain in detail why they think this.
Apr 20 2013
On Saturday, 20 April 2013 at 15:17:39 UTC, Namespace wrote:Listen, this issue is very real, but it is mostly about performance. I'll tell you something : the best performance improvement is the one that bring your program from non working state to working one. And right now, many existing feature are broken. The let's add whatever feature we have in mind is the very cause of the state of the language right now.I don't think adding more to the language is the sane thing to do right now.Why not? Could you explain this? This issue is discussed since more than a year and it is a very annoying issue. And even if Walter and Andrei are of this opinion, it would still only polite when they explain in detail why they think this.
Apr 20 2013
Listen, this issue is very real, but it is mostly about performance. I'll tell you something : the best performance improvement is the one that bring your program from non working state to working one. And right now, many existing feature are broken. The let's add whatever feature we have in mind is the very cause of the state of the language right now.As far as I remember, you were in favor of the introduction of the feature "attribute inference for auto functions". Also a new feature but none that would solve problems which are discussed since more than a year. Furthermore this issue should be solved with the introduction of "auto ref" (AFAIK introduced with dmd 2.035?). So this is not like "add whatever feature" but rather "fix an issue, that is often discussed and annoys many people".
Apr 20 2013
On Saturday, 20 April 2013 at 15:39:42 UTC, Namespace wrote:Half of the standard lib is broken because it is annotated incorrectly.Listen, this issue is very real, but it is mostly about performance. I'll tell you something : the best performance improvement is the one that bring your program from non working state to working one. And right now, many existing feature are broken. The let's add whatever feature we have in mind is the very cause of the state of the language right now.As far as I remember, you were in favor of the introduction of the feature "attribute inference for auto functions". Also a new feature but none that would solve problems which are discussed since more than a year.Furthermore this issue should be solved with the introduction of "auto ref" (AFAIK introduced with dmd 2.035?). So this is not like "add whatever feature" but rather "fix an issue, that is often discussed and annoys many people".DIP36 discuss the addition of new features.
Apr 20 2013
You miss quite an important point - DIP36 does not add new feature. It partially defines existing feature (scope) to replace an existing but broken solution (auto ref). Nothing new is really added to the language, only existing stuff better defined.
Apr 20 2013
On 04/20/2013 05:56 PM, Dicebot wrote:You miss quite an important point - DIP36 does not add new feature. It partially defines existing feature (scope) to replace an existing but broken solution (auto ref). Nothing new is really added to the language, only existing stuff better defined._New meaning_ is assigned to existing grammar whose original purpose is at most loosely related to the _new_ features. I do not think that making 'scope' indicate an rvalue reference is particularly future proof.
Apr 20 2013
On 21 April 2013 06:51, Timon Gehr <timon.gehr gmx.ch> wrote:On 04/20/2013 05:56 PM, Dicebot wrote:tYou miss quite an important point - DIP36 does not add new feature. It partially defines existing feature (scope) to replace an existing but broken solution (auto ref). Nothing new is really added to the language, only existing stuff better defined._New meaning_ is assigned to existing grammar whose original purpose is a=most loosely related to the _new_ features. I do not think that making 'scope' indicate an rvalue reference is particularly future proof.That's not what scope does. Scope promises that the variables will not escape the scope. And as such, just happens to make passing a temporary by ref safe. It does not implement r-value ref's. It simply allows refs to temporaries to be considered a safe operation. This DIP is actually likely to solve an important source of problems, consider: void func(const ref matrix m); func(x.getMatrix()); // compile error! // ... matrix temp =3D x.getMatrix(); func(temp); // no more compile error! (but equally unsafe/dangerous) In this example, the 'solution', which is what everybody does right now, is exactly as unsafe as the attempted call with the r-value. ref, as in the language right now, is a fundamentally unsafe operation... and not only is it technically unsafe, a programmer can't even know if it is practically unsafe or not. Since they have a habit of using this hack, they may unknowingly use it in a call site where it's not *practically* safe to do it. They can't know, and by habit (and frustration) they're trained to use this hack everywhere. With 'scope ref' (or 'in ref'), the programmer now has a guide to say whether it's safe to pass a temporary or not. In the future, if the function does not receive scope ref, perhaps the programmer will start to presume that it is NOT safe to pass a temporary, and stop doing so via the current local-variable hack. scope was always intended to implement this promise as far as I'm lead to believe(?). <Side rant> the first one that comes up, every time (which really doesn't help with first impressions), and I'm fairly sure every single person I've introduced to D has complained about this. It's kind of embarrassing when I'm saying that D is really cool, and then I have to start making excuses and apologising for this, and assure them that it's a known issue, and it'll be fixed one day.
Apr 20 2013
On Sunday, 21 April 2013 at 00:51:31 UTC, Manu wrote:That's not what scope does. Scope promises that the variables will not escape the scope. And as such, just happens to make passing a temporary by ref safe. It does not implement r-value ref's. It simply allows refs to temporaries to be considered a safe operation.It's a two-fer! (2 for 1 deal)This DIP is actually likely to solve an important source of problems, consider: void func(const ref matrix m); func(x.getMatrix()); // compile error! // ... matrix temp = x.getMatrix(); func(temp); // no more compile error! (but equally unsafe/dangerous)It's hard to fully understand this example without getMatrix() defined, and why func() is unsafe (does it escape the reference?). Help!<Side rant> complaint. It's the first one that comes up, every time (which really doesn't help with first impressions), and I'm fairly sure every single person I've introduced to D has complained about this. It's kind of embarrassing when I'm saying that D is really cool, and then I have to start making excuses and apologising for this, and assure them that it's a known issue, and it'll be fixed one day.Yikes.
Apr 20 2013
On 21 April 2013 11:36, Zach the Mystic <reachzach gggggmail.com> wrote:On Sunday, 21 April 2013 at 00:51:31 UTC, Manu wrote:byThat's not what scope does. Scope promises that the variables will not escape the scope. And as such, just happens to make passing a temporary =sref safe. It does not implement r-value ref's. It simply allows refs to temporarie=definition: matrix getMatrix(T x); // this is all you know That's the point of the example. You _don't know_ if func() is unsafe, does it escape the reference? But you need to pass a temp anyway, you have no bearing on whether you should just hack it to work, or reconsider the problem. And when 99 times out of 100, the correct answer is 'hack it to work', you're basically asking for a spectacular bug in that other 1% of cases. <Side rant>to be considered a safe operation.It's a two-fer! (2 for 1 deal) This DIP is actually likely to solve an important source of problems,consider: void func(const ref matrix m); func(x.getMatrix()); // compile error! // ... matrix temp =3D x.getMatrix(); func(temp); // no more compile error! (but equally unsafe/dangerous)It's hard to fully understand this example without getMatrix() defined, and why func() is unsafe (does it escape the reference?). Help!nthe first one that comes up, every time (which really doesn't help with first impressions), and I'm fairly sure every single person I've introduced to D has complained about this. It's kind of embarrassing when I'm saying that D is really cool, and the=I have to start making excuses and apologising for this, and assure them that it's a known issue, and it'll be fixed one day.Yikes.
Apr 20 2013
On Sunday, 21 April 2013 at 02:13:54 UTC, Manu wrote:definition: matrix getMatrix(T x); // this is all you know That's the point of the example. You _don't know_ if func() is unsafe, does it escape the reference? But you need to pass a temp anyway, you have no bearing on whether you should just hack it to work, or reconsider the problem. And when 99 times out of 100, the correct answer is 'hack it to work', you're basically asking for a spectacular bug in that other 1% of cases.If that is your concern then the DIP36 is a very bad answer to it : - It require extra anotation, which wont be added most of the time. - It is inferior, and impair the introduction of lifetime. This isn't even discussed.
Apr 20 2013
On Sunday, 21 April 2013 at 02:50:02 UTC, deadalnix wrote:If that is your concern then the DIP36 is a very bad answer to it : - It require extra anotation, which wont be added most of the time.Automatic annotations are indicators of broken language. If someone will forget this one, he won't be able to use rvalues, no problem.- It is inferior, and impair the introduction of lifetime. This isn't even discussed.Scope is the absolute minimal lifetime which is needed for this DIP. Any other lifetime options are simply irrelevant.
Apr 21 2013
On Sunday, 21 April 2013 at 02:50:02 UTC, deadalnix wrote:If that is your concern then the DIP36 is a very bad answer to it : - It require extra anotation, which wont be added most of the time.It's possible to make it an error to pass a stack variable to a non-'scope' ref parameter. Or to make it an error in safe code only. But those may be extreme measures. This also raises the issue that some types of escape are more dangerous than others. ref T func(ref T a) { return a; // Escape by return, safe if tracked at call site T* p = &a; // Escape to local pointer, safe? if *p is tracked static T* s = &a; // Escape by global pointer, system } In this sense, 'scope' is a blunt instrument, because you might want to say, 'returnable, but not globally assignable'. 'scope' is also the kind of thing which might be better as the default than as something you must specifically add. But then we'd need an attribute ' noscope' or something like that. Ugh.- It is inferior, and impair the introduction of lifetime. This isn't even discussed.You've mentioned lifetime a couple times. Can you show what lifetime is and show how it contrasts with the current proposal, particularly DIP25?
Apr 21 2013
On Sunday, 21 April 2013 at 16:02:35 UTC, Zach the Mystic wrote:On Sunday, 21 April 2013 at 02:50:02 UTC, deadalnix wrote:No they aren't.If that is your concern then the DIP36 is a very bad answer to it : - It require extra anotation, which wont be added most of the time.It's possible to make it an error to pass a stack variable to a non-'scope' ref parameter. Or to make it an error in safe code only. But those may be extreme measures.This also raises the issue that some types of escape are more dangerous than others.This is why the notion of lifetime is needed.'scope' is also the kind of thing which might be better as the default than as something you must specifically add. But then we'd need an attribute ' noscope' or something like that. Ugh.Inference is always a solution.Here is a good link to start : http://smallcultfollowing.com/babysteps/blog/2012/07/17/borrowed-pointer-tutorial/- It is inferior, and impair the introduction of lifetime. This isn't even discussed.You've mentioned lifetime a couple times. Can you show what lifetime is and show how it contrasts with the current proposal, particularly DIP25?
Apr 21 2013
On Sunday, 21 April 2013 at 02:13:54 UTC, Manu wrote:Yeah, that's kind of what I meant when I said it's a two-for-one deal. You get to pass temps, and you get safety checking too.This DIP is actually likely to solve an important source of problems,definition: matrix getMatrix(T x); // this is all you know That's the point of the example. You _don't know_ if func() is unsafe, does it escape the reference? But you need to pass a temp anyway, you have no bearing on whether you should just hack it to work, or reconsider the problem. And when 99 times out of 100, the correct answer is 'hack it to work', you're basically asking for a spectacular bug in that other 1% of cases.consider: void func(const ref matrix m); func(x.getMatrix()); // compile error! // ... matrix temp = x.getMatrix(); func(temp); // no more compile error! (but equally unsafe/dangerous)It's hard to fully understand this example without getMatrix() defined, and why func() is unsafe (does it escape the reference?). Help!
Apr 20 2013
On 04/21/2013 06:27 AM, Zach the Mystic wrote:... Yeah, that's kind of what I meant when I said it's a two-for-one deal. You get to pass temps, and you get safety checking too.I prefer to buy separate products separately.
Apr 21 2013
On 22 April 2013 04:23, Timon Gehr <timon.gehr gmx.ch> wrote:On 04/21/2013 06:27 AM, Zach the Mystic wrote:I'm confused, what 2 products are you getting? Which of said products do you actually object to?... Yeah, that's kind of what I meant when I said it's a two-for-one deal. You get to pass temps, and you get safety checking too.I prefer to buy separate products separately.
Apr 21 2013
On 04/21/2013 02:51 AM, Manu wrote:On 21 April 2013 06:51, Timon Gehr <timon.gehr gmx.ch <mailto:timon.gehr gmx.ch>> wrote: On 04/20/2013 05:56 PM, Dicebot wrote: You miss quite an important point - DIP36 does not add new feature. It partially defines existing feature (scope) to replace an existing but broken solution (auto ref). Nothing new is really added to the language, only existing stuff better defined. _New meaning_ is assigned to existing grammar whose original purpose is at most loosely related to the _new_ features. I do not think that making 'scope' indicate an rvalue reference is particularly future proof. That's not what scope does. Scope promises that the variables will not escape the scope.That is the intention, but this formulation is awfully imprecise. Hence nothing has been implemented. void foo(scope ref int x){ ... } void foo(scope int* x){ ... } void foo(scope ref int* x){ ... } // ??? struct S{ scope S* x; // ??? }And as such, just happens to make passing a temporary by ref safe. ...But this is not about safety! Passing an rvalue by ref is disallowed even in system code. Hence 'scope' is assigned a meaning different from its intention. The DIP also aims to add more special behaviour to built-in literals.
Apr 21 2013
On 22 April 2013 03:39, Timon Gehr <timon.gehr gmx.ch> wrote:On 04/21/2013 02:51 AM, Manu wrote:What's the problem here? // ???On 21 April 2013 06:51, Timon Gehr <timon.gehr gmx.ch <mailto:timon.gehr gmx.ch>> wrote: On 04/20/2013 05:56 PM, Dicebot wrote: You miss quite an important point - DIP36 does not add new feature. It partially defines existing feature (scope) to replace an existing but broken solution (auto ref). Nothing new is really added to the language, only existing stuff better defined. _New meaning_ is assigned to existing grammar whose original purpose is at most loosely related to the _new_ features. I do not think that making 'scope' indicate an rvalue reference is particularly future proof. That's not what scope does. Scope promises that the variables will not escape the scope.That is the intention, but this formulation is awfully imprecise. Hence nothing has been implemented. void foo(scope ref int x){ ... } void foo(scope int* x){ ... } void foo(scope ref int* x){ ... }struct S{ scope S* x; // ??? }I don't think scope on a struct member makes a lot of sense. scope on a local variable declaration makes sense though, it would be able to be assigned from another scope variable. Although I would say the same about ref on a local variable declaration, which is disallowed for completely unknown reasons. And as such, just happens to make passing a temporaryPassing an r-value by ref is disallowed for arbitrary reasons. It can easily create a temporary on the spot, but it doesn't, because it's not considered good form to pass a temp to a function by ref. This offers the possibility to pass a temp safely, and consequently, the compiler may generate the temp for you. Explain to me what meaning 'scope' has been assigned that is different from it's intention? And what 'special behaviour'? I honestly can't understand the objections, by you or deadalnix. Can someone actually explain the problem clearly?by ref safe. ...But this is not about safety! Passing an rvalue by ref is disallowed even in system code. Hence 'scope' is assigned a meaning different from its intention. The DIP also aims to add more special behaviour to built-in literals.
Apr 21 2013
On 04/21/2013 10:38 PM, Manu wrote:... That's not what scope does. Scope promises that the variables will not escape the scope. That is the intention, but this formulation is awfully imprecise. Hence nothing has been implemented. void foo(scope ref int x){ ... } void foo(scope int* x){ ... } void foo(scope ref int* x){ ... } What's the problem here?What does 'scope' bind to? How to make it bind to something else (if at all)? Does the proposal lock down 'scope' to always refer to every single pointer in the argument?// ??? struct S{ scope S* x; // ??? } I don't think scope on a struct member makes a lot of sense.void main() safe{ S s; auto t = S(&t); }scope on a local variable declaration makes sense though, it would be able to be assigned from another scope variable.'scope' shouldn't restrict the abstraction capability of structs.Although I would say the same about ref on a local variable declaration, which is disallowed for completely unknown reasons. And as such, just happens to make passing a temporary by ref safe. ... But this is not about safety! Passing an rvalue by ref is disallowed even in system code. Hence 'scope' is assigned a meaning different from its intention. The DIP also aims to add more special behaviour to built-in literals. Passing an r-value by ref is disallowed for arbitrary reasons.Reasons not closely related to lack of 'scope'. So why bind the new rule to scope?It can easily create a temporary on the spot, but it doesn't, because it's not considered good form to pass a temp to a function by ref. ...Yet this is what everyone appears to want to do.Explain to me what meaning 'scope' has been assigned that is different from it's intention?Implicit binding of (some) rvalues to ref.And what 'special behaviour'?If I read the ambiguous wording of the proposal correctly, the following code will be disallowed: void foo1(scope ref int x) { } void main(){ foo1(1); // error } But this will be fine: void foo1(scope ref int x) { } int bar(){ return 1; } void main(){ foo1(bar()); }I honestly can't understand the objections, by you or deadalnix. Can someone actually explain the problem clearly?Having a lot of ad-hoc programming language rules leads to a clumsy design. Eg. see the evolution of C++.
Apr 21 2013
On Sunday, 21 April 2013 at 22:16:14 UTC, Timon Gehr wrote:What does 'scope' bind to? How to make it bind to something else (if at all)?I agree this is an issue. We need to enumerate the use cases. Is 'scope' transitive or does it only apply to the first thing it hits?I think that it's possible to consider binding it as a convenient benefit of what 'scope' is generally meant to do anyway. I think the crossover of the two features is quite high. But it is a judgment call. Sometimes you may want to allow rvalue refs without prohibiting escaping them, or prohibit escaping them without allowing rvalues refs. But the point of 'scope' is that it safely takes stack references, which is exactly what rvalue temps are. Maybe getting the two features separate is good, but since it will require another parameter attribute, it suggests a need for increased reliance on attribute inference to spare the programmer the trouble. The main reason to consider combining is that it saves on syntax.Passing an r-value by ref is disallowed for arbitrary reasons.Reasons not closely related to lack of 'scope'. So why bind the new rule to scope?If I read the ambiguous wording of the proposal correctly, the following code will be disallowed: void foo1(scope ref int x) { } void main(){ foo1(1); // error }My impression is that this would be allowed, not disallowed.But this will be fine: void foo1(scope ref int x) { } int bar(){ return 1; } void main(){ foo1(bar()); }I think this would also be allowed.
Apr 21 2013
Yes, both cases are allowed. Dicebot initially wanted that scope ref does not accept literals (only in ref should this do), but Kenji has convinced him that this is unnecessary. In the current pull of Kenji both cases works fine. I also have taken the time and added the overload rules to the DIP.If I read the ambiguous wording of the proposal correctly, the following code will be disallowed: void foo1(scope ref int x) { } void main(){ foo1(1); // error }My impression is that this would be allowed, not disallowed.But this will be fine: void foo1(scope ref int x) { } int bar(){ return 1; } void main(){ foo1(bar()); }I think this would also be allowed.
Apr 22 2013
I realise I'm new here but this seems to be suggesting a whole load of changes and special cases for something that can be done in (IMHO) a much simpler way: Why not simply make escaping a "ref" pointer an unsafe operation. The compiler should be able to detect this and report it without any changes to the syntax. This should cover 99% of cases with no extra attributes required and no limitations on what you can do with a "ref" within the function. In the 1% of cases that a pointer needs to be escaped safely you can add an attribute (maybe "heap ref" or something, although perhaps some existing syntax could be used) that requires the input to have been allocated on the heap. In the case that a stack variable is passed as a "heap ref" parameter the compiler can automatically promote it where possible, or if that's not possible, such as the variable being marked "scope" (existing meaning) then it should complain. All values (including literals and temporaries) should then be able to be passed to a "ref const" parameter. As far as I'm aware the only real purpose for R-value references is to implement move semantics. This could already be done using "ref in" syntax, as that makes no guarantees that the value is not going to be destroyed, only says that the value should be initialised prior to it being passed in. The only change would be to allow passing temporaries as "ref in". To promise that the variable is not going to be modified "ref const" or "ref const in" can be used.
Apr 22 2013
On Monday, 22 April 2013 at 12:22:14 UTC, Diggory wrote:I realise I'm new here but this seems to be suggesting a whole load of changes and special cases for something that can be done in (IMHO) a much simpler way: Why not simply make escaping a "ref" pointer an unsafe operation. The compiler should be able to detect this and report it without any changes to the syntax. This should cover 99% of cases with no extra attributes required and no limitations on what you can do with a "ref" within the function. In the 1% of cases that a pointer needs to be escaped safely you can add an attribute (maybe "heap ref" or something, although perhaps some existing syntax could be used) that requires the input to have been allocated on the heap. In the case that a stack variable is passed as a "heap ref" parameter the compiler can automatically promote it where possible, or if that's not possible, such as the variable being marked "scope" (existing meaning) then it should complain. All values (including literals and temporaries) should then be able to be passed to a "ref const" parameter. As far as I'm aware the only real purpose for R-value references is to implement move semantics. This could already be done using "ref in" syntax, as that makes no guarantees that the value is not going to be destroyed, only says that the value should be initialised prior to it being passed in. The only change would be to allow passing temporaries as "ref in". To promise that the variable is not going to be modified "ref const" or "ref const in" can be used.This DIP already suggest 'in ref' besides 'scope ref'. 'in' is a shortcut for const scope. And Andrei already reject variants which _only_ consist of non-mutable rvalue ref's (like const ref), because the const system in D is physical. But this could be read on the wiki. You should read the DIP before you write here. ;)
Apr 22 2013
On Monday, 22 April 2013 at 13:17:36 UTC, Namespace wrote:On Monday, 22 April 2013 at 12:22:14 UTC, Diggory wrote:The definition was somewhat hidden in the language reference and the first reference I found on the forum said that "in" simply meant that the value should be initialised by the caller (in the same way that "out" means that the callee initialises the value).I realise I'm new here but this seems to be suggesting a whole load of changes and special cases for something that can be done in (IMHO) a much simpler way: Why not simply make escaping a "ref" pointer an unsafe operation. The compiler should be able to detect this and report it without any changes to the syntax. This should cover 99% of cases with no extra attributes required and no limitations on what you can do with a "ref" within the function. In the 1% of cases that a pointer needs to be escaped safely you can add an attribute (maybe "heap ref" or something, although perhaps some existing syntax could be used) that requires the input to have been allocated on the heap. In the case that a stack variable is passed as a "heap ref" parameter the compiler can automatically promote it where possible, or if that's not possible, such as the variable being marked "scope" (existing meaning) then it should complain. All values (including literals and temporaries) should then be able to be passed to a "ref const" parameter. As far as I'm aware the only real purpose for R-value references is to implement move semantics. This could already be done using "ref in" syntax, as that makes no guarantees that the value is not going to be destroyed, only says that the value should be initialised prior to it being passed in. The only change would be to allow passing temporaries as "ref in". To promise that the variable is not going to be modified "ref const" or "ref const in" can be used.This DIP already suggest 'in ref' besides 'scope ref'. 'in' is a shortcut for const scope. And Andrei already reject variants which _only_ consist of non-mutable rvalue ref's (like const ref), because the const system in D is physical.But this could be read on the wiki. You should read the DIP before you write here. ;)I have but the DIP isn't consistent, for example in test1 it says R-value temporaries are allowed:void test1(scope ref A a)And in test32 it says they are not "Only adressable parameters are valid, not temporaries, no extra template instances.":void test32(T)(scope ref T id)And then:test32(1337); // Fine, temporary mutable int variable is created with value 1337Some other problems: - Taking the address of a "scope ref" variable is prohibited even if the compiler can prove that it's safe. - Implementing "forward" in the following is impossible: doSomething(forward(<temporary/literal>)) Obviously a function that simply returns what is passed in seems pointless but it may be very useful if sometimes that function should do something else. All the restrictions on "scope ref" are exactly the same as the restrictions on "ref" if DIP25 is implemented, except that "scope ref" variables can't be returned (why is this the case when by following the same rules as DIP25 it can be safe?) In which case why not allow passing R-value references as normal "ref" parameters? Why the need for "scope" when the only new restriction it introduces can (and should) be avoided. DIP25 says that the return value of a ref function must not be assumed to have a lifetime longer than the shortest lifetime of any of its ref parameters. This formulation works just as well for an R-value reference as it does for a reference to a local variable, just that the first is slightly shorter.
Apr 22 2013
I have but the DIP isn't consistentI must have overlooked this all the time. I will clean up this inconsistency. The statement that only adressable elements are taken by scope ref is not true anymore. Both, scope ref and in ref can take any values. If it is an rvalue, a temporary is created and this is passed to the function. Thanks for the hint.In which case why not allow passing R-value references as normal "ref" parameters? Why the need for "scope" when the only new restriction it introduces can (and should) be avoided.DIP25 says that the return value of a ref function must not be assumed to have a lifetime longer than the shortest lifetime of any of its ref parameters. This formulation works just as well for an R-value reference as it does for a reference to a local variable, just that the first is slightly shorter.You should search for "rvalue references". 'ref' that takes both, lvalues and revalues was suggested and AFAIK rejected. Otherwise you could open a new DIP or first a thread and ask for this. I'm curious of the answers. This issue is very old (Exactly one year ago it was officially discussed for the first time). But the core problem exist since 2.038. There was 'auto ref' introduced. This was the first attempt to solve this problem. Long long time ago and it annoys us still today.
Apr 22 2013
On Monday, 22 April 2013 at 12:22:14 UTC, Diggory wrote:Why not simply make escaping a "ref" pointer an unsafe operation. The compiler should be able to detect this and report it without any changes to the syntax.In other words, 'scope' would be the default and require no explicit attribute. The first thing about this is the question of how much code it would break. I don't know the answer. Maybe a mockup of this idea could be used to create a sense of how badly it breaks existing code. The second question is how desirable is it as a feature. I think it may be quite desirable to have all refs be 'scope' by default, because the most common case will be the default, that refs will not be assigned to globals. Since there is a difference between the safety of returning by ref and the safety of assigning to heap or global addresses, there may need to be a distinction made between these two types of 'escape'.This should cover 99% of cases with no extra attributes required and no limitations on what you can do with a "ref" within the function. In the 1% of cases that a pointer needs to be escaped safely you can add an attribute (maybe "heap ref" or something, although perhaps some existing syntax could be used) that requires the input to have been allocated on the heap.' noscope ref' has also been suggested, since the reference in question would also need to include static global data.In the case that a stack variable is passed as a "heap ref" parameter the compiler can automatically promote it where possible, or if that's not possible, such as the variable being marked "scope" (existing meaning) then it should complain.This is interesting to me. The only drawback I can think of is the aversion people have to introducing code which could secretly allocate, since many people want to avoid the garbage collector. It would only be an issue if the automatic promotion looked so much like a normal function call that it was extraordinarily difficult to distinguish it.As far as I'm aware the only real purpose for R-value references is to implement move semantics. This could already be done using "ref in" syntax, as that makes no guarantees that the value is not going to be destroyed, only says that the value should be initialised prior to it being passed in. The only change would be to allow passing temporaries as "ref in".The only existing definition of 'in' is that it means 'const scope', so it already means scope. I don't know if that is a good definition or not. I think that there remains a significant fear in this community of introducing changes which will break existing code. I don't myself know how justified this fear is, but it is nonetheless something to take very seriously when proposing new ideas.I realise I'm new hereI'm new too. I'm glad to be able to have this discussion with you despite both of our being new. :-)
Apr 22 2013
On Sunday, 21 April 2013 at 22:16:14 UTC, Timon Gehr wrote:I had quite an impression this was prohibited mostly because of safe issues.Passing an r-value by ref is disallowed for arbitrary reasons.Reasons not closely related to lack of 'scope'. So why bind the new rule to scope?
Apr 23 2013
On 04/23/2013 10:10 AM, Dicebot wrote:On Sunday, 21 April 2013 at 22:16:14 UTC, Timon Gehr wrote:It is disallowed in system code.I had quite an impression this was prohibited mostly because of safe issues.Passing an r-value by ref is disallowed for arbitrary reasons.Reasons not closely related to lack of 'scope'. So why bind the new rule to scope?
Apr 23 2013
On Tuesday, 23 April 2013 at 08:19:43 UTC, Timon Gehr wrote:It is disallowed in system code.Ye, I know and always took it as yet another "we care mostly for safe" issue. What is the real rationale for this restriction?
Apr 23 2013
On Saturday, 20 April 2013 at 15:23:35 UTC, deadalnix wrote:On Saturday, 20 April 2013 at 15:17:39 UTC, Namespace wrote:Sadly, I have to agree on this. As nice as many new feature ideas are, they are far from priorities when there are multiple core mechanics that are broken.Listen, this issue is very real, but it is mostly about performance. I'll tell you something : the best performance improvement is the one that bring your program from non working state to working one. And right now, many existing feature are broken. The let's add whatever feature we have in mind is the very cause of the state of the language right now.I don't think adding more to the language is the sane thing to do right now.Why not? Could you explain this? This issue is discussed since more than a year and it is a very annoying issue. And even if Walter and Andrei are of this opinion, it would still only polite when they explain in detail why they think this.
Apr 20 2013
Sadly, I have to agree on this. As nice as many new feature ideas are, they are far from priorities when there are multiple core mechanics that are broken.There is no reason to prioritize DIP 36. Kenji, Dicebot and I did most of the work. The DIP is written and all necessary information are described in detail there with examples. The code also exists and there is even a pull request which has passed all the tests. Thus, this proposal is linked with not much work. Most of it was taken over by others. Due to this, it really is not asking too much to get a note if this pull is accepted or rejected. Of course, with detailed justification.
Apr 20 2013
On Saturday, 20 April 2013 at 16:11:49 UTC, Namespace wrote:How about "on hold"? (Not that I have any say in it at all) The fact is, there's much more to any change than simply implementing it. Changes break unexpected things. There are always extra corner cases not considered. There are always bugs and inconsistencies. Although it's great that you and some others have done the legwork to implement this proposal, it may have to wait until other more urgent problems have been fixed.Sadly, I have to agree on this. As nice as many new feature ideas are, they are far from priorities when there are multiple core mechanics that are broken.There is no reason to prioritize DIP 36. Kenji, Dicebot and I did most of the work. The DIP is written and all necessary information are described in detail there with examples. The code also exists and there is even a pull request which has passed all the tests. Thus, this proposal is linked with not much work. Most of it was taken over by others. Due to this, it really is not asking too much to get a note if this pull is accepted or rejected. Of course, with detailed justification.
Apr 20 2013
How about "on hold"? (Not that I have any say in it at all)As long as it is implemented in the near future and we must not wait another year (not even a half) it is ok. But the fact is, that we don't know what state it has, because we get no response.The fact is, there's much more to any change than simply implementing it. Changes break unexpected things. There are always extra corner cases not considered. There are always bugs and inconsistencies.Could be, but I don't see what could be broken by this DIP. All contingencies are listed also in the DIP (and that are not many). And it passed all tests what is crucial.Although it's great that you and some others have done the legwork to implement this proposal, it may have to wait until other more urgent problems have been fixed.Could be, but I don't know why. Which other fix is necessary for this pull? But also this would be ok, as long as we know, _which_ problems must be fixed.
Apr 20 2013
On Saturday, 20 April 2013 at 18:00:50 UTC, Namespace wrote:The DIP for instance, consider that const scope ref is semantically equivalent to pass by value, when it isn't (and not only for performance reasons, but for aliasing reasons). Nothing is considered about it.The fact is, there's much more to any change than simply implementing it. Changes break unexpected things. There are always extra corner cases not considered. There are always bugs and inconsistencies.Could be, but I don't see what could be broken by this DIP. All contingencies are listed also in the DIP (and that are not many). And it passed all tests what is crucial.
Apr 20 2013
On Sunday, 21 April 2013 at 01:04:04 UTC, deadalnix wrote:On Saturday, 20 April 2013 at 18:00:50 UTC, Namespace wrote:At least some objections that make sense and I'd love to see in the very first announcement. If you see any issues that prevent treating "const scope int" as "const scope ref int", please tell about them and they will be addressed in DIP. Because it is the intention. I don't understand what aliasing are you speaking about.The DIP for instance, consider that const scope ref is semantically equivalent to pass by value, when it isn't (and not only for performance reasons, but for aliasing reasons). Nothing is considered about it.The fact is, there's much more to any change than simply implementing it. Changes break unexpected things. There are always extra corner cases not considered. There are always bugs and inconsistencies.Could be, but I don't see what could be broken by this DIP. All contingencies are listed also in the DIP (and that are not many). And it passed all tests what is crucial.
Apr 21 2013
On Sunday, 21 April 2013 at 10:55:37 UTC, Dicebot wrote:The only thing I could think of was if you want to 'ref' a reference type. void func(ref Object o, scope Object o2, scope ref Object o3) {} Would there be a difference between the type of o and o2, or of o2 and o3? There is inconsistency, but it would be nice to find use cases which make this inconsistency truly unworkable with other things in the language.The DIP for instance, consider that const scope ref is semantically equivalent to pass by value, when it isn't (and not only for performance reasons, but for aliasing reasons). Nothing is considered about it.At least some objections that make sense and I'd love to see in the very first announcement. If you see any issues that prevent treating "const scope int" as "const scope ref int", please tell about them and they will be addressed in DIP. Because it is the intention. I don't understand what aliasing are you speaking about.
Apr 21 2013
On Sunday, 21 April 2013 at 16:08:55 UTC, Zach the Mystic wrote:Would there be a difference between the type of o and o2, or of o2 and o3? There is inconsistency, but it would be nice to find use cases which make this inconsistency truly unworkable with other things in the language.('nice' in the sense that it would prove the suggestion to be unworkable as opposed to nice that it actually is unworkable...)
Apr 21 2013
On Sunday, 21 April 2013 at 16:08:55 UTC, Zach the Mystic wrote:The only thing I could think of was if you want to 'ref' a reference type. void func(ref Object o, scope Object o2, scope ref Object o3) {} Would there be a difference between the type of o and o2, or of o2 and o3? There is inconsistency, but it would be nice to find use cases which make this inconsistency truly unworkable with other things in the language.Taking consistent approach with "ref", they all should have same type but bpth "ref" and "scope" differences are mangled into func name so that caller can take notion of proper behavior. I don't see an issue here.
Apr 23 2013
On Saturday, 20 April 2013 at 15:23:35 UTC, deadalnix wrote:On Saturday, 20 April 2013 at 15:17:39 UTC, Namespace wrote:I thought D was driven by its community.Listen, this issue is very real, but it is mostly about performance. I'll tell you something : the best performance improvement is the one that bring your program from non working state to working one. And right now, many existing feature are broken. The let's add whatever feature we have in mind is the very cause of the state of the language right now.I don't think adding more to the language is the sane thing to do right now.Why not? Could you explain this? This issue is discussed since more than a year and it is a very annoying issue. And even if Walter and Andrei are of this opinion, it would still only polite when they explain in detail why they think this.
Apr 20 2013
On 04/20/2013 07:34 PM, Minas Mina wrote:... I thought D was driven by its community.(This is its community.)
Apr 20 2013
On 4/20/13 11:17 AM, Namespace wrote:In a way I wish my not being polite would be the main bottleneck for this. I've been extremely busy at work, then preparing for DConf 2013, and last week has been quite distracting what with the Boston bombings three miles away from where we live and all that. It strikes me as odd to be obligated to spend time on something just because someone else did, and framed as impolite if I don't. That being said, I have made a pass through this DIP and I have the following concerns about it. 1. It defines a new language feature instead of improving the existing ones. At this point in the development of the language, our preference should be putting the existing features in good order. 2. The proposal is sketchy and does not give many details, such as the lifetime of temporaries bound to scope ref objects. 3. The relationship with auto ref is insufficiently described, e.g. there should be clarification on why auto ref cannot be improved to fulfill the desired role. 4. Above all this is a new language feature and again we want to resort to adding new feature only if it is clear that the existing features are insufficient and cannot be made sufficient. In particular we are much more inclined to impart real, demonstrable safety to "ref" and to make "auto ref" work as a reference that can bind to rvalues as well as lvalues. AndreiI don't think adding more to the language is the sane thing to do right now.Why not? Could you explain this? This issue is discussed since more than a year and it is a very annoying issue. And even if Walter and Andrei are of this opinion, it would still only polite when they explain in detail why they think this.
Apr 22 2013
On Monday, 22 April 2013 at 20:02:12 UTC, Andrei Alexandrescu wrote:4. Above all this is a new language feature and again we want to resort to adding new feature only if it is clear that the existing features are insufficient and cannot be made sufficient. In particular we are much more inclined to impart real, demonstrable safety to "ref" and to make "auto ref" work as a reference that can bind to rvalues as well as lvalues.Why isn't DIP36 "scope ref" be future compatible with a future safe "auto ref"? ... and if in the future the compiler would be able to infer "scope ref" from "auto ref", this entire DIP could be reused, with the benefit that people could start using this functionality already today(there is a full pull request with a very small delta), before the auto inference is in place.
Apr 22 2013
In a way I wish my not being polite would be the main bottleneck for this. I've been extremely busy at work, then preparing for DConf 2013, and last week has been quite distracting what with the Boston bombings three miles away from where we live and all that. It strikes me as odd to be obligated to spend time on something just because someone else did, and framed as impolite if I don't. That being said, I have made a pass through this DIP and I have the following concerns about it. 1. It defines a new language feature instead of improving the existing ones. At this point in the development of the language, our preference should be putting the existing features in good order. 2. The proposal is sketchy and does not give many details, such as the lifetime of temporaries bound to scope ref objects. 3. The relationship with auto ref is insufficiently described, e.g. there should be clarification on why auto ref cannot be improved to fulfill the desired role. 4. Above all this is a new language feature and again we want to resort to adding new feature only if it is clear that the existing features are insufficient and cannot be made sufficient. In particular we are much more inclined to impart real, demonstrable safety to "ref" and to make "auto ref" work as a reference that can bind to rvalues as well as lvalues. AndreiI'm sorry that you take it so personally, but I know from experience that some topics often get forgotten or ignored if you don't ask about it more then once. And that we have made so much effort should show that we work for D and not against it and that we don't want to annoy you. But you are right, scope ref is in comparison to auto ref a new feature, but it is one with little sideeffects and minimized implementation effort. And Jonathan described here (http://forum.dlang.org/thread/uswucstsooghescofycp forum.dlang.org?page=2#post-mailman.293.1364249651.4724.digitalmars-d-le rn:40puremagic.com) very well and in detail why auto ref is no solution for non-templates. In short: It cannot work the same way for non-templates as it does for template functions, because that would mean that non-templates are also doubled 2^n times. And the way scope ref would work, would mean, that auto ref works different for templates and non-template functions. But you'd better read Jonathan's answer.
Apr 22 2013
On Monday, 22 April 2013 at 20:02:12 UTC, Andrei Alexandrescu wrote:In a way I wish my not being polite would be the main bottleneck for this. I've been extremely busy at work, then preparing for DConf 2013, and last week has been quite distracting what with the Boston bombings three miles away from where we live and all that. It strikes me as odd to be obligated to spend time on something just because someone else did, and framed as impolite if I don't.Thanks for your time. Sometimes even simple "Have seen it, will answer later / after DConf is priceless".That being said, I have made a pass through this DIP and I have the following concerns about it. 1. It defines a new language feature instead of improving the existing ones. At this point in the development of the language, our preference should be putting the existing features in good order.You consider "scope" a new language feature? And consider "auto ref" improvable solution. The very point of this DIP is to not create syntax-driven features, instead better define existing ones that make sense on their own so they can be used for same purpose.2. The proposal is sketchy and does not give many details, such as the lifetime of temporaries bound to scope ref objects.It can't because lifetime of temporaries is not defined in D at all and suck stuff needs to be consistent. It is not really different from a lifetime of struct literal temporary used for pass-by-value.3. The relationship with auto ref is insufficiently described, e.g. there should be clarification on why auto ref cannot be improved to fulfill the desired role.auto ref is a template-world entity. If by "improved" you mean "completely reworked" than sure, I can add this rationale. Will do today.4. Above all this is a new language feature and again we want to resort to adding new feature only if it is clear that the existing features are insufficient and cannot be made sufficient. In particular we are much more inclined to impart real, demonstrable safety to "ref" and to make "auto ref" work as a reference that can bind to rvalues as well as lvalues.Can't agree. "scope" is defined (but not implemented, a pity). Creating temporaries already exists for some cases. No really new language feature is added. No special syntax created. "scope ref" is still "scope" and "ref" with all semantics this imposes, rvalue references are just a side-effect. Contrary to this, "auto ref" IS a new feature created specifically for syntax hack. That is a very problem you are speaking about - introducing new concepts instead of making use of ones that exist for ages.
Apr 23 2013
On 4/23/13 4:08 AM, Dicebot wrote:You consider "scope" a new language feature?Yes.And consider "auto ref" improvable solution.Yes.The very point of this DIP is to not create syntax-driven features, instead better define existing ones that make sense on their own so they can be used for same purpose.It's a new feature, no two ways about it. It overlaps ref and auto ref without any palpable benefit and defines yet another way to achieve the same thing as auto ref. On this ground alone the proposal has a large problem.A proposal aimed at binding rvalues to references must address lifetime of temporaries as a central concern.2. The proposal is sketchy and does not give many details, such as the lifetime of temporaries bound to scope ref objects.It can't because lifetime of temporaries is not defined in D at all and suck stuff needs to be consistent. It is not really different from a lifetime of struct literal temporary used for pass-by-value.I think we should focus on http://d.puremagic.com/issues/show_bug.cgi?id=9238 and on making ref safe.3. The relationship with auto ref is insufficiently described, e.g. there should be clarification on why auto ref cannot be improved to fulfill the desired role.auto ref is a template-world entity. If by "improved" you mean "completely reworked" than sure, I can add this rationale. Will do today.You are of course to disagree, but that would make you wrong. Andrei4. Above all this is a new language feature and again we want to resort to adding new feature only if it is clear that the existing features are insufficient and cannot be made sufficient. In particular we are much more inclined to impart real, demonstrable safety to "ref" and to make "auto ref" work as a reference that can bind to rvalues as well as lvalues.Can't agree. "scope" is defined (but not implemented, a pity). Creating temporaries already exists for some cases. No really new language feature is added. No special syntax created. "scope ref" is still "scope" and "ref" with all semantics this imposes, rvalue references are just a side-effect. Contrary to this, "auto ref" IS a new feature created specifically for syntax hack. That is a very problem you are speaking about - introducing new concepts instead of making use of ones that exist for ages.
Apr 23 2013
On Tuesday, 23 April 2013 at 14:24:06 UTC, Andrei Alexandrescu wrote:On 4/23/13 4:08 AM, Dicebot wrote:Well, ok, that explains everything. Thank you.You consider "scope" a new language feature?Yes.
Apr 23 2013
On 24 April 2013 00:24, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org>wrote:How does it overlap ref? It simply justifies the argument with an extra constraint and isn't tied to 'ref' at all, it's just useful in conjunction. I can't agree that it overlaps auto-ref at all. They're fundamentally different concepts. auto-ref is a template concept; it selects the ref-ness based on the received arg. 'auto ref', ie, 'automatic ref-ness'. It makes no sense on a non-template situation. I'm still completely amazed that the very reason this DIP makes perfect sense to me(/us) is the same reason you have a problem with it. 2. The proposal is sketchy and does not give many details, such as theThe very point of this DIP is to not create syntax-driven features, instead better define existing ones that make sense on their own so they can be used for same purpose.It's a new feature, no two ways about it. It overlaps ref and auto ref without any palpable benefit and defines yet another way to achieve the same thing as auto ref. On this ground alone the proposal has a large problem.It's not an r-value, it's a standard stack-allocated temporary. It's lifetime is identical to any other local. The reason it's not detailed in the proposal is because it adds no such new feature, and makes no changes. The lifetime of a local is well understood. 3. The relationship with auto ref is insufficiently described, e.g.A proposal aimed at binding rvalues to references must address lifetime of temporaries as a central concern.lifetime of temporaries bound to scope ref objects.It can't because lifetime of temporaries is not defined in D at all and suck stuff needs to be consistent. It is not really different from a lifetime of struct literal temporary used for pass-by-value.I don't believe it's possible to make ref safe. Can you suggest any vision for this? It's unsafe by definition... you are passing a pointer of unknown origin to a function that could do anything with that pointer. Hence 'scope ref', which appropriately restricts what the callee is able to do with it. 4. Above all this is a new language feature and again we want toI think we should focus on http://d.puremagic.com/issues/** show_bug.cgi?id=9238 <http://d.puremagic.com/issues/show_bug.cgi?id=9238>and on making ref safe.there should be clarification on why auto ref cannot be improved to fulfill the desired role.auto ref is a template-world entity. If by "improved" you mean "completely reworked" than sure, I can add this rationale. Will do today.Explain why? Proclaiming he is simply wrong when he presents sound reason isn't helpful.You are of course to disagree, but that would make you wrong.resort to adding new feature only if it is clear that the existing features are insufficient and cannot be made sufficient. In particular we are much more inclined to impart real, demonstrable safety to "ref" and to make "auto ref" work as a reference that can bind to rvalues as well as lvalues.Can't agree. "scope" is defined (but not implemented, a pity). Creating temporaries already exists for some cases. No really new language feature is added. No special syntax created. "scope ref" is still "scope" and "ref" with all semantics this imposes, rvalue references are just a side-effect. Contrary to this, "auto ref" IS a new feature created specifically for syntax hack. That is a very problem you are speaking about - introducing new concepts instead of making use of ones that exist for ages.
Apr 23 2013
On 4/23/13 12:04 PM, Manu wrote:On 24 April 2013 00:24, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org <mailto:SeeWebsiteForEmail erdani.org>> wrote: The very point of this DIP is to not create syntax-driven features, instead better define existing ones that make sense on their own so they can be used for same purpose. It's a new feature, no two ways about it. It overlaps ref and auto ref without any palpable benefit and defines yet another way to achieve the same thing as auto ref. On this ground alone the proposal has a large problem. How does it overlap ref? It simply justifies the argument with an extra constraint and isn't tied to 'ref' at all, it's just useful in conjunction.The best setup would be: 1. To take lvalues by reference, write "ref". 2. To take lvalues and rvalues by reference, write "auto ref". Everything else is superfluous and puts the burden of justification on the proposer. With DIP36, the setup would be: 1. To take lvalues by reference, write "ref". 2. To take lvalues and rvalues by reference: 2.1. Is it a template? Then write "auto ref". 2.2. Is it a non-template? Then write "scope ref".I can't agree that it overlaps auto-ref at all. They're fundamentally different concepts. auto-ref is a template concept; it selects the ref-ness based on the received arg. 'auto ref', ie, 'automatic ref-ness'. It makes no sense on a non-template situation. I'm still completely amazed that the very reason this DIP makes perfect sense to me(/us) is the same reason you have a problem with it.I don't know how to respond to this. To me is it painfully obvious DIP 36 is poor language design and fails to solve a variety of issues, such as clarifying lifetime of temporaries, safety, and returning ref from functions.2. The proposal is sketchy and does not give many details, such as the lifetime of temporaries bound to scope ref objects. It can't because lifetime of temporaries is not defined in D at all and suck stuff needs to be consistent. It is not really different from a lifetime of struct literal temporary used for pass-by-value. A proposal aimed at binding rvalues to references must address lifetime of temporaries as a central concern. It's not an r-value, it's a standard stack-allocated temporary. It's lifetime is identical to any other local. The reason it's not detailed in the proposal is because it adds no such new feature, and makes no changes. The lifetime of a local is well understood.Currently rvalues are destroyed immediately after the call they are passed into. DIP 36 would need to change that, but fails to specify it.3. The relationship with auto ref is insufficiently described, e.g. there should be clarification on why auto ref cannot be improved to fulfill the desired role. auto ref is a template-world entity. If by "improved" you mean "completely reworked" than sure, I can add this rationale. Will do today. I think we should focus on http://d.puremagic.com/issues/__show_bug.cgi?id=9238 <http://d.puremagic.com/issues/show_bug.cgi?id=9238> and on making ref safe. I don't believe it's possible to make ref safe. Can you suggest any vision for this?http://d.puremagic.com/issues/show_bug.cgi?id=9238It's unsafe by definition... you are passing a pointer of unknown origin to a function that could do anything with that pointer. Hence 'scope ref', which appropriately restricts what the callee is able to do with it.Our intent is to make "ref" always scoped and reserve non-scoped uses to pointers. We consider this good language design: we have unrestricted pointers for code that doesn't care much about safety, and we have "ref" which is almost as powerful but sacrifices a teeny bit of that power for the sake of guaranteed safety. Safety is guaranteed by making sure "ref" is always scoped (references can be passed down but never escape their bound value).4. Above all this is a new language feature and again we want to resort to adding new feature only if it is clear that the existing features are insufficient and cannot be made sufficient. In particular we are much more inclined to impart real, demonstrable safety to "ref" and to make "auto ref" work as a reference that can bind to rvalues as well as lvalues. Can't agree. "scope" is defined (but not implemented, a pity). Creating temporaries already exists for some cases. No really new language feature is added. No special syntax created. "scope ref" is still "scope" and "ref" with all semantics this imposes, rvalue references are just a side-effect. Contrary to this, "auto ref" IS a new feature created specifically for syntax hack. That is a very problem you are speaking about - introducing new concepts instead of making use of ones that exist for ages. You are of course to disagree, but that would make you wrong. Explain why? Proclaiming he is simply wrong when he presents sound reason isn't helpful.I assumed it was obvious from what I'd already written. The claim has been made that "scope ref" is not a new language feature. I don't know how to reply to that other than, well, it is. Andrei
Apr 23 2013
On Tue, 23 Apr 2013 13:33:31 -0400, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:Our intent is to make "ref" always scoped and reserve non-scoped uses to pointers.So no more returning ref? Because if you allow returning ref, you lose any notion of safety, unless you plan on changing the entire compilation model?We consider this good language design: we have unrestricted pointers for code that doesn't care much about safety, and we have "ref" which is almost as powerful but sacrifices a teeny bit of that power for the sake of guaranteed safety. Safety is guaranteed by making sure "ref" is always scoped (references can be passed down but never escape their bound value).Not being able to return ref is a large loss of power. Not arguing in favor of DIP36, but it seems there is a misunderstanding as to what it does. -Steve
Apr 23 2013
So no more returning ref? Because if you allow returning ref, you lose any notion of safety, unless you plan on changing the entire compilation model?The rules from DIP25/35 show how you can return refs while still maintaining safety.
Apr 23 2013
On Tue, 23 Apr 2013 14:01:14 -0400, Diggory <diggsey googlemail.com> wrote:Those rules disallow the following valid code: struct S { int x; ref S opOpAssign(string op : "+")(ref S other) { x += other.x; return this;} } ref S add5(ref S s) { auto o = S(5); return s += o; } void main() { auto s = S(5); S s2 = add5(s); } Because opOpAssign takes two refs to S, and in add5, we bind one parameter to a local, we cannot return the result, even though it's perfectly safe and valid. The point is simply that there exist valid and safe cases which will be disallowed by these rules. While maybe it's OK in your mind to restrict the above code from validity, it's currently valid and compiling code. You will be breaking existing code for pretty much no reason. -SteveSo no more returning ref? Because if you allow returning ref, you lose any notion of safety, unless you plan on changing the entire compilation model?The rules from DIP25/35 show how you can return refs while still maintaining safety.
Apr 23 2013
In that example you could make opOpAssign take a "const ref" and then the compiler could see that it could not return that parameter, but this is slightly hacky and I can see how there may be obscure corner cases where the rules are not sufficient. Actually this could also be solved by using the (original) meaning of "scope" to mark parameters that are not going to be returned. (I still think both "ref" and "scope ref" should accept rvalues)
Apr 23 2013
On 4/23/13 1:57 PM, Steven Schveighoffer wrote:On Tue, 23 Apr 2013 13:33:31 -0400, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> wrote:If we can't return ref, ref has failed. (This is what makes the entire thing difficult btw.) AndreiOur intent is to make "ref" always scoped and reserve non-scoped uses to pointers.So no more returning ref?
Apr 23 2013
On 24 April 2013 04:01, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org>wrote:On 4/23/13 1:57 PM, Steven Schveighoffer wrote:I think the key that's not in this DIP is that it should also return 'scope ref' to maintain the safety. This brings the proposal in-line with your plans, except the safety is explicit, and the option is available to the programmer. Making 'safe' ref the default is a major breaking change.On Tue, 23 Apr 2013 13:33:31 -0400, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org**> wrote: Our intent is to make "ref" always scoped and reserve non-scoped usesIf we can't return ref, ref has failed. (This is what makes the entire thing difficult btw.)to pointers.So no more returning ref?
Apr 23 2013
On 4/23/13 2:32 PM, Manu wrote:On 24 April 2013 04:01, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org <mailto:SeeWebsiteForEmail erdani.org>> wrote: On 4/23/13 1:57 PM, Steven Schveighoffer wrote: On Tue, 23 Apr 2013 13:33:31 -0400, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org <mailto:SeeWebsiteForEmail erdani.org>__> wrote: Our intent is to make "ref" always scoped and reserve non-scoped uses to pointers. So no more returning ref? If we can't return ref, ref has failed. (This is what makes the entire thing difficult btw.) I think the key that's not in this DIP is that it should also return 'scope ref' to maintain the safety. This brings the proposal in-line with your plans, except the safety is explicit, and the option is available to the programmer.We prefer to simplify. Use ref safely for scoped pass-down of resources, use pointers for unrestricted escapes. What you see as "offering an option" I see as "adding a burden".Making 'safe' ref the default is a major breaking change.How do you assess the size of the breakage? Andrei
Apr 23 2013
On Tuesday, 23 April 2013 at 18:41:07 UTC, Andrei Alexandrescu wrote:I think it's fairly well-understood, probably with the same meaning that you used in your own post somewhere else: http://forum.dlang.org/thread/hlh4g2$1tn0$2 digitalmars.com#post-hlh753:24270m:241:40digitalmars.comMaking 'safe' ref the default is a major breaking change.How do you assess the size of the breakage?
Apr 23 2013
On 24 April 2013 03:33, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org>wrote:On 4/23/13 12:04 PM, Manu wrote:That's not a good setup at all. It still doesn't make sense. There's nothing 'automatic' about it, I've specified ref, it is ref, there's no other choice. And it relies on a major breaking change to ref, which restricts the functionality of ref by default. Everything else is superfluous and puts the burden of justification on theOn 24 April 2013 00:24, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org <mailto:SeeWebsiteForEmail **erdani.org<SeeWebsiteForEmail erdani.org>The best setup would be: 1. To take lvalues by reference, write "ref". 2. To take lvalues and rvalues by reference, write "auto ref".wrote: The very point of this DIP is to not create syntax-driven features, instead better define existing ones that make sense on their own so they can be used for same purpose. It's a new feature, no two ways about it. It overlaps ref and auto ref without any palpable benefit and defines yet another way to achieve the same thing as auto ref. On this ground alone the proposal has a large problem. How does it overlap ref? It simply justifies the argument with an extra constraint and isn't tied to 'ref' at all, it's just useful in conjunction.proposer. With DIP36, the setup would be: 1. To take lvalues by reference, write "ref". 2. To take lvalues and rvalues by reference: 2.1. Is it a template? Then write "auto ref". 2.2. Is it a non-template? Then write "scope ref".Stop talking about r-values, rather, consider safety of passing temporaries. This problem has nothing to do with r-values, this is equally unsafe: void f(ref int x); int x; f(x); It's precisely the same problem, and should be fixed with the same solution. I would rewrite your list as such: 1. 'un-safely' pass a value (may not be a local), write 'ref' 2. safely pass a value (may be a local), write 'scope ref' 3. if you are concerned with templates do you: 3.a. want unsafe auto-ref, type 'auto ref' (only non-locals would generate 'ref') 3.b. want safe auto-ref, type 'scope auto ref' The automatic selection of ref for templates is fairly unrelated to this issue. I can't agree that it overlaps auto-ref at all. They're fundamentallyLifetime of temporaries is the most basic of principles. A local lives the life of the function in which it is defined. Safety is the whole point, and intrinsic to the proposal; safety by explicit specification, thus the programmer retains the option. If a function receives 'scope ref', and wants to return it, I think it should also return 'scope ref' (I guess this wasn't defined in the DIP), otherwise it would be considered an escape. 2. The proposal is sketchy and does not give many details,different concepts. auto-ref is a template concept; it selects the ref-ness based on the received arg. 'auto ref', ie, 'automatic ref-ness'. It makes no sense on a non-template situation. I'm still completely amazed that the very reason this DIP makes perfect sense to me(/us) is the same reason you have a problem with it.I don't know how to respond to this. To me is it painfully obvious DIP 36 is poor language design and fails to solve a variety of issues, such as clarifying lifetime of temporaries, safety, and returning ref from functions.Again, I think it was presumed (I can't conceive any other approach), and certainly Kenji read it that way, because his code appears to do just that. 3. The relationship with auto ref is insufficientlysuch as the lifetime of temporaries bound to scope ref objects. It can't because lifetime of temporaries is not defined in D at all and suck stuff needs to be consistent. It is not really different from a lifetime of struct literal temporary used for pass-by-value. A proposal aimed at binding rvalues to references must address lifetime of temporaries as a central concern. It's not an r-value, it's a standard stack-allocated temporary. It's lifetime is identical to any other local. The reason it's not detailed in the proposal is because it adds no such new feature, and makes no changes. The lifetime of a local is well understood.Currently rvalues are destroyed immediately after the call they are passed into. DIP 36 would need to change that, but fails to specify it.That's a massive breaking change... [response in other thread, we need to stop repeating in 2 threads I think]described, e.g. there should be clarification on why auto ref cannot be improved to fulfill the desired role. auto ref is a template-world entity. If by "improved" you mean "completely reworked" than sure, I can add this rationale. Will do today. I think we should focus on http://d.puremagic.com/issues/**__show_bug.cgi?id=9238<http://d.puremagic.com/issues/__show_bug.cgi?id=9238> <http://d.puremagic.com/**issues/show_bug.cgi?id=9238<http://d.puremagic.com/issues/show_bug.cgi?id=9238>> and on making ref safe. I don't believe it's possible to make ref safe. Can you suggest any vision for this?http://d.puremagic.com/issues/**show_bug.cgi?id=9238<http://d.puremagic.com/issues/show_bug.cgi?id=9238> It's unsafe by definition... you are passing a pointer of unknown originto a function that could do anything with that pointer. Hence 'scope ref', which appropriately restricts what the callee is able to do with it.Our intent is to make "ref" always scoped and reserve non-scoped uses to pointers. We consider this good language design: we have unrestricted pointers for code that doesn't care much about safety, and we have "ref" which is almost as powerful but sacrifices a teeny bit of that power for the sake of guaranteed safety. Safety is guaranteed by making sure "ref" is always scoped (references can be passed down but never escape their bound value).
Apr 23 2013
On 4/23/13 2:29 PM, Manu wrote:On 24 April 2013 03:33, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org <mailto:SeeWebsiteForEmail erdani.org>> wrote: The best setup would be: 1. To take lvalues by reference, write "ref". 2. To take lvalues and rvalues by reference, write "auto ref". That's not a good setup at all. It still doesn't make sense. There's nothing 'automatic' about it,There is - it means ref is inferred.I've specified ref, it is ref, there's no other choice.Well "auto ref" means "I don't care whether this is ref or not".And it relies on a major breaking change to ref, which restricts the functionality of ref by default.This is a confusion. There's no reliance on any change to ref. The breaking changes are related to adding safety. If safety weren't a concern, a lot of things would be simple.Stop talking about r-values, rather, consider safety of passing temporaries. This problem has nothing to do with r-values, this is equally unsafe: void f(ref int x); int x; f(x); It's precisely the same problem, and should be fixed with the same solution.We should make the code above safe as is.I would rewrite your list as such: 1. 'un-safely' pass a value (may not be a local), write 'ref' 2. safely pass a value (may be a local), write 'scope ref' 3. if you are concerned with templates do you: 3.a. want unsafe auto-ref, type 'auto ref' (only non-locals would generate 'ref') 3.b. want safe auto-ref, type 'scope auto ref'This a terrible, terrible list. I'd be ashamed to have to explain this with a straight face.I don't know how to respond to this. To me is it painfully obvious DIP 36 is poor language design and fails to solve a variety of issues, such as clarifying lifetime of temporaries, safety, and returning ref from functions. Lifetime of temporaries is the most basic of principles. A local lives the life of the function in which it is defined. Safety is the whole point, and intrinsic to the proposal; safety by explicit specification, thus the programmer retains the option.The missing point here is inflicting more complexity on the user. Andrei
Apr 23 2013
On 04/23/2013 07:33 PM, Andrei Alexandrescu wrote:On 4/23/13 12:04 PM, Manu wrote:or "scope ref", to be fair. scope ref on a template would behave differently than auto ref on a template.On 24 April 2013 00:24, Andrei Alexandrescu <SeeWebsiteForEmail erdani.org <mailto:SeeWebsiteForEmail erdani.org>> wrote: The very point of this DIP is to not create syntax-driven features, instead better define existing ones that make sense on their own so they can be used for same purpose. It's a new feature, no two ways about it. It overlaps ref and auto ref without any palpable benefit and defines yet another way to achieve the same thing as auto ref. On this ground alone the proposal has a large problem. How does it overlap ref? It simply justifies the argument with an extra constraint and isn't tied to 'ref' at all, it's just useful in conjunction.The best setup would be: 1. To take lvalues by reference, write "ref". 2. To take lvalues and rvalues by reference, write "auto ref". Everything else is superfluous and puts the burden of justification on the proposer. With DIP36, the setup would be: 1. To take lvalues by reference, write "ref". 2. To take lvalues and rvalues by reference: 2.1. Is it a template? Then write "auto ref".2.2. Is it a non-template? Then write "scope ref".+1.I can't agree that it overlaps auto-ref at all. They're fundamentally different concepts. auto-ref is a template concept; it selects the ref-ness based on the received arg. 'auto ref', ie, 'automatic ref-ness'. It makes no sense on a non-template situation. I'm still completely amazed that the very reason this DIP makes perfect sense to me(/us) is the same reason you have a problem with it.I don't know how to respond to this. To me is it painfully obvious DIP 36 is poor language design and fails to solve a variety of issues, such as clarifying lifetime of temporaries, safety, and returning ref from functions.... Our intent is to make "ref" always scoped and reserve non-scoped uses to pointers. We consider this good language design: we have unrestricted pointers for code that doesn't care much about safety, and we have "ref" which is almost as powerful but sacrifices a teeny bit of that power for the sake of guaranteed safety. Safety is guaranteed by making sure "ref" is always scoped (references can be passed down but never escape their bound value). ...Safety should be guaranteed in safe code. There is no point in conservatively disallowing perfectly fine system code on the basis of safety concerns, unless, of course, the type system is advanced enough to prove safe all relevant use cases.
Apr 23 2013
On Tue, 23 Apr 2013 15:40:35 -0400, Timon Gehr <timon.gehr gmx.ch> wrote:Safety should be guaranteed in safe code. There is no point in conservatively disallowing perfectly fine system code on the basis of safety concerns, unless, of course, the type system is advanced enough to prove safe all relevant use cases.I agree with this. If safe code is all that is affected, we will be well off. We can also disallow known bad cases in non- safe code. -Steve
Apr 23 2013
On 04/23/2013 09:51 PM, Steven Schveighoffer wrote:On Tue, 23 Apr 2013 15:40:35 -0400, Timon Gehr <timon.gehr gmx.ch> wrote:Another possibility I consider fine is to implement what Andrei suggests and then allow system code to cast around the conservative escape checks using something like eg. cast(scope). struct CodeGen{ struct Label{ CodeGen* outer; } Label makeLabel(){ return Label(&this); } // error } struct CodeGen{ struct Label{ CodeGen* outer; } Label makeLabel(){ return Label(cast(scope)&this); } // ok } The best way to fix this would of course be to introduce lifetimes as an explicit type system feature. (Though if I was allowed to add that kind of complexity to the type system, I'd do many things very differently.)Safety should be guaranteed in safe code. There is no point in conservatively disallowing perfectly fine system code on the basis of safety concerns, unless, of course, the type system is advanced enough to prove safe all relevant use cases.I agree with this. If safe code is all that is affected, we will be well off. We can also disallow known bad cases in non- safe code. -Steve
Apr 23 2013
First of all, we should define words for the discussion. 1. Let's name current `auto ref` "parameterized-ref", which works only with template functions and the `auto ref` parameter is instantiated to both ref/non-ref by the actual function argument. 2. Let's call it "rvalue-ref(erence)", which currently discussed, that can receive both lvalues and rvalues by one function body. 2013/4/24 Andrei Alexandrescu <SeeWebsiteForEmail erdani.org>The best setup would be: 1. To take lvalues by reference, write "ref". 2. To take lvalues and rvalues by reference, write "auto ref". Everything else is superfluous and puts the burden of justification on the proposer. With DIP36, the setup would be: 1. To take lvalues by reference, write "ref". 2. To take lvalues and rvalues by reference: 2.1. Is it a template? Then write "auto ref". 2.2. Is it a non-template? Then write "scope ref".The difference between 2.1 and 2.2 is not superfluous. Because: 1. "parameterized-ref" is already there with the syntax `auto ref`. Removing it introduces breaking language change. 2. If we remove "parameterized-ref" from D, we will lose the ability to write certain kind of template functions. For example: auto ref forward(T)(auto ref T arg) { return arg; } The parameter `arg` is instantiated with both ref/non-ref, and forward `function` returns also both ref/non-ref value. In such case, you cannot replace "parameterized-ref" to "rvalue-ref". These are why DIP36 is necessary. Repeatedly, I think removing current `auto ref` is not good.Currently rvalues are destroyed immediately after the call they are passed into. DIP 36 would need to change that, but fails to specify it.DIP36 does not change it.Our intent is to make "ref" always scoped and reserve non-scoped uses to pointers. We consider this good language design: we have unrestricted pointers for code that doesn't care much about safety, and we have "ref" which is almost as powerful but sacrifices a teeny bit of that power for the sake of guaranteed safety. Safety is guaranteed by making sure "ref" is always scoped (references can be passed down but never escape their bound value).I'm basically agreeing with the DIP25. Making `ref` more safety is possible and should. I can guess that you are intended applying DIP25 to "rvalue-ref" concept. It is sane design, but DIP36 also accepts such applying DIP25. There is no issue.Kenji HaraAndrei
Apr 23 2013
On 04/24/2013 02:41 AM, kenji hara wrote:... 1. "parameterized-ref" is already there with the syntax `auto ref`. Removing it introduces breaking language change. 2. If we remove "parameterized-ref" from D, we will lose the ability to write certain kind of template functions. For example: auto ref forward(T)(auto ref T arg) { return arg; } The parameter `arg` is instantiated with both ref/non-ref, and forward `function` returns also both ref/non-ref value. In such case, you cannot replace "parameterized-ref" to "rvalue-ref". These are why DIP36 is necessary. Repeatedly, I think removing current `auto ref` is not good. ...We could specify that if there is no influence (to be made more precise) of the actual ref-ness for the function semantics, the second copy is elided. It is then illegal for non-templated functions to require multiple copies. This would merge the two features under the name auto ref.
Apr 24 2013
On Saturday, 20 April 2013 at 14:42:57 UTC, Namespace wrote:That is true, but it makes the impression that, with the exception of Kenji, none of the core developers is interested in a solution to this problem.I don't think that's true.The DIP was not much discussed and the pull request is regularly overlooked / ignored.Patience!Also in the discussion on the pull request no comments for Walter or Andrei are found. Although the pull is complete and has passed all the tests and would be ready to merge. Also this thread is completely ignored even though both write in this forum regularly and participate in other discussions. To me this makes the impression that they were not interested in this problem (or in our solution to the problem). Either they want the problem does not solve or try to solve it in their own way and that can take a very long time. At least an annotation what of both is the case or if I see it completely wrong, would be polite.I think you've done a good job with the feature and the presentation. But I personally don't feel like it's my job to rush D's development. Part of the reason is that D is already way ahead of most if not all of the competition in terms of sheer language design. When you extend into unknown territory, it's sometimes wise just to stay where you are for a bit, to give yourself time to adapt and build up a foundation. I don't think your work will go unnoticed or unappreciated. Most of the time when people don't get back to you, it's because they're busy with other things. Probably the best thing you can do is say, well, my work on this feature is done, what else can I improve around here? This feature and this issue won't go away, IMO.But someone besides me would need to evaluate both DIP 35 & 36 to see if there were any real conflicts there.Yes that would be good.
Apr 20 2013
Well perhaps I am too hasty. I'll wait and see what is happening. BTW: Thanks for the support. ;)
Apr 21 2013
On Wednesday, 10 April 2013 at 07:43:57 UTC, Dicebot wrote:Consistent behavior is important but it does not change the fact that there two types of rvalues in the language - raw literals (42, A.init) and constructed temporaries (A()). Accepting rvalues of the first type in as mutable references may be consistent from the point of view of syntax by _extremely_ confusing semantics-wise: void foo(scope ref int x) { x = 32; } void main() { foo(42); // erm, 32 is the new 42 or ref is not actually ref? } Beauty of "in ref" is that in that case user can't use it in any way that may disclose the fact the temporary variable for non-adressable entities is created. For mutable scope ref it is not the case and we must leak implementation details, which is never good. Another concern is that if someone tries to pass "42" as a mutable ref, most likely he does not really wants it to be mutable and "in ref" is a better match. This may not be consistent from the point of view of generic code, but it is now consistent from the point of view of programmer : A(...) construct always create temporaries, raw value literals never do (well, they will for "in ref" but you can't observe it). I think this is much more important. One extra thing to note is that test32 may actually work if it instantiates T as "const int" for 42 (making it "in ref" essentially), but I don't know if D rules allow it.I think this is another case of two different features which may or may not be paired up together. If it is always okay to have A accompany B, and B accompany A, it's good from a syntax point of view because you only need one syntax for both of them. But if you pair them up and later think, I wish I could do A without having to do B, or B without having to do A, then you'll regret pairing them up because you'll either have to break code or live with what you've got. When you say we shouldn't be able to return an rvalue temporaries, even if they're safe, I think it's reasonable, not a life or death issue. But if 'scope ref' is used to mean that, you're also saying that any *other* feature which wants 'scope', such as 'ref' safety (why I created DIP35, to highlight this), will automatically also have to take rvalue temps because they're bound up with it, it's more risky. Some of these will be a judgment call - A and B are sometimes so similar that it's better to save on syntax than differentiate them. 'const scope' might be the same way.
Apr 11 2013
On Tuesday, 9 April 2013 at 17:06:47 UTC, Namespace wrote:http://wiki.dlang.org/DIP36// Does not pretend to be safe any more void test2(ref A a) { } I believe 'ref' still *can* be safe. The unsafe action is really when you assign it to a global pointer. void test2(ref A a) { static A* p; p = &a; // <-- This is really the only unsafe thing } I think for convenience the function must only be considered unsafe if it does the above. Even returning the 'ref' is safe so long as the *caller* keeps track of what it passes in, according to DIP25. "Following limitation apply to scope ref function parameters (including in ref): ...3. Parameter can only be used as an argument for other function if it also accepts scope ref, no implicit casting away." The DIP fails to mention that 'scope' by itself implies 'ref', and (presumably) can be reserved for cases where the caller specifically does not want to allow rvalue temps. 'scope' implies 'ref' because value types are inherently safe and need no attributes. I'm not sure what's so bad about allowing 'scope ref' arguments to be passed to 'scope' parameters also. It passes the ref it receives, but since it's still 'scope', it's not going anywhere. Also, given that 'scope' implies 'ref', there may be significant advantage in simply allowing *all* scope parameters to accept rvalue temps. It would be helpful to have a use case where 'scope' was clearly desired but rvalue temps clearly *not* desired. In most cases, it seems, anything marked 'scope' could easily accept an rvalue temp no problem. The 'scope ref' syntax does have a slight conflict with DIP25 and my suggested addition DIP35, in that if other means are found to making returning 'ref' safe, 'scope ref' as a syntax means that no rvalue temporary can ever be returned. Since this may be perfectly acceptable from a 'bad practices' point of view, 'scope ref' may still be a good syntax. But if it were seen as okay to return even a an rvalue temporary, since it is made safe by other means, 'scope ref' would either not be usable for this or would actually be (confusingly) returnable.
Apr 09 2013
2013/4/10 Zach the Mystic <reachzach gggggmail.com>On Tuesday, 9 April 2013 at 17:06:47 UTC, Namespace wrote:I think having both 'ref' and 'scope ref' is still reasonable, because: 1. According to DIP25, escaping ref parameter is always safe. But, for rvalue reference, it allows meaningless code. // Even if this is allowed, it is safe. BUT will introduce bad practice. ref int foo(scope ref int x) { return x; } // safe ref int bar(ref int x) { return x; } void test() { int x; foo(x) = 10; // may useful but... foo(1) = 10; // completely useless! bar(x) = 10; // may useful, and bar(1) = 10; // disallowed. } 2. Certainly 'scope' by itself _can_ imply 'ref'. BUT, currently a function parameter without 'ref' storage class implies having value semantics (== copy). If we change the 'scope' meaning to 'implicit ref', it will break the consistency. And, 'scope' is alredy used for delegate parameter. int opApply(scope int delegate(ref int) dg); Such a semantic modification will silently change the meaning of existing code. It's not good to me. Kenji Harahttp://wiki.dlang.org/DIP36// Does not pretend to be safe any more void test2(ref A a) { } I believe 'ref' still *can* be safe. The unsafe action is really when you assign it to a global pointer. void test2(ref A a) { static A* p; p = &a; // <-- This is really the only unsafe thing } I think for convenience the function must only be considered unsafe if it does the above. Even returning the 'ref' is safe so long as the *caller* keeps track of what it passes in, according to DIP25. "Following limitation apply to scope ref function parameters (including in ref): ...3. Parameter can only be used as an argument for other function if it also accepts scope ref, no implicit casting away." The DIP fails to mention that 'scope' by itself implies 'ref', and (presumably) can be reserved for cases where the caller specifically does not want to allow rvalue temps. 'scope' implies 'ref' because value types are inherently safe and need no attributes. I'm not sure what's so bad about allowing 'scope ref' arguments to be passed to 'scope' parameters also. It passes the ref it receives, but since it's still 'scope', it's not going anywhere. Also, given that 'scope' implies 'ref', there may be significant advantage in simply allowing *all* scope parameters to accept rvalue temps. It would be helpful to have a use case where 'scope' was clearly desired but rvalue temps clearly *not* desired. In most cases, it seems, anything marked 'scope' could easily accept an rvalue temp no problem. The 'scope ref' syntax does have a slight conflict with DIP25 and my suggested addition DIP35, in that if other means are found to making returning 'ref' safe, 'scope ref' as a syntax means that no rvalue temporary can ever be returned. Since this may be perfectly acceptable from a 'bad practices' point of view, 'scope ref' may still be a good syntax. But if it were seen as okay to return even a an rvalue temporary, since it is made safe by other means, 'scope ref' would either not be usable for this or would actually be (confusingly) returnable.
Apr 09 2013
On Wednesday, 10 April 2013 at 02:41:10 UTC, kenji hara wrote:I think having both 'ref' and 'scope ref' is still reasonable, because: 1. According to DIP25, escaping ref parameter is always safe. But, for rvalue reference, it allows meaningless code. // Even if this is allowed, it is safe. BUT will introduce bad practice. ref int foo(scope ref int x) { return x; } // safe ref int bar(ref int x) { return x; } void test() { int x; foo(x) = 10; // may useful but... foo(1) = 10; // completely useless! bar(x) = 10; // may useful, and bar(1) = 10; // disallowed. }'foo(1) = 10' is indeed completely useless, but I don't think all uses are completely useless. But I will concede that allowing things like 'foo(1)' may be useless *enough* to disallow it without anyone feeling bad. I have made DIP35, http://wiki.dlang.org/DIP35 , which utilizes 'scope' to actually make DIP25 more flexible, which I think is probably good. The example I used was the 'copy' function. 'foo' above, rewritten as the copy function would be: ref int foo(scope ref int x) { int* y = new int; *y = x; return y; } DIP25 may *need* to use 'scope' in this way to know that foo() will always give a fresh value - so it can treat it like a global safely. Thus 'foo(1)' will return a fresh heap allocated copy of "1". ref int test() { return foo(1); // allowed return bar(1); // disallowed! } Without the 'scope' parameter, there would be no way the compiler could know. Therefore, it is not completely useless.2. Certainly 'scope' by itself _can_ imply 'ref'. BUT, currently a function parameter without 'ref' storage class implies having value semantics (== copy).This is slightly wrong, I suspect. 'out' parameters are implicitly references.If we change the 'scope' meaning to 'implicit ref', it will break the consistency. And, 'scope' is already used for delegate parameter. int opApply(scope int delegate(ref int) dg); Such a semantic modification will silently change the meaning of existing code. It's not good to me.Generally, I agree. My argument is for a small convenience of not having to type 'ref' when not necessary. It would mean that when the type was implicitly a reference, such as a delegate or object, 'ref' was *not* implied, whereas it *was* implied with a value type. This may or may not wreak havoc on the generic type system. I thought there might be an off-chance that it would actually be a *convenience* for the type system, since it would get the right level of referencing for the type involved. I believe that the 'scope' keyword may be a necessary addition to DIP25 to make 'ref' fully safe and flexible (DIP35). If so, then there may be a conflict with using it only to mean rvalue temporaries. They are two separate features. I believe that if they are to be used together, it will be because it was decided that whenever you want to stop a reference from escaping, you *always* want to allow rvalue temporaries, and whenever you want to allow rvalue temporaries, you *never* want them to be returned. Right now, returning an rvalue temporary might seem dangerous, but sealed references *are* part of the plan for D, and there may be no need to see them as dangerous.
Apr 09 2013
On Wednesday, 10 April 2013 at 04:46:43 UTC, Zach the Mystic wrote:ref int bar(ref int x) { return x; } ref int foo(scope ref int x) { int* y = new int; *y = x; return y; } ref int test() { return foo(1); // allowed return bar(1); // disallowed! }When said 'bar(1)' was disallowed, I meant that it was considered local and not disallowed because it doesn't accept rvalue temps. Fix: ref int test() { int y; return foo(y); // allowed return bar(y); // disallowed! }
Apr 09 2013
On 10 April 2013 12:40, kenji hara <k.hara.pg gmail.com> wrote:2013/4/10 Zach the Mystic <reachzach gggggmail.com>Why are you suggesting changing scope to imply ref? This seems wrong. scope and ref are separate, should remain that way. Arguments would be scope ref, or in ref, thus allowing rvalues. Without ref, I would imagine that the meaning is such that, even though the argument is a copy, it, or members thereof are not allowed to escape. struct X { int *p; } int* global; void func(scope X x) // note: is not ref { global = x.p; // <- error! scope prevents any part of x escaping, even though it's a copy. } This way, scope has meaning with or without ref. And, 'scope' is alredy used for delegate parameter.On Tuesday, 9 April 2013 at 17:06:47 UTC, Namespace wrote:I think having both 'ref' and 'scope ref' is still reasonable, because: 1. According to DIP25, escaping ref parameter is always safe. But, for rvalue reference, it allows meaningless code. // Even if this is allowed, it is safe. BUT will introduce bad practice. ref int foo(scope ref int x) { return x; } // safe ref int bar(ref int x) { return x; } void test() { int x; foo(x) = 10; // may useful but... foo(1) = 10; // completely useless! bar(x) = 10; // may useful, and bar(1) = 10; // disallowed. } 2. Certainly 'scope' by itself _can_ imply 'ref'. BUT, currently a function parameter without 'ref' storage class implies having value semantics (== copy). If we change the 'scope' meaning to 'implicit ref', it will break the consistency.http://wiki.dlang.org/DIP36// Does not pretend to be safe any more void test2(ref A a) { } I believe 'ref' still *can* be safe. The unsafe action is really when you assign it to a global pointer. void test2(ref A a) { static A* p; p = &a; // <-- This is really the only unsafe thing } I think for convenience the function must only be considered unsafe if it does the above. Even returning the 'ref' is safe so long as the *caller* keeps track of what it passes in, according to DIP25. "Following limitation apply to scope ref function parameters (including in ref): ...3. Parameter can only be used as an argument for other function if it also accepts scope ref, no implicit casting away." The DIP fails to mention that 'scope' by itself implies 'ref', and (presumably) can be reserved for cases where the caller specifically does not want to allow rvalue temps. 'scope' implies 'ref' because value types are inherently safe and need no attributes. I'm not sure what's so bad about allowing 'scope ref' arguments to be passed to 'scope' parameters also. It passes the ref it receives, but since it's still 'scope', it's not going anywhere. Also, given that 'scope' implies 'ref', there may be significant advantage in simply allowing *all* scope parameters to accept rvalue temps. It would be helpful to have a use case where 'scope' was clearly desired but rvalue temps clearly *not* desired. In most cases, it seems, anything marked 'scope' could easily accept an rvalue temp no problem. The 'scope ref' syntax does have a slight conflict with DIP25 and my suggested addition DIP35, in that if other means are found to making returning 'ref' safe, 'scope ref' as a syntax means that no rvalue temporary can ever be returned. Since this may be perfectly acceptable from a 'bad practices' point of view, 'scope ref' may still be a good syntax. But if it were seen as okay to return even a an rvalue temporary, since it is made safe by other means, 'scope ref' would either not be usable for this or would actually be (confusingly) returnable.int opApply(scope int delegate(ref int) dg); Such a semantic modification will silently change the meaning of existing code. It's not good to me.What does scope mean in this case? Is this a conflict in some way?
Apr 09 2013
On Wednesday, 10 April 2013 at 05:21:40 UTC, Manu wrote:Why are you suggesting changing scope to imply ref? This seems wrong. scope and ref are separate, should remain that way.To be clear, I suggested it, not Kenji. The reason scope could imply ref is that no value type is ever unsafe. If you copy the value you're passing, there's no way the reference could escape the scope, because there's no reference! A delegate has an implicit pointer and is inherently a reference type, which is why it can work with 'scope'. In all likelihood 'scope' implying 'ref' would needlessly complicate the type system, in exchange for the convenience of only having to type either 'scope' or 'ref' depending on what you wanted. But I suggested it because I at least wanted it to be discussed.
Apr 09 2013
On 10 April 2013 16:11, Zach the Mystic <reachzach gggggmail.com> wrote:On Wednesday, 10 April 2013 at 05:21:40 UTC, Manu wrote:It is though, in the case I demonstrated. A value type can aggregate a reference type, and by-val scope would prohibit any part of the copy from escaping in turn. This is tricky, but I think it would be an important enhancement for non-ref scope variables and safe-ty. It might be impractical, but it's something to think about anyway... If you copy the value you're passing, there's no way the reference couldWhy are you suggesting changing scope to imply ref? This seems wrong. scope and ref are separate, should remain that way.To be clear, I suggested it, not Kenji. The reason scope could imply ref is that no value type is ever unsafe.escape the scope, because there's no reference! A delegate has an implicit pointer and is inherently a reference type, which is why it can work with 'scope'. In all likelihood 'scope' implying 'ref' would needlessly complicate the type system, in exchange for the convenience of only having to type either 'scope' or 'ref' depending on what you wanted. But I suggested it because I at least wanted it to be discussed.Fair enough.
Apr 09 2013
On Wednesday, 10 April 2013 at 06:11:29 UTC, Zach the Mystic wrote:no value type is ever unsafe.Delegates?
Apr 23 2013
On Tuesday, 23 April 2013 at 08:13:28 UTC, Mehrdad wrote:On Wednesday, 10 April 2013 at 06:11:29 UTC, Zach the Mystic wrote:Well, I don't know the formal definition of a delegate, but I believe it is a pointer to a function, plus a pointer to a data frame for the function. Since it contains a pointer, it qualifies to me as a reference type. Arrays too.no value type is ever unsafe.Delegates?
Apr 23 2013
On Wednesday, 10 April 2013 at 05:21:40 UTC, Manu wrote:struct X { int *p; } int* global; void func(scope X x) // note: is not ref { global = x.p; // <- error! scope prevents any part of x escaping, even though it's a copy. } This way, scope has meaning with or without ref.I think this is a subtle point, but I don't think it's correct. I think there's a difference between 'x.p' above, and what '&x.p' or '&x' would give. I think 'scope' should guarantee that you won't assign the *address* of the passed-in parameter: void func(scope X x, ref X y) { static X* xx = &x; // Error static int** xpp = &x.p; // Error xx = &y; // unsafe, but pass xpp = &y.p; // same } I don't think it should guarantee that you won't copy something that is *already* a pointer. Copying the pointer may be dangerous, but I don't think 'scope' will be very useful if it's supposed to track the internal pointers of aggregate types like that. I think somebody else has to make sure that pointer is safe. I could be wrong.
Apr 10 2013
On Wednesday, 10 April 2013 at 07:39:25 UTC, Zach the Mystic wrote:...Kind of. I am thinking that scope is best when transitive for aggregation but not for indirection: struct S { int a; int *b; } void foo(scope S s) { static int *x1 = &(s.a); // error static int *x2 = s.b; // fine }
Apr 23 2013
On 04/23/2013 10:16 AM, Dicebot wrote:On Wednesday, 10 April 2013 at 07:39:25 UTC, Zach the Mystic wrote:(Both of these are in error because static variables are initialized at compile time, but I get what you mean.) Why would 'scope' have any effect on the validity of the first? s.a belongs to the callee exclusively. Adding modular annotations to prevent taking its address has no point....Kind of. I am thinking that scope is best when transitive for aggregation but not for indirection: struct S { int a; int *b; } void foo(scope S s) { static int *x1 = &(s.a); // error static int *x2 = s.b; // fine }
Apr 23 2013
On Tuesday, 23 April 2013 at 08:25:18 UTC, Timon Gehr wrote:(Both of these are in error because static variables are initialized at compile time, but I get what you mean.)Shame on me! (blush)Why would 'scope' have any effect on the validity of the first? s.a belongs to the callee exclusively. Adding modular annotations to prevent taking its address has no point.Because it is an attempt to take/store address of a scope variable, which is prohibited by scope definition. I think (but I am not sure!) that it makes sense to make scope transitive for aggregation, because automatic destruction upon leaving the scope happens for aggregated entities. Thus, nothing can be known about s.a lifetime, same as s lifetime. This is one step towards consistent "scope" behavior that will allow safety desired by this DIP.
Apr 23 2013
2013/4/10 Manu <turkeyman gmail.com>Why are you suggesting changing scope to imply ref? This seems wrong. scope and ref are separate, should remain that way.I say that 'scope' itself should not imply 'ref'. It is *possible* but would break existing code meaning, so it should not be applied.Arguments would be scope ref, or in ref, thus allowing rvalues. Without ref, I would imagine that the meaning is such that, even though the argument is a copy, it, or members thereof are not allowed to escape. struct X { int *p; } int* global; void func(scope X x) // note: is not ref { global = x.p; // <- error! scope prevents any part of x escaping, even though it's a copy. } This way, scope has meaning with or without ref.That is an enhancement. Similar things is now in my mind, but it is not yet output.And, 'scope' is alredy used for delegate parameter.Compiler guarantees that given delegate to the scope parameter never make a closure. It would avoid heap allocation. Kenji Haraint opApply(scope int delegate(ref int) dg); Such a semantic modification will silently change the meaning of existing code. It's not good to me.What does scope mean in this case? Is this a conflict in some way?
Apr 09 2013
On 10 April 2013 15:30, kenji hara <k.hara.pg gmail.com> wrote:2013/4/10 Manu <turkeyman gmail.com>Right. Absolutely agree then! :)Why are you suggesting changing scope to imply ref? This seems wrong. scope and ref are separate, should remain that way.I say that 'scope' itself should not imply 'ref'. It is *possible* but would break existing code meaning, so it should not be applied.Arguments would be scope ref, or in ref, thus allowing rvalues. WithoutI think this is a tool that will greatly enhance working with safe in the future. I look forward to it. And, 'scope' is alredy used for delegate parameter.ref, I would imagine that the meaning is such that, even though the argument is a copy, it, or members thereof are not allowed to escape. struct X { int *p; } int* global; void func(scope X x) // note: is not ref { global = x.p; // <- error! scope prevents any part of x escaping, even though it's a copy. } This way, scope has meaning with or without ref.That is an enhancement. Similar things is now in my mind, but it is not yet output.Do you have any ideas/solutions that still fit this proposal? I tend to think the value of this proposal is of extreme significance to D. It is, without doubt, the single biggest complaint I've heard by virtually every programmer I've introduced D to, and the future implications for safe improvements are valuable too.Compiler guarantees that given delegate to the scope parameter never make a closure. It would avoid heap allocation.int opApply(scope int delegate(ref int) dg); Such a semantic modification will silently change the meaning of existing code. It's not good to me.What does scope mean in this case? Is this a conflict in some way?
Apr 09 2013
On Wednesday, 10 April 2013 at 01:40:49 UTC, Zach the Mystic wrote:I think for convenience the function must only be considered unsafe if it does the above. Even returning the 'ref' is safe so long as the *caller* keeps track of what it passes in, according to DIP25.Safety of "ref" is not problem that this DIP tries to solve. It should be solved with DIP25. Now ref is not safe (despite the fact it pretends to) and it still won't be after DIP36 approval, not until issue is addressed in DIP25. No need to mix it.
Apr 10 2013
On Wednesday, 10 April 2013 at 07:46:41 UTC, Dicebot wrote:On Wednesday, 10 April 2013 at 01:40:49 UTC, Zach the Mystic wrote:My proposed DIP35 uses 'scope' to enhance DIP25. I don't believe DIP25 is really complete. 'scope' would help it a lot, but that would give more meanings to 'scope' which are potentially in conflict with it just meaning rvalue temp.I think for convenience the function must only be considered unsafe if it does the above. Even returning the 'ref' is safe so long as the *caller* keeps track of what it passes in, according to DIP25.Safety of "ref" is not problem that this DIP tries to solve. It should be solved with DIP25. Now ref is not safe (despite the fact it pretends to) and it still won't be after DIP36 approval, not until issue is addressed in DIP25. No need to mix it.
Apr 10 2013
On Wednesday, 10 April 2013 at 09:26:38 UTC, Zach the Mystic wrote:On Wednesday, 10 April 2013 at 07:46:41 UTC, Dicebot wrote:And how it is relevant to DIP36? It solves specific issue. It provides some hints how other DIP may use new opportunities. It is up to DIP25 and DIP35 to be built on top if this gets accepted first. Or other way around. DIPs are built in context for current language implementation, not some potential other DIPs.On Wednesday, 10 April 2013 at 01:40:49 UTC, Zach the Mystic wrote:My proposed DIP35 uses 'scope' to enhance DIP25. I don't believe DIP25 is really complete. 'scope' would help it a lot, but that would give more meanings to 'scope' which are potentially in conflict with it just meaning rvalue temp.I think for convenience the function must only be considered unsafe if it does the above. Even returning the 'ref' is safe so long as the *caller* keeps track of what it passes in, according to DIP25.Safety of "ref" is not problem that this DIP tries to solve. It should be solved with DIP25. Now ref is not safe (despite the fact it pretends to) and it still won't be after DIP36 approval, not until issue is addressed in DIP25. No need to mix it.
Apr 10 2013
On Wednesday, 10 April 2013 at 09:31:22 UTC, Dicebot wrote:I would say, if you are going to use a keyword ('scope' in this case) to mean something, and there are other uses of the keyword which are also useful, you have to decide first if there is a conflict, and second how it should be resolved. In my opinion there is a conflict. The only existing definition of 'scope' parameters we have suggets that it means the parameter may not be escaped. It turns out that such a parameter is possibly necessary to successfully seal references in D. If a different proposal wants to use the word to mean something else, then it's important to decide either that two different features require two different parameter attributes (DIP36 understands this, and proposes several alternate possibilities to use), or that each feature can always automatically include the other feature without any problems (possible but see my other responses), or that only one feature is truly important enough to be included in the language, allowing you to disregard the other feature entirely.And how it is relevant to DIP36? It solves specific issue. It provides some hints how other DIP may use new opportunities. It is up to DIP25 and DIP35 to be built on top if this gets accepted first. Or other way around. DIPs are built in context for current language implementation, not some potential other DIPs.Safety of "ref" is not problem that this DIP tries to solve. It should be solved with DIP25. Now ref is not safe (despite the fact it pretends to) and it still won't be after DIP36 approval, not until issue is addressed in DIP25. No need to mix it.My proposed DIP35 uses 'scope' to enhance DIP25. I don't believe DIP25 is really complete. 'scope' would help it a lot, but that would give more meanings to 'scope' which are potentially in conflict with it just meaning rvalue temp.
Apr 10 2013
YES PLEASE!! I've been saying precisely this for years, I'm glad someone took the time to write it down all nice and proposal-like :) On 10 April 2013 03:06, Namespace <rswhite4 googlemail.com> wrote:http://wiki.dlang.org/DIP36
Apr 09 2013
On Wednesday, 10 April 2013 at 05:01:12 UTC, Manu wrote:YES PLEASE!! I've been saying precisely this for years, I'm glad someone took the time to write it down all nice and proposal-like :)When I initially volunteered to help formalize it I had no strong feelings about this proposal but after taking care of all details I really like how it naturally fits into existing D type system, with no ugly hacks or weird behavior changes.
Apr 10 2013
On Tuesday, 9 April 2013 at 17:06:47 UTC, Namespace wrote:http://wiki.dlang.org/DIP36I see no point in adding that much complexity for something that can mostly be automated.
Apr 10 2013
On Wednesday, 10 April 2013 at 11:36:22 UTC, deadalnix wrote:On Tuesday, 9 April 2013 at 17:06:47 UTC, Namespace wrote:Can you explain this a bit more extensively, probably with some sort of counter-proposal? I can't see where complexity comes from, this DIP introduces literally zero special cases.http://wiki.dlang.org/DIP36I see no point in adding that much complexity for something that can mostly be automated.
Apr 10 2013
On Wednesday, 10 April 2013 at 11:37:43 UTC, Dicebot wrote:On Wednesday, 10 April 2013 at 11:36:22 UTC, deadalnix wrote:I think he means that the Compiler could/should decide, if something should passed by ref or by value. But I think that would be far more complex than scope ref/in ref.On Tuesday, 9 April 2013 at 17:06:47 UTC, Namespace wrote:Can you explain this a bit more extensively, probably with some sort of counter-proposal? I can't see where complexity comes from, this DIP introduces literally zero special cases.http://wiki.dlang.org/DIP36I see no point in adding that much complexity for something that can mostly be automated.
Apr 10 2013
On 10 April 2013 22:27, Namespace <rswhite4 googlemail.com> wrote:On Wednesday, 10 April 2013 at 11:37:43 UTC, Dicebot wrote:Right. Yeah, seems more complex for sure. It's also unreliable/unpredictable. Same as with the pure conversation, I really prefer explicit control of things to at least be an option. I really don't want to be guessing about things that I may be depending on.On Wednesday, 10 April 2013 at 11:36:22 UTC, deadalnix wrote:I think he means that the Compiler could/should decide, if something should passed by ref or by value. But I think that would be far more complex than scope ref/in ref.On Tuesday, 9 April 2013 at 17:06:47 UTC, Namespace wrote:Can you explain this a bit more extensively, probably with some sort of counter-proposal? I can't see where complexity comes from, this DIP introduces literally zero special cases.http://wiki.dlang.org/DIP36I see no point in adding that much complexity for something that can mostly be automated.
Apr 10 2013
I hope this proposal gets implemented soon :)
Apr 10 2013
On Wednesday, 10 April 2013 at 12:40:57 UTC, Manu wrote:On 10 April 2013 22:27, Namespace <rswhite4 googlemail.com> wrote:It is certainly more complex on the compiler implementation side. But the ends result can be much better, and any program would benefit from it. Plus, do you know that depending on the ABI, some pass by value are already transformed as pass by ref ? This is already in place in some cases, and have been proven to work well. Back to the DIP, it fail to define how and where lvalue are implicitely created, what are their lifetime, etc . . . Finally, ref and scope would benefit much more from the introduction of lifetime into D than hacking around.On Wednesday, 10 April 2013 at 11:37:43 UTC, Dicebot wrote:Right. Yeah, seems more complex for sure. It's also unreliable/unpredictable. Same as with the pure conversation, I really prefer explicit control of things to at least be an option. I really don't want to be guessing about things that I may be depending on.On Wednesday, 10 April 2013 at 11:36:22 UTC, deadalnix wrote:I think he means that the Compiler could/should decide, if something should passed by ref or by value. But I think that would be far more complex than scope ref/in ref.On Tuesday, 9 April 2013 at 17:06:47 UTC, Namespace wrote:Can you explain this a bit more extensively, probably with some sort of counter-proposal? I can't see where complexity comes from, this DIP introduces literally zero special cases.http://wiki.dlang.org/DIP36I see no point in adding that much complexity for something that can mostly be automated.
Apr 10 2013
On Wednesday, 10 April 2013 at 13:51:59 UTC, deadalnix wrote:It is certainly more complex on the compiler implementation side. But the ends result can be much better, and any program would benefit from it. Plus, do you know that depending on the ABI, some pass by value are already transformed as pass by ref ? This is already in place in some cases, and have been proven to work well. Back to the DIP, it fail to define how and where lvalue are implicitely created, what are their lifetime, etc . . . Finally, ref and scope would benefit much more from the introduction of lifetime into D than hacking around.DIP36 was intentionally tweaked in such way so that compiler is free to do any implementation and swap pass by values with pass by ref if needed - until it preserves the semantics guarantees. Introduction of lifetime is very beneficial but not really relevant to _this_ DIP. If lifetime is well defined, idea of making struct literal lvalues may be discussed, but that is a different story. I don't care about how complex compiler implementation is but behavior needs to be predictable by programmer, no observable magic. Scope happens to have exactly the semantics needed to make stuff work right here and right now, with no relation to possible improvements of ref and rvalue/lvalue system.
Apr 10 2013
On 10 April 2013 21:36, deadalnix <deadalnix gmail.com> wrote:On Tuesday, 9 April 2013 at 17:06:47 UTC, Namespace wrote:Where's the complexity? I find it intuitive and super useful. I personally see this DIP as just fleshing out the functionality of scope that I imagined/assumed from the moment I learned about the scope keyword. I was actually quite surprised to learn it wasn't already like this :)http://wiki.dlang.org/DIP36I see no point in adding that much complexity for something that can mostly be automated.
Apr 10 2013
Isn's it too strict? The following example would not work because you cannot take the address of the parameter. But it would still be nice to have it passed by ref and scoped: struct Item { int data; Item* next; } void printThem(const scope ref Item first) { auto it = &first; while (it) { std.stdio.writeln(*it); it = it.next; } } /Jonas
Apr 11 2013