www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Making AssertError a singleton

reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
Here it is:

https://github.com/dlang/druntime/pull/1710

It relieves code that uses assert from needing the GC. I think all 
Errors should be singletons - multiple objects in that hierarchy 
arguably make no sense. But of course there are many situations out 
there. If this breaks your code, please holler.


Andrei
Dec 12 2016
next sibling parent reply safety0ff <safety0ff.dev gmail.com> writes:
On Monday, 12 December 2016 at 15:51:07 UTC, Andrei Alexandrescu 
wrote:
 But of course there are many situations out there.
Wouldn't it break chained assertion errors?
Dec 12 2016
next sibling parent reply Adam D. Ruppe <destructionator gmail.com> writes:
On Monday, 12 December 2016 at 16:35:22 UTC, safety0ff wrote:
 Wouldn't it break chained assertion errors?
An Error is unrecoverable anyway, if such a case arises it can always just abort the program immediately.
Dec 12 2016
parent reply Dsby <dushibaiyu yahoo.com> writes:
On Monday, 12 December 2016 at 17:57:13 UTC, Adam D. Ruppe wrote:
 On Monday, 12 December 2016 at 16:35:22 UTC, safety0ff wrote:
 Wouldn't it break chained assertion errors?
An Error is unrecoverable anyway, if such a case arises it can always just abort the program immediately.
I think all error can be a singleton, and when has the erro, the program should be killed. But Exception should be new , and in GC. we can use the GC.free to free the memony.
Dec 12 2016
parent Dsby <dushibaiyu yahoo.com> writes:
On Tuesday, 13 December 2016 at 03:07:56 UTC, Dsby wrote:
 On Monday, 12 December 2016 at 17:57:13 UTC, Adam D. Ruppe 
 wrote:
 On Monday, 12 December 2016 at 16:35:22 UTC, safety0ff wrote:
 Wouldn't it break chained assertion errors?
An Error is unrecoverable anyway, if such a case arises it can always just abort the program immediately.
I think all error can be a singleton, and when has the erro, the program should be killed. But Exception should be new , and in GC. we can use the GC.free to free the memony.
Error should not hide and catch. When the erro, the Program should be immediately exited! If the Erro can catch, will has other error form this erro!
Dec 12 2016
prev sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 12/12/2016 11:35 AM, safety0ff wrote:
 On Monday, 12 December 2016 at 15:51:07 UTC, Andrei Alexandrescu wrote:
 But of course there are many situations out there.
Wouldn't it break chained assertion errors?
Once a type in Error's cone gets thrown there is no guarantee of unwinding, hence no guarantee of chaining. -- Andrei
Dec 12 2016
parent reply Brad Roberts via Digitalmars-d <digitalmars-d puremagic.com> writes:
On 12/12/16 12:59 PM, Andrei Alexandrescu via Digitalmars-d wrote:
 On 12/12/2016 11:35 AM, safety0ff wrote:
 On Monday, 12 December 2016 at 15:51:07 UTC, Andrei Alexandrescu wrote:
 But of course there are many situations out there.
Wouldn't it break chained assertion errors?
Once a type in Error's cone gets thrown there is no guarantee of unwinding, hence no guarantee of chaining. -- Andrei
For this to have much meaning, at some-point druntime (for all the various compilers) is going to need to be changed to not unwind. It does, and has all the effects that come from that. What actually happens tends to trump what the documentation claims it's allowed to not do. Of course, then you'll find the fun of all the tests (and probably code) that catch AssertError.
Dec 12 2016
next sibling parent Timon Gehr <timon.gehr gmx.ch> writes:
On 12.12.2016 22:35, Brad Roberts via Digitalmars-d wrote:
 On 12/12/16 12:59 PM, Andrei Alexandrescu via Digitalmars-d wrote:
 On 12/12/2016 11:35 AM, safety0ff wrote:
 On Monday, 12 December 2016 at 15:51:07 UTC, Andrei Alexandrescu wrote:
 But of course there are many situations out there.
