Make assumeSafeAppend nothrow#553
Make assumeSafeAppend nothrow#553MartinNowak merged 1 commit intodlang:masterfrom monarchdodra:reserveCapAppend
Conversation
|
I'd like to see the implementation of |
|
Hum... I can was able to "cleanly" tag those two extern (C) void* gc_addrOf( in void* p );
extern (C) size_t gc_sizeOf( in void* p );
extern (C) BlkInfo gc_query( in void* p );But I wasn't able to find their source, so I'm no sure if I can tag them. Even if I could, the keyword src/rt/lifetime.d(246): Error: '_d_monitorenter' is not nothrow
src/rt/lifetime.d(246): Error: '_d_monitorexit' is not nothrowAnd I don't know how to fix that. So... yeah... I wasn't actually able to mark them as nothrow... |
|
Those are in
These functions are defined in |
|
Maybe we should close this pull? |
The problem I think we have is that As long as |
|
Hey, can you make sense of this? extern(C) void _d_arrayshrinkfit(const TypeInfo ti, void[] arr) nothrow
{
// note, we do not care about shared. We are setting the length no matter
// what, so no lock is required.
...
__setArrayAllocLength(info, (arr.ptr - info.base) + cursize, false); //false represents "isshared"
}Is this comment and implementation accurate? If so, then we can statically split |
|
@dawgfoto: What do you think about my above comment. I could statically prove that An alternative would be to split each and every function in That would be a much more complex development though, and would really just be a workaround to the whole "druntime has no templates" problem. So... my conclusion (IMO), is that we should just mark |
|
I think the nothrow attributes inside the runtime are not necessary. When you are under the hood, you have to simply assume things like this. It's why allocating memory is pure and nothrow, even though it's not really. One might put a @MartinNowak any comments? How does one get the autotester to rerun? |
|
We make mistakes with attributes on high level functions, so I'd like to have more compiler verification in general. |
In this case, it's not so much that we can't verify, in fact we can verify that it MAY throw. But the throw would be due to a condition we know will not happen (the lock throwing) unless the system is in an invalid state. Likewise, we can allow new int[5] to be pure, even though we KNOW it modifies global state. These are primitives for which we cannot rely on compiler scrutiny. Marking as much as possible nothrow would be nice, but it would stop at some point. |
|
@schveiguy : I should also mark the function as pure, correct.
I could, yes. And document in the code why an exception can't be thrown when it calls |
Then it should throw an Error, right? So maybe the longterm solution is to make Monitor.lock/unlock nothrow. |
|
It's just important that we remain correct with those annotations, otherwise they become useless.
Then |
The basic idea is that since
I have no idea if this is correct or not. I think its not necessary here anyways. In any case @MartinNowak , if you take a quick look at #632, I "proved" it is nothrow. The code is ugly, so I wouldn't pull it, but it is correct. |
Why? It's changing globally visible state (array capacity) and the blkinfo cache is altered too.
Fine, it would still be useful to refactor |
For the same reasons that appending to an array is pure (provided no postblit): GC memory management and allocations are considered (weakly) pure. And besides, the function does take a pointer to the array, which gives it the right to modify it (albeit in an underhanded global manner). Am I completely mistaken? |
|
To give some background, assumeSafeAppend does not alter global state. It modifies a field contained within the array memory block. However, to determine the extents of the block the pointer refers to, it must use the heap's metadata to look up the block information for that pointer. I think in all cases, looking up block info should be nothrow, pure, and safe, even if the underlying functions are not provably so. Otherwise, critical components of the language cannot function properly. If they can be fully marked that way, fine, but only if the requirements on marking the underlying functions don't affect other code. In the case of altering information on |
|
Auto-merge toggled on |
Make assumeSafeAppend nothrow
|
TYVM @schveiguy for looking into this pull, and backing. TYVM @MartinNowak for reviewing and pulling into drunime. |
|
I'd still like to encourage anyone to put those kind of attribute decision on a more formal basis so that we preserve the ability to use them for compiler optimizations. |
|
@MartinNowak I agree, I think we should push down as far as possible the actual attributes, and create a layer where things aren't provably pure/safe/nothrow, but must be labeled as such in order to get useful work done. Ideally, these would be deep inside druntime. Any real decision on where this should be should really be discussed with the community. |
|
@MartinNowak , @schveiguy there was apparently a problem, that when used with immutable types, See here: dlang/phobos#2025 This might be a problem. Strongly pure functions can be optimized out if we don't use the return value, especially if marked nothrow to boot... |
Allocating memory via Some functions can be legitimatedly converted to nothrow if the exceptions they throw are |
This makes
assumeSafeAppendnothrow. AFAIK, it can't throw, so...