Wouldn't it break chained assertion errors?
Once a type in Error's cone gets thrown there is no guarantee of unwinding, hence no guarantee of chaining. -- Andrei
For this to have much meaning, at some-point druntime (for all the various compilers) is going to need to be changed to not unwind. It does, and has all the effects that come from that. What actually happens tends to trump what the documentation claims it's allowed to not do. Of course, then you'll find the fun of all the tests (and probably code) that catch AssertError.
There is a /language feature/ ('in'-contract inheritance) that relies on normal execution after catching AssertError.
Dec 12 2016
prev sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 12/12/16 4:35 PM, Brad Roberts via Digitalmars-d wrote:
 Of course, then you'll find the fun of all the tests (and probably code)
 that catch AssertError.
You can catch AssertError. There's no guarantees dtors have been called during unwinding. -- Andrei
Dec 12 2016
next sibling parent reply Shachar Shemesh <shachar weka.io> writes:
On 13/12/16 02:57, Andrei Alexandrescu wrote:
 You can catch AssertError. There's no guarantees dtors have been called
 during unwinding. -- Andrei
That makes no sense to me, unless you only want to catch it in order to do something right before exiting anyways. Also, please note that not all non-Exception Throwables are terminal for the process. We use a Throwable that is not an Exception in order to force termination of a fiber from outside in a clean way. If proper unwinding is not guaranteed under this condition, we have a problem. Shachar
Dec 12 2016
next sibling parent ketmar <ketmar ketmar.no-ip.org> writes:
On Tuesday, 13 December 2016 at 06:36:47 UTC, Shachar Shemesh 
wrote:
 Also, please note that not all non-Exception Throwables are 
 terminal for the process. We use a Throwable that is not an 
 Exception in order to force termination of a fiber from outside 
 in a clean way. If proper unwinding is not guaranteed under 
 this condition, we have a problem.
yes, we have a big problem.
Dec 13 2016
prev sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Tuesday, 13 December 2016 at 06:36:47 UTC, Shachar Shemesh 
wrote:
 On 13/12/16 02:57, Andrei Alexandrescu wrote:
 You can catch AssertError. There's no guarantees dtors have 
 been called
 during unwinding. -- Andrei
That makes no sense to me, unless you only want to catch it in order to do something right before exiting anyways. Also, please note that not all non-Exception Throwables are terminal for the process. We use a Throwable that is not an Exception in order to force termination of a fiber from outside in a clean way. If proper unwinding is not guaranteed under this condition, we have a problem.
_Errors_ do not guarantee that the stack is unwound properly. It's been Walter's stance for years that it's bad for the program to do any cleanup when an Error is thrown and that it's not guaranteed that the cleanup happens. However, someone working on the exception stuff at one point _did_ make it so that the cleanup is always done (which Walter doesn't like but hasn't fixed). So, for code that doesn't use nothrow, Errors currently result in full cleanup but it's not actually, officially guaranteed that it will, and it could change in the future (though that would be a problem in the case of AssertError for contracts and unittest blocks). For nothrow code, it _is_ currently the case that full cleanup doesn't necessarily happen when an Error is thrown, because the compiler doesn't emit the exception stuff for nothrow functions. As for Throwable, I think that it's mostly ignored and not really thought about in discussions like this. Most everything is either an Exception or an Error. So, I don't know what Walter would say about it. However, Throwables do _not_ work with nothrow. This function void func() nothrow { throw new Throwable("blah"); } will fail to compile. That being the case, it would seem that Throwables are treated more like Exceptions than Errors, which implies that you're fine, but Walter would have to weigh in to be sure. Part of the question probably comes down to when it's valid to derive from Throwable directly, which it rarely is. But I don't think that it would be hard to convince Walter that you have a valid use case that requires that Throwable clean up correctly and that only Errors should not do proper cleanup - particularly since the whole reason that Errors don't guarantee full cleanup is because it's an unrecoverable error condition, and if a Throwable is an unrecoverable error condition, it really should be derived from Error, not Throwable. - Jonathan M Davis
Dec 13 2016
prev sibling parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 13.12.2016 01:57, Andrei Alexandrescu wrote:
 On 12/12/16 4:35 PM, Brad Roberts via Digitalmars-d wrote:
 Of course, then you'll find the fun of all the tests (and probably code)
 that catch AssertError.
You can catch AssertError. There's no guarantees dtors have been called during unwinding. -- Andrei
If 'in'-contracts are not allowed to corrupt the program state, then I don't really see how implementations will be able to not call dtors.
Dec 13 2016
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 12/13/2016 11:39 AM, Timon Gehr wrote:
 On 13.12.2016 01:57, Andrei Alexandrescu wrote:
 On 12/12/16 4:35 PM, Brad Roberts via Digitalmars-d wrote:
 Of course, then you'll find the fun of all the tests (and probably code)
 that catch AssertError.
You can catch AssertError. There's no guarantees dtors have been called during unwinding. -- Andrei
If 'in'-contracts are not allowed to corrupt the program state, then I don't really see how implementations will be able to not call dtors.
One way to accomplish that is to have assert work differently when called from within contracts. (I'm not sure whether that's currently done that way.) -- Andrei
Dec 13 2016
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 13.12.2016 17:47, Andrei Alexandrescu wrote:
 On 12/13/2016 11:39 AM, Timon Gehr wrote:
 On 13.12.2016 01:57, Andrei Alexandrescu wrote:
 On 12/12/16 4:35 PM, Brad Roberts via Digitalmars-d wrote:
 Of course, then you'll find the fun of all the tests (and probably
 code)
 that catch AssertError.
You can catch AssertError. There's no guarantees dtors have been called during unwinding. -- Andrei
If 'in'-contracts are not allowed to corrupt the program state, then I don't really see how implementations will be able to not call dtors.
One way to accomplish that is to have assert work differently when called from within contracts. (I'm not sure whether that's currently done that way.) -- Andrei
I assume you don't refer to passing along a runtime flag whether execution is currently in a contract and then selectively disable calling of dtors. So I think you are suggesting a breaking change in language semantics: void myAssert(bool x){ // this function could be in a different compilation unit assert(x); } class C{ void foo(int a)in{ myAssert(a>0); }body{ } } class D:C{ override void foo(int a)in{ myAssert(a<0); }body{ } } void main(){ D d = new D; d.foo(1); d.foo(-1); } (Using 'assert' for specifying contracts is a questionable design decision anyway: it is not possible to distinguish implementation bugs in the contract code and functions it calls from contract violations.)
Dec 13 2016
parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 12/13/2016 12:18 PM, Timon Gehr wrote:
 I assume you don't refer to passing along a runtime flag whether
 execution is currently in a contract and then selectively disable
 calling of dtors.
No, something simpler than that - nontransitive. Consider: T fun(R range) in { assert(range.front == 42); } body { ... } Here, the assert keyword present straight in the contract has a distinct meaning from the assert present transitively in code invoked by the contract. If the assert in the contract fails, that's the contract not passing. Assume Range.front() has e.g. assert(!empty) inside, that's a different kind of failure - in this case it may arguably be a bug in the contract definition.
 So I think you are suggesting a breaking change in language semantics:

 void myAssert(bool x){
     // this function could be in a different compilation unit
     assert(x);
 }

 class C{
     void foo(int a)in{
         myAssert(a>0);
     }body{

     }
 }
 class D:C{
     override void foo(int a)in{
         myAssert(a<0);
     }body{

     }
 }

 void main(){
     D d = new D;
     d.foo(1);
     d.foo(-1);
 }
Yah, this would have to do with user code not using the assert keyword inside the contract.
 (Using 'assert' for specifying contracts is a questionable design
 decision anyway: it is not possible to distinguish implementation bugs
 in the contract code and functions it calls from contract violations.)
I agree it's odd. I've always thought of asserts in contracts as "cheap" conditionals that return false if not met. Asserts (and other Throwables) thrown from code transitively invoked by the contract are a different business. The saving grace here is that assert is a keyword as opposed to an ordinary function :o). I don't know how contracts are currently implemented. Thanks for raising this discussion about a matter that's been buzzing in my mind for a while. Andrei
Dec 13 2016
prev sibling next sibling parent reply Guillaume Boucher <guillaume.boucher.d gmail.com> writes:
On Monday, 12 December 2016 at 15:51:07 UTC, Andrei Alexandrescu 
wrote:
 I think all Errors should be singletons - multiple objects in 
 that hierarchy arguably make no sense.
With that logic, why does Throwable have the field "next"?
Dec 12 2016
parent Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 12/12/2016 12:43 PM, Guillaume Boucher wrote:
 On Monday, 12 December 2016 at 15:51:07 UTC, Andrei Alexandrescu wrote:
 I think all Errors should be singletons - multiple objects in that
 hierarchy arguably make no sense.
With that logic, why does Throwable have the field "next"?
Probably only Exception should. -- Andrei
Dec 12 2016
prev sibling next sibling parent reply Shachar Shemesh <shachar weka.io> writes:
On 12/12/16 17:51, Andrei Alexandrescu wrote:
 Here it is:

 https://github.com/dlang/druntime/pull/1710

 It relieves code that uses assert from needing the GC. I think all
 Errors should be singletons - multiple objects in that hierarchy
 arguably make no sense. But of course there are many situations out
 there. If this breaks your code, please holler.


 Andrei
As you may know, Weka has a huge GC aversion. Despite that fact, I fail to see the improvement such a change would bring. The only situation under which using the GC is not harmful is when the entire process is about to go kaboom anyways. Now, if you'd make regular Exceptions GC free.... Shachar
Dec 12 2016
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 12/12/2016 02:54 PM, Shachar Shemesh wrote:
 On 12/12/16 17:51, Andrei Alexandrescu wrote:
 Here it is:

 https://github.com/dlang/druntime/pull/1710

 It relieves code that uses assert from needing the GC. I think all
 Errors should be singletons - multiple objects in that hierarchy
 arguably make no sense. But of course there are many situations out
 there. If this breaks your code, please holler.


 Andrei
As you may know, Weka has a huge GC aversion. Despite that fact, I fail to see the improvement such a change would bring.
Why am I not surprised :o).
 The only situation
 under which using the GC is not harmful is when the entire process is
 about to go kaboom anyways.
You get to use assert without needing to link in the GC.
 Now, if you'd make regular Exceptions GC free....
That will come too. Andrei
Dec 12 2016
next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Monday, 12 December 2016 at 21:02:11 UTC, Andrei Alexandrescu 
wrote:
 On 12/12/2016 02:54 PM, Shachar Shemesh wrote:
 Now, if you'd make regular Exceptions GC free....
That will come too.
Then why bother making Errors singletons in order to avoid the GC? The problem you're trying to fix with this singleton suggestion would then be fixed anyway. - Jonathan M Davis
Dec 12 2016
prev sibling next sibling parent reply Shachar Shemesh <shachar weka.io> writes:
On 12/12/16 23:02, Andrei Alexandrescu wrote:
 On 12/12/2016 02:54 PM, Shachar Shemesh wrote:
 On 12/12/16 17:51, Andrei Alexandrescu wrote:
 Here it is:

 https://github.com/dlang/druntime/pull/1710

 It relieves code that uses assert from needing the GC. I think all
 Errors should be singletons - multiple objects in that hierarchy
 arguably make no sense. But of course there are many situations out
 there. If this breaks your code, please holler.


 Andrei
As you may know, Weka has a huge GC aversion. Despite that fact, I fail to see the improvement such a change would bring.
Why am I not surprised :o).
I'm not sure what to make of that comment.
 The only situation
 under which using the GC is not harmful is when the entire process is
 about to go kaboom anyways.
You get to use assert without needing to link in the GC.
int func(int num1, int num2, int num3) body { int result; scope(exit) assert(result>20); assert(num1>5); result += num1; assert(num2>10); result += num2; assert(num3>5); result += num3; // Some more work return result; } Yes, I know, there multiple ways in which this function can be written much better, and in all of them the double assert won't happen. Such a case may actually happen, however, particularly if the first assert to happen happens in a sub-function. What is supposed to happen, after your proposed change, if I call "func(1, 2, 3)"? Shachar
Dec 12 2016
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 12/13/2016 01:23 AM, Shachar Shemesh wrote:
 On 12/12/16 23:02, Andrei Alexandrescu wrote:
 Why am I not surprised :o).
I'm not sure what to make of that comment.
Just jesting, and not always in style. Apologies. Let me restate the factors at play here; admittedly the matter is a bit fuzzily defined at the moment: * A number of D libraries (Ilya's Mir being a prominent one) aim to offer a C-level API that is shunning a relatively heavy runtime support library. Mir makes use of D's cool compile-time introspection and such, but avoids things like module information and the garbage collector. A good way to go about it is compile with -betterC and not link druntime. * Druntime has a simple charter: isolate the platform-dependent things needed to get a D implementation going. However, its design predates a bunch of great things done with templates. This makes for druntime to miss many opportunities to be smaller, more modular, and faster. * People have noticed that certain simple uses of D trigger calls into druntime that are not quite justified. For example, assigning an array of int to another array of int issues a call into a function that uses dynamic introspection (!) to copy any array into any other array. A template present in object.d would trivially do this using introspection to boil down to memcpy. * Generally reducing the footprint of druntime support amenities for performing something with D is a good thing. Hence, assert() not requiring the GC to be linked is good because it would allow folks who don't link the GC at all to still use assert without needing to redefine it. The community has been aware for a while that there's some good opportunity to use modern techniques such as lowering and templates to make druntime smaller, more modular, and actually more self-effacing. Ilya brought this point strongly recently with a good use case, and https://github.com/dlang/druntime/pull/1710 is a step in that direction. Andrei
Dec 13 2016
parent reply Stefan Koch <uplink.coder googlemail.com> writes:
On Tuesday, 13 December 2016 at 18:52:05 UTC, Andrei Alexandrescu 
wrote:
 * People have noticed that certain simple uses of D trigger 
 calls into druntime that are not quite justified. For example, 
 assigning an array of int to another array of int issues a call 
 into a function that uses dynamic introspection (!) to copy any 
 array into any other array. A template present in object.d 
 would trivially do this using introspection to boil down to 
 memcpy.
I am in favor of templatizing more of druntime. But please keep those templates simple. I have noticed severe code-bloat at ctfe, and worse when ctfe-codegen miscompiles those templates, there in way to know why! It will work fine if the bodys are - very simple (C-subset of D) - use static if moderately - please minimize the use of constraints they are wired when it comes to ctfe interaction
Dec 13 2016
parent Stefan Koch <uplink.coder googlemail.com> writes:
On Tuesday, 13 December 2016 at 22:15:13 UTC, Stefan Koch wrote:
 I have noticed severe code-bloat at ctfe, and worse when 
 ctfe-codegen miscompiles those templates,
 there in way to know why!
Was meant to say. there is no way to know why.
Dec 13 2016
prev sibling parent reply Guillaume Piolat <first.last gmail.com> writes:
On Monday, 12 December 2016 at 21:02:11 UTC, Andrei Alexandrescu 
wrote:
 That will come too.


 Andrei
Great teaser :) For reference, here is how I currently do this: - make Object.~this() nogc with a cast - throw emplaced exceptions in malloc'd memory - release them explicitely at catch time This probably breaks chaining so maybe RC objects are needed first, dunno.
Dec 13 2016
parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Tuesday, 13 December 2016 at 11:39:16 UTC, Guillaume Piolat 
wrote:
 On Monday, 12 December 2016 at 21:02:11 UTC, Andrei 
 Alexandrescu wrote:
 That will come too.


 Andrei
Great teaser :) For reference, here is how I currently do this: - make Object.~this() nogc with a cast - throw emplaced exceptions in malloc'd memory - release them explicitely at catch time This probably breaks chaining so maybe RC objects are needed first, dunno.
It also only works if you're the one controlling all of your code, because D code in general expects exceptions to be GC-allocated and isn't going to do anything to free it. So, it works under certain circumstances but not in general. - Jonathan M Davis
Dec 13 2016
prev sibling next sibling parent Shachar Shemesh <shachar weka.io> writes:
On 12/12/16 17:51, Andrei Alexandrescu wrote:
 Here it is:

 https://github.com/dlang/druntime/pull/1710

 It relieves code that uses assert from needing the GC. I think all
 Errors should be singletons - multiple objects in that hierarchy
 arguably make no sense. But of course there are many situations out
 there. If this breaks your code, please holler.


 Andrei
I'll just add that we're not using AssertError anyways. We found that the various scope(failure) and scope(exit) that run in such cases significantly detract from the ability to debug what actually happened. Our assert immediately terminates the process. Shachar
Dec 12 2016
prev sibling parent reply Jonathan M Davis <jmdavisProg gmx.com> writes:
On Monday, 12 December 2016 at 15:51:07 UTC, Andrei Alexandrescu 
wrote:
 Here it is:

 https://github.com/dlang/druntime/pull/1710

 It relieves code that uses assert from needing the GC. I think 
 all Errors should be singletons - multiple objects in that 
 hierarchy arguably make no sense. But of course there are many 
 situations out there. If this breaks your code, please holler.
I don't know if that would actually work with polymorphic contracts in classes. It also could be problematic with unit tests - especially unit tests that catch AssertErrors (e.g. if someone wants to test the contracts). I also fail to see how this fixes much of anything. If the issue is avoiding the GC, it doesn't matter if the program is being killed. If the issue is avoiding even linking in the GC, doesn't that mean that druntime isn't being used (in which case, doing this in druntime is pointless)? So, I don't see how such a change would matter for either scenario, and I don't know why else it would be of any value. And if we fix it so that exceptions don't need the GC (which is arguably needed for nogc to be widely used), then this whole problem goes away anyway. So, I'm inclined to argue that we just fix _that_ problem and not worry about the fact that assert currently triggers the GC on failure. - Jonathan M Davis
Dec 12 2016
next sibling parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 12/12/16 11:07 PM, Jonathan M Davis wrote:
 On Monday, 12 December 2016 at 15:51:07 UTC, Andrei Alexandrescu wrote:
 Here it is:

 https://github.com/dlang/druntime/pull/1710

 It relieves code that uses assert from needing the GC. I think all
 Errors should be singletons - multiple objects in that hierarchy
 arguably make no sense. But of course there are many situations out
 there. If this breaks your code, please holler.
I don't know if that would actually work with polymorphic contracts in classes.
How do you mean that? Do you have an example in mind?
 It also could be problematic with unit tests - especially unit
 tests that catch AssertErrors (e.g. if someone wants to test the
 contracts).
What kind of problems would it create?
 I also fail to see how this fixes much of anything. If the issue is
 avoiding the GC, it doesn't matter if the program is being killed. If
 the issue is avoiding even linking in the GC, doesn't that mean that
 druntime isn't being used (in which case, doing this in druntime is
 pointless)? So, I don't see how such a change would matter for either
 scenario, and I don't know why else it would be of any value.
Is reducing dependencies for core constructs a good thing?
 And if we fix it so that exceptions don't need the GC (which is arguably
 needed for  nogc to be widely used), then this whole problem goes away
 anyway. So, I'm inclined to argue that we just fix _that_ problem and
 not worry about the fact that assert currently triggers the GC on failure.
I agree the perfect system would fix everything - problem is we don't have it yet. The per-thread singleton is a step forward (which at some point we should probably make publicly available). Andrei
Dec 12 2016
next sibling parent reply Shachar Shemesh <shachar weka.io> writes:
On 13/12/16 06:45, Andrei Alexandrescu wrote:
 I agree the perfect system would fix everything - problem is we don't
 have it yet. The per-thread singleton is a step forward (which at some
 point we should probably make publicly available).


 Andrei
If it's not going to be needed once exceptions are GC free, and unlinking GC from phobos is not likely to happen until that happens, can you explain how is it a step forward? To me, it seems like it isn't heading where we're going and it doesn't provide any extra benefit for the interim time. Shachar
Dec 12 2016
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 12/13/2016 01:34 AM, Shachar Shemesh wrote:
 unlinking GC from phobos is not likely to happen until that happens
You can avoid linking druntime today with -betterC. -- Andrei
Dec 13 2016
parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Tuesday, 13 December 2016 at 13:59:13 UTC, Andrei Alexandrescu 
wrote:
 On 12/13/2016 01:34 AM, Shachar Shemesh wrote:
 unlinking GC from phobos is not likely to happen until that 
 happens
You can avoid linking druntime today with -betterC. -- Andrei
You can avoid linking druntime _now_. And betterC is so extreme in what it's trying to do that it would arguably better off with an entirely different build of druntime if they're willing to use druntime at all. If you really want to support betterC with druntime, I would suggest using version blocks for the areas that the betterC folks can't afford and then have a betterC build of druntime without them. And if something needs an alternate implementation for that, then it can have it. In an environment like that AssertErrors could probably even just be malloced and thrown without caring about catching them, because the program is about to die anyway. If they still want AssertErrors with contracts and unit tests though, then we really need an RC solution with malloc and not the GC or singletons. Regardless, I really don't want to see functionality removed from druntime or Phobos because of betterC. I'm fine with supporting betterC if it's not impacting normal D stuff, but the position of betterC is so extreme that it could very quickly negatively impact normal D if we start catering to it. - Jonathan M Davis
Dec 13 2016
prev sibling parent reply Jonathan M Davis <jmdavisProg gmx.com> writes:
On Tuesday, 13 December 2016 at 04:45:35 UTC, Andrei Alexandrescu 
wrote:
 On 12/12/16 11:07 PM, Jonathan M Davis wrote:
 On Monday, 12 December 2016 at 15:51:07 UTC, Andrei 
 Alexandrescu wrote:
 Here it is:

 https://github.com/dlang/druntime/pull/1710

 It relieves code that uses assert from needing the GC. I 
 think all
 Errors should be singletons - multiple objects in that 
 hierarchy
 arguably make no sense. But of course there are many 
 situations out
 there. If this breaks your code, please holler.
I don't know if that would actually work with polymorphic contracts in classes.
How do you mean that? Do you have an example in mind?
I mean that with virtual functions, in contracts get ||ed and out contracts get &&ed. Since that involves assertions, unless the compiler is doing something special there with assert, that involves throwing multiple AssertErrors and catching them. Depending on how that's implemented, having a singleton for AssertError would break that. If so, I expect that it's fixable, but simply turning AssertError into a singleton without verifying how that would affects contracts on virtual functions seems like a bad idea.
 It also could be problematic with unit tests - especially unit
 tests that catch AssertErrors (e.g. if someone wants to test 
 the
 contracts).
What kind of problems would it create?
Well, if anyone is catching AssertErrors in unit tests, then they'll no longer be getting multiple of them. For some stuff, it wouldn't matter, but for other stuff it would break it. For instance, while the default test runner stops on the first failure in a unittest block, others are going to run them all and then print out the failures, and if AssertError is a singelton, then all of the AssertErrors that were stored to print at the end would then be the same AssertError and would print the same thing, defeating the purpose of the alternate test runner.
 Is reducing dependencies for core constructs a good thing?
It is when it reduces functionality, which this does. It puts unnecessary restrictions on AssertError which are of zero benefit for the vast majority of D programs.
 And if we fix it so that exceptions don't need the GC (which 
 is arguably
 needed for  nogc to be widely used), then this whole problem 
 goes away
 anyway. So, I'm inclined to argue that we just fix _that_ 
 problem and
 not worry about the fact that assert currently triggers the GC 
 on failure.
I agree the perfect system would fix everything - problem is we don't have it yet. The per-thread singleton is a step forward (which at some point we should probably make publicly available).
We _need_ to fix the fact that exceptions require the GC, or nogc is utterly useless for large portions of D code simply because of the exceptions, which will make it much harder to use D without the GC. If we fix it so that exceptions don't need the GC, then this problem goes away, and these changes are just an unnecessary complication in druntime. - Jonathan M Davis
Dec 13 2016
parent reply Andrei Alexandrescu <SeeWebsiteForEmail erdani.org> writes:
On 12/13/2016 05:05 PM, Jonathan M Davis wrote:
 I mean that with virtual functions, in contracts get ||ed and out
 contracts get &&ed. Since that involves assertions, unless the compiler
 is doing something special there with assert, that involves throwing
 multiple AssertErrors and catching them. Depending on how that's
 implemented, having a singleton for AssertError would break that. If so,
 I expect that it's fixable, but simply turning AssertError into a
 singleton without verifying how that would affects contracts on virtual
 functions seems like a bad idea.
Yeah, that's the kind of feedback I was hoping for. Thanks. Recall that all AssertError instances are equivalent up to file and line. It is possible that that causes issues but the likelihood is low. Overally I'm not too worried about this because contract handling is also under the control of the compiler/runtime so it doesn't break client code.
 It also could be problematic with unit tests - especially unit
 tests that catch AssertErrors (e.g. if someone wants to test the
 contracts).
What kind of problems would it create?
Well, if anyone is catching AssertErrors in unit tests, then they'll no longer be getting multiple of them. For some stuff, it wouldn't matter, but for other stuff it would break it. For instance, while the default test runner stops on the first failure in a unittest block, others are going to run them all and then print out the failures, and if AssertError is a singelton, then all of the AssertErrors that were stored to print at the end would then be the same AssertError and would print the same thing, defeating the purpose of the alternate test runner.
Would be quite cool if all failed assertions showed the same file and line, eh? :o) I'm actually of a mind to push this in the language specification - Error objects are not guaranteed to be distinct. Errors already have a number of concessions and shouldn't be used naively.
 Is reducing dependencies for core constructs a good thing?
It is when it reduces functionality, which this does. It puts unnecessary restrictions on AssertError which are of zero benefit for the vast majority of D programs.
Probably a negation was meant somewhere.
 And if we fix it so that exceptions don't need the GC (which is arguably
 needed for  nogc to be widely used), then this whole problem goes away
 anyway. So, I'm inclined to argue that we just fix _that_ problem and
 not worry about the fact that assert currently triggers the GC on
 failure.
I agree the perfect system would fix everything - problem is we don't have it yet. The per-thread singleton is a step forward (which at some point we should probably make publicly available).
We _need_ to fix the fact that exceptions require the GC, or nogc is utterly useless for large portions of D code simply because of the exceptions, which will make it much harder to use D without the GC. If we fix it so that exceptions don't need the GC, then this problem goes away, and these changes are just an unnecessary complication in druntime.
This kind of argument I honestly don't put too much in the balance because it promotes paralysis of analysis. Right now I don't know what to do to make all exceptions not use GC. I do know what to do to avoid using the GC in assert, and in my opinion at a negligible cost in amenities. We can't afford to refuse to take a step just because the journey is long. Andrei
Dec 13 2016
parent Jonathan M Davis <jmdavisProg gmx.com> writes:
On Tuesday, 13 December 2016 at 22:47:55 UTC, Andrei Alexandrescu 
wrote:
 On 12/13/2016 05:05 PM, Jonathan M Davis wrote:
 Recall that all AssertError instances are equivalent up to file 
 and line.
They also have a message. AssertErrors aren't any more the same as each other than any other exception type.
 Would be quite cool if all failed assertions showed the same 
 file and line, eh? :o)
LOL. Not so much, no.
 I'm actually of a mind to push this in the language 
 specification - Error objects are not guaranteed to be 
 distinct. Errors already have a number of concessions and 
 shouldn't be used naively.
I might agree if we weren't talking about AssertErrors, but assertions are used in contracts and unit tests where they do not kill the program and potentially need mupltiple instances to work properly with anyone who wants to show all failures rather than just one per module. Also, aside from the fact that nothrow let's you throw Errors, there's really nothing special about Errors at this point. nothrow does have the side effect that you don't always get full stack cleanup with Errors (and Walter would like that to be the case for cleanup with Errors in general), but the Error objects themselves are not special, and not having full cleanup with AssertErrors with contracts and unit tests would be a big problem for some people. There are people who test their contracts and other Errors with unit tests to make sure that they fail when and how they're supposed to. Either skipping the cleanup in that case or making Errors singletons would break such code, and I don't know how anyone could test their contracts if your proposal went through.
 Right now I don't know what to do to make all exceptions not 
 use GC.
Wouldn't the reference counting solution that you and Walter agreed needed to be done make it possible to fix it so that exceptions don't have to use the GC?
 I do know what to do to avoid using the GC in assert, and in my 
 opinion at a negligible cost in amenities. We can't afford to 
 refuse to take a step just because the journey is long.
Well, this seems to only be of benefit to the folks trying to use betterC, and it's going to cause problems for D programmers that don't care about betterC at all. Given the kind of restrictions and feature-reduction that the folks using betterC are looking for, it seems to me to make a lot more sense to take advantage of version statements so that the betterC folks can have a stripped down build of druntime without negatively impacting D's features for the rest of us. - Jonatan M Davis
Dec 13 2016
prev sibling parent reply Jacob Carlborg <doob me.com> writes:
On 2016-12-13 05:07, Jonathan M Davis wrote:

 It also could be problematic with unit tests - especially unit
 tests that catch AssertErrors (e.g. if someone wants to test the
 contracts).
I also expect all unit test frameworks that are slightly more advanced then the built-in we have now would like to catch AssertErrors. -- /Jacob Carlborg
Dec 12 2016
parent Atila Neves <atila.neves gmail.com> writes:
On Tuesday, 13 December 2016 at 07:49:59 UTC, Jacob Carlborg 
wrote:
 On 2016-12-13 05:07, Jonathan M Davis wrote:

 It also could be problematic with unit tests - especially unit
 tests that catch AssertErrors (e.g. if someone wants to test 
 the
 contracts).
I also expect all unit test frameworks that are slightly more advanced then the built-in we have now would like to catch AssertErrors.
Well, they _have_ to unless they want to completely ignore existing unittest blocks. But I don't see how making them a singleton would stop that. Atila
Dec 13 2016